leaflet-geosearch icon indicating copy to clipboard operation
leaflet-geosearch copied to clipboard

Performing a smooth pan-zoom animation , like leaflet flyTo not panTo

Open dolorain opened this issue 3 years ago • 2 comments

As the title

Thanks

dolorain avatar Dec 30 '21 02:12 dolorain

@smeijer This is a function copy from leaflet.js, and it took me some time to understand. I think it replacing some of the code in the centerMap function (line 437) of SearchControl may achieve it. But I didn't try it, because I didn't figure out the correspondence between the if else functions of thecenterMap.

`

    // @method flyTo(latlng: LatLng, zoom?: Number, options?: Zoom/pan options): this
    // Sets the view of the map (geographical center and zoom) performing a smooth
    // pan-zoom animation.
    flyTo: function (targetCenter, targetZoom, options) {
	options = options || {};
	if (options.animate === false || !Browser.any3d) {
		return this.setView(targetCenter, targetZoom, options);
	}

	this._stop();

	var from = this.project(this.getCenter()),
	    to = this.project(targetCenter),
	    size = this.getSize(),
	    startZoom = this._zoom;

	targetCenter = toLatLng(targetCenter);
	targetZoom = targetZoom === undefined ? startZoom : targetZoom;

	var w0 = Math.max(size.x, size.y),
	    w1 = w0 * this.getZoomScale(startZoom, targetZoom),
	    u1 = (to.distanceTo(from)) || 1,
	    rho = 1.42,
	    rho2 = rho * rho;

	function r(i) {
		var s1 = i ? -1 : 1,
		    s2 = i ? w1 : w0,
		    t1 = w1 * w1 - w0 * w0 + s1 * rho2 * rho2 * u1 * u1,
		    b1 = 2 * s2 * rho2 * u1,
		    b = t1 / b1,
		    sq = Math.sqrt(b * b + 1) - b;

		    // workaround for floating point precision bug when sq = 0, log = -Infinite,
		    // thus triggering an infinite loop in flyTo
		    var log = sq < 0.000000001 ? -18 : Math.log(sq);

		return log;
	}

	function sinh(n) { return (Math.exp(n) - Math.exp(-n)) / 2; }
	function cosh(n) { return (Math.exp(n) + Math.exp(-n)) / 2; }
	function tanh(n) { return sinh(n) / cosh(n); }

	var r0 = r(0);

	function w(s) { return w0 * (cosh(r0) / cosh(r0 + rho * s)); }
	function u(s) { return w0 * (cosh(r0) * tanh(r0 + rho * s) - sinh(r0)) / rho2; }

	function easeOut(t) { return 1 - Math.pow(1 - t, 1.5); }

	var start = Date.now(),
	    S = (r(1) - r0) / rho,
	    duration = options.duration ? 1000 * options.duration : 1000 * S * 0.8;

	function frame() {
		var t = (Date.now() - start) / duration,
		    s = easeOut(t) * S;

		if (t <= 1) {
			this._flyToFrame = Util.requestAnimFrame(frame, this);

			this._move(
				this.unproject(from.add(to.subtract(from).multiplyBy(u(s) / u1)), startZoom),
				this.getScaleZoom(w0 / w(s), startZoom),
				{flyTo: true});

		} else {
			this
				._move(targetCenter, targetZoom)
				._moveEnd(true);
		}
	}

	this._moveStart(true, options.noMoveStart);

	frame.call(this);
	return this;
},

`

dolorain avatar Jan 04 '22 02:01 dolorain

If we want this functionality, we can simply call the flyTo method on the map instance. We don't need to copy all that code.

It should definitely be an option though. Not everyone prefers the long animation.

smeijer avatar Jan 04 '22 07:01 smeijer