To get full source code for this tutorial, click here.
To check the live demo for this tutorial, click here.
In this post, we will implement a Undo/Redo operation for zooming to Previous/Next extent and zoom in OpenLayers. Using this functionality, we will able to navigate to previous or next extent. This operation is similar to the functionality of undo/redo of any text editor where you can undo or redo any changes. In our case, it is our map where we are zooming to previous or next extent and zoom of map.
Before moving forward, we need to understand how undo/redo functionality for anything works at basic level. The following image will make it clear to you. The data structure for this operation used is stack. So, in any undo redo operation, the changes made by user are stored in stack. When user click on undo redo button, the stack is looked for last changes and user is provided with the changes based on either undo or redo operation.
In standard Undo Redo functionality, if you do any changes between undo/redo operation, all the redo changes from that point on stack are deleted and new changes are added to the top of stack. For example, you performed action1, action2 and so on. They are stored in stack as shown in below image. Suppose, you have undone your actions and you are at action6. In that state, you can undo your actions which are below it and you can redo actions which are above it. If you do any changes at that point, all the actions above action6 will be deleted and new changes will added on top of stack.
Let’s code Undo Redo functionality for navigating to Previous/Next Extent. We will use a moveend map event defined at line number 6. This event will be called when you will pan/zoom the map. Once the panning/zooming operation is done, this event will be called. We will use this event to capture the extent and zoom level of map and store this information on nav_history variable. At line number 13, we are calculating the extent and zoom of the map and storing them to nav_history. To perform undo redo operation for map, we are going through nav_history object and then performing undo redo operations. We are tracking undo redo operation using size variable.
One thing to note here is we don’t want our moveend event to run when doing undo/redo operation. Because during undo/redo operation, our map is panning/zooming which can trigger this event and can disturb the existing functionality. To deal with this situation, we will use undo_redo flag which will prevent moveend event from triggering during undo/redo. if undo_redo is false, only then moveend event will run. During undo/redo operation, we will set undo_redo to true temporarily. See line number 26 and 40.
The other part of the code is self explainatory.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 |
var nav_history=[]; var size=-1; var undo_redo=false; //Add event listener to map on move end. map.on('moveend', function(){ if(undo_redo===false){ if(size<nav_history.length-1){ for(var i=nav_history.length-1;i>size;i--){ console.log(nav_history.pop()); } } nav_history.push({extent:map.getView().calculateExtent(map.getSize()),size:map.getSize(), zoom:map.getView().getZoom()}); size=size+1; console.log(nav_history); } }); //Function for undo pevious extent and zoom let undoClick = () => { if(size>0){ undo_redo=true; map.getView().fit(nav_history[size-1].extent, nav_history[size-1].size); map.getView().setZoom(nav_history[size-1].zoom); setTimeout(function () { undo_redo = false; }, 360); size=size-1; console.log(size); } } //Function for redo next extent and zoom let redoClick = () => { if(size<nav_history.length-1){ undo_redo=true; map.getView().fit(nav_history[size+1].extent, nav_history[size+1].size); map.getView().setZoom(nav_history[size+1].zoom); setTimeout(function () { undo_redo = false; }, 360); size=size+1; console.log(size); } } |
I hope this tutorial will create a good foundation for you.
If you want tutorials on another GIS topic or you have any queries, please send an email at contact@spatial-dev.guru