npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

leaflet.sync

v0.2.4

Published

Sync two or more Leaflet map instances

Downloads

5,414

Readme

Leaflet.Sync

Synchronized view of two maps. Tested with Leaflet 1.0.3, 1.1.0 and 1.2.0.

More information in original blog post by @turban

Installation

Using npm for browserify npm install leaflet.sync (and require('leaflet.sync')), or just download L.Map.Sync.js and add a script tag for it in you html.

Usage

Two maps.

With two map objects, mapA and mapB, call mapA.sync(mapB) to sync interactions on mapA with mapB.

In order to make the other direction work, you should make another call: mapB.sync(mapA)

When in need to unsync maps simply call mapA.unsync(mapB) to release sync interactions on mapB and mapB.unsync(mapA) to release mapA.

More than two maps

Just make more calls to map.sync(), with different map objects. Interaction will be synced to all of them. If you want the actions to be synced vice-versa, you should synchronize all directions.

// synchronize three maps
mapA.sync(mapB);
mapA.sync(mapC);
mapB.sync(mapA);
mapB.sync(mapC);
mapC.sync(mapA);
mapC.sync(mapB);

Offset

You can synchronize not only the centers, but other points, using the option offsetFn. The parameters send to the function are (center, zoom, referenceMap, targetMap), and it must return the equivalent center to produce your offset. That means, the center to pass to setView.

In most cases, you can use the factory L.Sync.offsetHelper, that accepts two arrays of two elements each (ratioRef, ratioTgt). The meaning of this array is the relative position -relative to the top left corner and the whole size- in the map container of the point to synchronize. The first value in the array is for the x axis, where 0 is the left side and 1 the right side. The second value in the array is for the y axis, where 0 is the top side, and 1 the bottom side. So [0, 0] is the top left corner, [0, 1] is the bottom left corner, [0.5, 1] is the middle of the bottom side, [0.5, 0.5] is the center of the container, [0.75, 0.25] is the center of the top right quadrant, and [2, 0] is a point out of the container, one 'width' far to the right, in the top line.

 [0,0]------[0.5,0]------[1,0]     ...       [2,0]
   |                       |
 [0,0.5]---[0.5,0.5]---[1,0.5]
   |                       |
 [0,1]------[0.5,1]------[1,1]

For instance mapB.sync(mapC, {offsetFn: L.Sync.offsetHelper([0, 1], [1, 1])}); will sync the bottom left corner [0, 1] in the reference map (mapB) with the bottom right corner [1, 1] in the target map (mapC).

As well mapB.sync(mapA, {offsetFn: L.Sync.offsetHelper([0, 0], [1, 0.5])}); will sync the top left corner [0 ,0] in mapB with the center of the right side [1, 0.5] in mapA.

If you want the actions to be synced vice-versa, you should use symmetric values (as reference and target are swapped); for instance:

// place B below A, and show a continuous map
mapA.sync(mapB, {offsetFn: L.Sync.offsetHelper([0, 1], [0, 0])});
mapB.sync(mapA, {offsetFn: L.Sync.offsetHelper([0, 0], [0, 1])});

The default behaviour is to synchronize the centers, the corresponding offset points are [0.5, 0.5], [0.5, 0.5].

Have a look at the file examples/multiple_offset.html to see how to sync multiple maps with offsets.

If you need a different behaviour not supported by L.Sync.offsetHelper, create your own function. For instance, if you have a banner on the left side of mapA 100px width that you want to exclude, you can create something like this:

mapA.sync(mapB, {offsetFn: function (center, zoom, refMap, tgtMap) {
    var pt = refMap.project(center, zoom).add([100, 0]);
    return refMap.unproject(pt, zoom);
    }
});

Another example for offsetFn is this function, that will sync all the maps as if they were continuous, like in examples/select_syncs.html

function offsetGlobal (center, zoom, refMap, tgtMap) {
    var refC = refMap.getContainer();
    var tgtC = tgtMap.getContainer();
    var pt = refMap.project(center, zoom)
                   .subtract([refC.offsetLeft, refC.offsetTop])
                   .subtract(refMap.getSize().divideBy(2))
                   .add([tgtC.offsetLeft, tgtC.offsetTop])
                   .add(tgtMap.getSize().divideBy(2));
    return refMap.unproject(pt, zoom);
}

offset animation

API

mapA.sync(mapB, [options])

Replays all interaction on mapA on mapB to keep their views synchronized. Initially synchronizes the view of mapA to mapB.

Optional options:

{
    noInitialSync: true, // disables initial synchronization of the maps.
    syncCursor: true, // add a circle marker on the synced map
    offsetFn: function (center, zoom, refMap, tgtMap) { return center; } // function to compute an offset for the center
}

mapA.unsync(mapB)

Removes synchronization.

mapA.isSynced([otherMap])

Returns true if the map is synchronized with any other map. When otherMap is present, returns true if the map is synchronized exactly with this otherMap.

Known issues

  • Dragging is not propagated more than one level (In a a.sync(b.sync(c)) situation, dragging on a will not result in change on c).

Running tests

Install dependencies and run tests:

npm install && npm test

or load test/index.html in your browser after installing the dependencies by running npm install.