├── LICENSE ├── Leaflet.Marker.Parallax.js ├── README.md └── examples ├── cloud.png ├── clouds.html ├── floating-labels.html ├── leaflet-parallaxmarker-demo-clouds-small.gif ├── leaflet.parallaxmarker.demo.floatinglabels.gif ├── leaflet.parallaxmarker.demo.minimumexample.gif ├── minimum-example.html └── sun.png /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2016 Dag Jomar Mersland 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Leaflet.Marker.Parallax.js: -------------------------------------------------------------------------------- 1 | L.Marker.Parallax = L.Marker.extend({ 2 | 3 | _initIcon: function () { 4 | L.Marker.prototype._initIcon.call(this); 5 | var anchor = this.options.icon.options.iconAnchor ? L.point(this.options.icon.options.iconAnchor) : L.point([0,0]); 6 | this.options.icon._originalOffset = L.point(-anchor.x, -anchor.y); 7 | 8 | }, 9 | onAdd: function (e) { 10 | L.Marker.prototype.onAdd.call(this, e); 11 | 12 | this._map.on('move', this._onMapMove, this); 13 | this._map.on('zoomstart', this._onZoomStart, this); 14 | 15 | this._onMapMove(); 16 | }, 17 | 18 | onRemove: function (e) { 19 | 20 | this._map.off('move', this._onMapMove, this); 21 | this._map.off('zoomstart', this._onZoomStart, this); 22 | L.Marker.prototype.onRemove.call(this, e); 23 | 24 | }, 25 | 26 | _onMapMove : function(e){ 27 | var offsets = this._calculateOffsetFromOrigin(); 28 | 29 | if(this._icon){ 30 | this._updateIconOffset(offsets.centerOffset); 31 | } 32 | }, 33 | 34 | _onZoomStart : function(e){ 35 | var tempLatLng = this._calcLatLngFromOffset(); 36 | var origLatLng = this.getLatLng(); 37 | var origParallaxZoffset = this.options.parallaxZoffset; 38 | this.options.parallaxZoffset = 0; 39 | this.setLatLng(tempLatLng); 40 | 41 | map.once('zoomend', function(){ console.log('@ zoomend', tempLatLng, origLatLng); this.options.parallaxZoffset = origParallaxZoffset; this.setLatLng(origLatLng); this._onMapMove(); }, this); 42 | }, 43 | 44 | _calcLatLngFromOffset: function(){ 45 | var offsets = this._calculateOffsetFromOrigin(); 46 | var parallax = this._calculateParallaxFromOffset(offsets.centerOffset); 47 | 48 | var containerPoint = offsets.containerPoint.add(parallax); 49 | var markerLatLng = this._map.containerPointToLatLng(containerPoint); 50 | 51 | console.log('@ containerPoint: ', containerPoint); 52 | 53 | console.log('@ got markerLatLng', markerLatLng); 54 | return markerLatLng; 55 | }, 56 | 57 | _updateIconOffset: function(offset){ 58 | 59 | if(!offset || ! this._icon){ return }; 60 | 61 | var parallax = this._calculateParallaxFromOffset(offset); 62 | var originalOffset = this.options.icon._originalOffset; 63 | 64 | var newOffset = originalOffset.add(parallax); 65 | 66 | if (true) { 67 | this._icon.style.marginLeft = newOffset.x + 'px'; 68 | this._icon.style.marginTop = newOffset.y + 'px'; 69 | } 70 | }, 71 | 72 | //Find how much from the center of the map the marker is currently located 73 | _calculateOffsetFromOrigin: function(){ 74 | if(!this._map){ return; }; 75 | 76 | var latlng = this.getLatLng(); 77 | var markerPoint = this._map.latLngToContainerPoint(latlng); 78 | var centerPoint = this._map.getSize().divideBy(2); 79 | //User centerPoint and markerPoint to calculate the distance from center 80 | 81 | var deltaX = (markerPoint.x - centerPoint.x); 82 | var deltaY = (markerPoint.y - centerPoint.y); 83 | 84 | var offset = {x: deltaX, y: deltaY}; 85 | var containerPoint = markerPoint.add(offset); 86 | 87 | return {containerPoint: containerPoint, centerOffset: offset}; 88 | // targetPoint = centerPoint.subtract([overlayWidth, 0]), 89 | // targetLatLng = map.containerPointToLatLng(centerPoint); 90 | }, 91 | 92 | _calculateParallaxFromOffset: function(offset){ 93 | var parallax = L.point([0,0]); 94 | 95 | if(!this.options.parallaxZoffset){ 96 | return parallax; 97 | } 98 | 99 | 100 | //Multiplies the delta x with a factor depending on the map z. 101 | var z = this._map.getZoom(); 102 | 103 | var constFactor = this.options.parallaxZoffset * 0.000001; 104 | var moveFactor = constFactor * Math.pow(2, z); 105 | 106 | parallax.x = offset.x * moveFactor; 107 | parallax.y = offset.y * moveFactor; 108 | 109 | 110 | return parallax; 111 | } 112 | }); 113 | 114 | L.Marker.parallax = function(latlng, opts){ return new L.Marker.Parallax(latlng, opts); }; 115 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Leaflet.ParallaxMarker 2 | 3 | Markers that move with a parallax effect in relation to the base map. 4 | 5 | 6 | ## Demos / Examples 7 | See demos/examples at [https://dagjomar.github.io/Leaflet.ParallaxMarker/](https://dagjomar.github.io/Leaflet.ParallaxMarker/). 8 | 9 | 10 | ![Screencapture GIF](examples/leaflet.parallaxmarker.demo.floatinglabels.gif) 11 | 12 | ![Screencapture GIF](examples/leaflet-parallaxmarker-demo-clouds-small.gif) 13 | 14 | 15 | ## How to use 16 | 17 | The option property `parallaxZoffset` determines **how much** of a parallax effect you want. 18 | A higher number, means more effect. 19 | 0 means it will be stationary on the map, as in no effect at all 20 | 21 | #### Example 22 | 23 | The following example will stack a bunch of markers on top of each other in the z-axis 24 | Notice that the offset doubles by a factor of 2 for a nice realistic effect 25 | 26 | 27 | ![Screencapture GIF](examples/leaflet.parallaxmarker.demo.minimumexample.gif) 28 | 29 | ``` 30 | var center = {lat: 63.417103647850126, lng: 10.403537750244142}; 31 | 32 | L.Marker.parallax(center,{ parallaxZoffset: 0}).addTo(map); 33 | L.Marker.parallax(center,{ parallaxZoffset: 2}).addTo(map); 34 | L.Marker.parallax(center,{ parallaxZoffset: 4}).addTo(map); 35 | L.Marker.parallax(center,{ parallaxZoffset: 8}).addTo(map); 36 | L.Marker.parallax(center,{ parallaxZoffset: 16}).addTo(map); 37 | L.Marker.parallax(center,{ parallaxZoffset: 32}).addTo(map); 38 | ``` 39 | 40 | ## TODO 41 | - Make things work smoother on zoom animation -------------------------------------------------------------------------------- /examples/cloud.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dagjomar/Leaflet.ParallaxMarker/20cbbcb8bf848e0ab2b7cac9c45bc048256f7558/examples/cloud.png -------------------------------------------------------------------------------- /examples/clouds.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Clouds | Leaflet.Marker.Parallax Demo 4 | 5 | 6 | 7 | 8 | 9 | 13 | 14 | 15 | 16 |
17 | 18 | 82 | 83 | 84 | -------------------------------------------------------------------------------- /examples/floating-labels.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Floating Label | Leaflet.Marker.Parallax Demo 4 | 5 | 6 | 7 | 8 | 9 | 25 | 26 | 27 | 28 |
29 | 30 | 109 | 110 | 111 | -------------------------------------------------------------------------------- /examples/leaflet-parallaxmarker-demo-clouds-small.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dagjomar/Leaflet.ParallaxMarker/20cbbcb8bf848e0ab2b7cac9c45bc048256f7558/examples/leaflet-parallaxmarker-demo-clouds-small.gif -------------------------------------------------------------------------------- /examples/leaflet.parallaxmarker.demo.floatinglabels.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dagjomar/Leaflet.ParallaxMarker/20cbbcb8bf848e0ab2b7cac9c45bc048256f7558/examples/leaflet.parallaxmarker.demo.floatinglabels.gif -------------------------------------------------------------------------------- /examples/leaflet.parallaxmarker.demo.minimumexample.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dagjomar/Leaflet.ParallaxMarker/20cbbcb8bf848e0ab2b7cac9c45bc048256f7558/examples/leaflet.parallaxmarker.demo.minimumexample.gif -------------------------------------------------------------------------------- /examples/minimum-example.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Floating Label | Leaflet.Marker.Parallax Demo 4 | 5 | 6 | 7 | 8 | 9 | 25 | 26 | 27 | 28 |
29 | 30 | 64 | 65 | 66 | -------------------------------------------------------------------------------- /examples/sun.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dagjomar/Leaflet.ParallaxMarker/20cbbcb8bf848e0ab2b7cac9c45bc048256f7558/examples/sun.png --------------------------------------------------------------------------------