Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Animations 2.0 (fractional zoom, pyramid tiles & zoomPanTo) #2382

Merged
merged 49 commits into from
Oct 21, 2014
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
49 commits
Select commit Hold shift + click to select a range
2be2cca
basic linear zoomPanTo without intermediary tile loading
mourner Jan 15, 2014
5d58aa4
initial fractional zoom implementation for grid layers
mourner Jan 15, 2014
e41d65f
fractional zoom code clean up an fixes
mourner Jan 15, 2014
c1b2c5c
round grid layer scaling transform
mourner Jan 15, 2014
de4910f
use offset when animating transform to avoid dividing by zero
mourner Jan 16, 2014
4a344ae
working zoomPanTo implementation
mourner Jan 16, 2014
790acad
clean up zoomPanTo
mourner Jan 16, 2014
e26d148
cleaner reset logic for GridLayer
mourner Jan 17, 2014
bbb5a5a
fix some positioning bugs
mourner Jan 20, 2014
1b8f68d
simpler zoom anim calculations
mourner Jan 20, 2014
dc04b9d
add fromZoom arg to Map getZoomScale and getScaleZoom
mourner Jan 20, 2014
e093979
fix GridLayer to not reset if tile zoom didn't change
mourner Jan 20, 2014
454552e
fix zoomPan logic, cleaner code
mourner Jan 21, 2014
983a4ec
implement pyramid animations (no tile removal yet)
mourner Jan 21, 2014
169b6a0
adjust zoomPan options, add a debug page
mourner Jan 21, 2014
fc655e4
manage tile pyramid levels; always animate tile fade
mourner Jan 21, 2014
5912c36
zoom to the nearest round zoom with pinch or dblclick
mourner Jan 24, 2014
acaea1c
code cleanup; don't reload tile level that's already loaded
mourner Jan 24, 2014
dc573b7
Add safari and firefox launchers
tmcw Mar 19, 2014
74133f4
Fix MarkerSpec in retina browsers.
tmcw Mar 19, 2014
00a66b4
Add an element for tracking zoom animations. Use it for trying to sto…
danzel Mar 19, 2014
a0bc81c
Stop animating before starting a ZoomPan, otherwise they both run at …
danzel Mar 19, 2014
c1bea62
stopAnimation -> stop
danzel Mar 19, 2014
7aa9d95
Getting closer. project and unproject based on the current zoom seems…
danzel Mar 19, 2014
a5552f4
listen to moveend instead so we know where we are after a map drag
danzel Mar 19, 2014
97598d4
Move animated zoom stopping in to the place it belongs
danzel Mar 19, 2014
b6c4ebd
Move the proxy in to Map.ZoomAnimation as it is the only place that u…
danzel Mar 19, 2014
498aef4
Push getTransform up to L.DomUtil.getTransform rather than having it …
danzel Mar 19, 2014
a071f48
Removing comment out code and not needed todos
danzel Mar 19, 2014
a34810c
Use Map#stop to stop all animations
jfirebaugh Mar 19, 2014
0f0d66f
Support matrix3d as used in IE11
danzel Mar 19, 2014
b42500b
Only stop the pan animation within pan animation. If there is a zoom …
danzel Mar 20, 2014
fefe4b7
Initialize tilesToLoad variable on GridLayer creation
tmcw Mar 20, 2014
29a0eae
include zoom in tile coords, simplify parsing tile keys
mourner Mar 20, 2014
683cc45
cleanup tile removal, make unloadInvisibleTiles work again
mourner Mar 20, 2014
9b75275
more flexible tile remove method
mourner Mar 21, 2014
b0ce42f
minor tile code cleanup
mourner Mar 21, 2014
fbe2308
add prune lower res tiles algorithm
mourner Mar 21, 2014
44f16b2
much better tile pruning; add coords to tile events, ref #2378
mourner Mar 22, 2014
ad0cf36
fix world wrapping
mourner Mar 22, 2014
a4e8f4e
improve tile pruning
mourner Mar 22, 2014
8b26a73
fix build and cleanup tile pruning
mourner Mar 22, 2014
66c13bc
fix tile loading regression after rebase
mourner Jul 30, 2014
a33eff7
replace CSS transitions in pan animations with frames
mourner Jul 30, 2014
468e195
rename PosAnimation.Timer to PosAnimation
mourner Jul 30, 2014
7a75d07
update inertia settings
mourner Jul 30, 2014
70923e6
rename zoomPanTo to flyTo
mourner Jul 30, 2014
23998c1
ditch transition stopping code
mourner Aug 1, 2014
d93e828
stop panning/fly animations when necessary
mourner Aug 1, 2014
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 4 additions & 7 deletions build/deps.js
Original file line number Diff line number Diff line change
Expand Up @@ -234,14 +234,11 @@ var deps = {
desc: 'Core panning animation support.'
},

AnimationTimer: {
src: ['dom/PosAnimation.Timer.js'],
deps: ['AnimationPan'],
desc: 'Timer-based pan animation fallback for browsers that don\'t support CSS3 transitions.'
},

AnimationZoom: {
src: ['map/anim/Map.ZoomAnimation.js'],
src: [
'map/anim/Map.ZoomAnimation.js',
'map/anim/Map.FlyTo.js'
],
deps: ['AnimationPan'],
desc: 'Smooth zooming animation. Works only on browsers that support CSS3 Transitions.'
},
Expand Down
2 changes: 1 addition & 1 deletion debug/map/grid.html
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
// test async
setTimeout(function () {
done(null, tile);
}, Math.random() * 500);
}, 500 + Math.random() * 500);

return tile;
};
Expand Down
71 changes: 71 additions & 0 deletions debug/map/zoompan.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
<!DOCTYPE html>
<html>
<head>
<title>Leaflet debug page</title>

<link rel="stylesheet" href="../../dist/leaflet.css" />

<meta name="viewport" content="width=device-width, initial-scale=1.0">

<link rel="stylesheet" href="../css/screen.css" />
<style>
#map {
width: 600px;
height: 400px;
}
</style>

<script type="text/javascript" src="../../build/deps.js"></script>
<script src="../leaflet-include.js"></script>
</head>
<body>

<div id="map"></div>

<div style="position: absolute; left: 530px; top: 10px; z-index: 500">
<!-- <button id="london">London</button>
<button id="kyiv">Kyiv</button> -->
<button id="dc">DC</button>
<button id="sf">SF</button>
<button id="stop">stop</button>
</div>

<script type="text/javascript">

var kyiv = [50.5, 30.5],
london = [51.51, -0.12],
sf = [37.77, -122.42],
dc = [38.91, -77.04];

var map = L.map('map').setView(dc, 10);

var tiles = L.tileLayer('http://{s}.tiles.mapbox.com/v3/{id}/{z}/{x}/{y}.png', {
attribution: '<a href="https://www.mapbox.com/about/maps/">Terms and Feedback</a>',
id: 'examples.map-20v6611k'
}).addTo(map);

var marker1 = L.marker(kyiv).addTo(map),
marker2 = L.marker(london).addTo(map);
// marker3 = L.marker(dc).addTo(map),
// marker4 = L.marker(sf).addTo(map);

document.getElementById('dc').onclick = function () { map.flyTo(dc, 10); };
document.getElementById('sf').onclick = function () { map.flyTo(sf, 10); };
document.getElementById('stop').onclick = function () { map.stop(); };
// document.getElementById('london').onclick = function () { map.flyTo(london); };
// document.getElementById('kyiv').onclick = function () { map.flyTo(kyiv); };

function logEvent(e) { console.log(e.type); }

// map.on('click', logEvent);

// map.on('movestart', logEvent);
// map.on('move', logEvent);
// map.on('moveend', logEvent);

// map.on('zoomstart', logEvent);
// map.on('zoomend', logEvent);

</script>
</body>
</html>
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
"karma-coverage": "~0.2.3",
"karma-phantomjs-launcher": "^0.1.4",
"karma-chrome-launcher": "^0.1.4",
"karma-firefox-launcher": "~0.1.3",
"karma-safari-launcher": "~0.1.1",
"tin": "^0.5.0",
"copyfiles": "0.1.0"
},
Expand Down
4 changes: 3 additions & 1 deletion spec/karma.conf.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,9 @@ module.exports = function (config) {
'karma-mocha',
'karma-coverage',
'karma-phantomjs-launcher',
'karma-chrome-launcher'],
'karma-chrome-launcher',
'karma-safari-launcher',
'karma-firefox-launcher'],

// frameworks to use
frameworks: ['mocha'],
Expand Down
27 changes: 0 additions & 27 deletions spec/suites/dom/PosAnimationSpec.js

This file was deleted.

6 changes: 5 additions & 1 deletion spec/suites/layer/marker/MarkerSpec.js
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,11 @@ describe("Marker", function () {
expect(oldIcon).to.not.be(marker._icon);
expect(oldIcon.parentNode).to.be(null);

expect(marker._icon.src).to.contain('marker-icon.png');
if (L.Browser.retina) {
expect(marker._icon.src).to.contain('marker-icon-2x.png');
} else {
expect(marker._icon.src).to.contain('marker-icon.png');
}
expect(marker._icon.parentNode).to.be(map._panes.markerPane);
});

Expand Down
67 changes: 0 additions & 67 deletions src/dom/PosAnimation.Timer.js

This file was deleted.

95 changes: 33 additions & 62 deletions src/dom/PosAnimation.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* L.PosAnimation is used by Leaflet internally for pan animations.
* L.PosAnimation powers Leaflet pan animations internally.
*/

L.PosAnimation = L.Evented.extend({
Expand All @@ -9,87 +9,58 @@ L.PosAnimation = L.Evented.extend({

this._el = el;
this._inProgress = true;
this._newPos = newPos;
this._duration = duration || 0.25;
this._easeOutPower = 1 / Math.max(easeLinearity || 0.5, 0.2);

this.fire('start');

el.style[L.DomUtil.TRANSITION] = 'all ' + (duration || 0.25) +
's cubic-bezier(0,0,' + (easeLinearity || 0.5) + ',1)';
this._startPos = L.DomUtil.getPosition(el);
this._offset = newPos.subtract(this._startPos);
this._startTime = +new Date();

L.DomEvent.on(el, L.DomUtil.TRANSITION_END, this._onTransitionEnd, this);
L.DomUtil.setPosition(el, newPos);
this.fire('start');

// there's no native way to track value updates of transitioned properties, so we imitate this
this._stepTimer = setInterval(L.bind(this._onStep, this), 50);
this._animate();
},

stop: function () {
if (!this._inProgress) { return; }

// if we just removed the transition property, the element would jump to its final position,
// so we need to make it stay at the current position

// Only setPosition if _getPos actually returns a valid position.
this._newPos = this._getPos();
if (this._newPos) {
L.DomUtil.setPosition(this._el, this._newPos);
}

this._onTransitionEnd();
L.Util.falseFn(this._el.offsetWidth); // force reflow in case we are about to start a new animation
this._step();
this._complete();
},

_onStep: function () {
var stepPos = this._getPos();
if (!stepPos) {
this._onTransitionEnd();
return;
}
// jshint camelcase: false
// make L.DomUtil.getPosition return intermediate position value during animation
this._el._leaflet_pos = stepPos;

this.fire('step');
_animate: function () {
// animation loop
this._animId = L.Util.requestAnimFrame(this._animate, this);
this._step();
},

// you can't easily get intermediate values of properties animated with CSS3 Transitions,
// we need to parse computed style (in case of transform it returns matrix string)

_transformRe: /([-+]?(?:\d*\.)?\d+)\D*, ([-+]?(?:\d*\.)?\d+)\D*\)/,
_step: function () {
var elapsed = (+new Date()) - this._startTime,
duration = this._duration * 1000;

_getPos: function () {
var left, top, matches,
el = this._el,
style = window.getComputedStyle(el);

if (L.Browser.any3d) {
matches = style[L.DomUtil.TRANSFORM].match(this._transformRe);
if (!matches) { return; }
left = parseFloat(matches[1]);
top = parseFloat(matches[2]);
if (elapsed < duration) {
this._runFrame(this._easeOut(elapsed / duration));
} else {
left = parseFloat(style.left);
top = parseFloat(style.top);
this._runFrame(1);
this._complete();
}

return new L.Point(left, top, true);
},

_onTransitionEnd: function () {
L.DomEvent.off(this._el, L.DomUtil.TRANSITION_END, this._onTransitionEnd, this);

if (!this._inProgress) { return; }
this._inProgress = false;
_runFrame: function (progress) {
var pos = this._startPos.add(this._offset.multiplyBy(progress));
L.DomUtil.setPosition(this._el, pos);

this._el.style[L.DomUtil.TRANSITION] = '';
this.fire('step');
},

// jshint camelcase: false
// make sure L.DomUtil.getPosition returns the final position value after animation
this._el._leaflet_pos = this._newPos;
_complete: function () {
L.Util.cancelAnimFrame(this._animId);

clearInterval(this._stepTimer);
this._inProgress = false;
this.fire('end');
},

this.fire('step').fire('end');
_easeOut: function (t) {
return 1 - Math.pow(1 - t, this._easeOutPower);
}

});
Loading