An overlay class for Leaflet, a JS library for interactive maps. Allows drawing overlay using Pixi.js, a JavaScript library for drawing using WebGL that seamlessly falls back to HTML5's canvas if needed. Thanks to Leaflet.D3SvgOverlay for inspiration.
- No limitations to polylines, circles or geoJSON. Draw whatever you want with Pixi.js
- No need to reproject your geometries on zoom, this is done using scaling
- Zoom animation where Leaflet supports it
Compatible with Leaflet 0.7.x and 1.x
A very basic demo.
Largest US cities (1000 animated markers).
French cities (36700 animated markers).
Rotating markers with constant size during zoom
French presidential 2017 election results: first round and second round (36000 polygons).
French legislative 2017 election results: first round and second round (36000 polygons).
(graph-draw is used to display boundaries in the election demos when rendered in WebGL)
Leaflet.PixiOverlay is available as a npm package:
npm install leaflet-pixi-overlay
or can be included in a page with jsDelivr CDN.
Include Pixi.js and the PixiOverlay libraries:
<script src="pixi.min.js"></script>
<script src="L.PixiOverlay.min.js"></script>
Create a map:
var map = L.map(...);
Create an overlay:
var pixiOverlay = L.pixiOverlay(function(utils) {
// your drawing code here
}, new PIXI.Container());
Add it to the map:
pixiOverlay.addTo(map);
var loader = new PIXI.loaders.Loader();
loader.add('marker', 'img/marker-icon.png');
loader.load(function(loader, resources) {
var markerTexture = resources.marker.texture;
var markerLatLng = [51.5, -0.09];
var marker = new PIXI.Sprite(markerTexture);
marker.anchor.set(0.5, 1);
var pixiContainer = new PIXI.Container();
pixiContainer.addChild(marker);
var firstDraw = true;
var prevZoom;
var pixiOverlay = L.pixiOverlay(function(utils) {
var zoom = utils.getMap().getZoom();
var container = utils.getContainer();
var renderer = utils.getRenderer();
var project = utils.latLngToLayerPoint;
var scale = utils.getScale();
if (firstDraw) {
var markerCoords = project(markerLatLng);
marker.x = markerCoords.x;
marker.y = markerCoords.y;
}
if (firstDraw || prevZoom !== zoom) {
marker.scale.set(1 / scale);
}
firstDraw = false;
prevZoom = zoom;
renderer.render(container);
}, pixiContainer);
pixiOverlay.addTo(map);
});
var polygonLatLngs = [
[51.509, -0.08],
[51.503, -0.06],
[51.51, -0.047],
[51.509, -0.08]
];
var projectedPolygon;
var triangle = new PIXI.Graphics();
var pixiContainer = new PIXI.Container();
pixiContainer.addChild(triangle);
var firstDraw = true;
var prevZoom;
var pixiOverlay = L.pixiOverlay(function(utils) {
var zoom = utils.getMap().getZoom();
var container = utils.getContainer();
var renderer = utils.getRenderer();
var project = utils.latLngToLayerPoint;
var scale = utils.getScale();
if (firstDraw) {
projectedPolygon = polygonLatLngs.map(function(coords) {return project(coords);});
}
if (firstDraw || prevZoom !== zoom) {
triangle.clear();
triangle.lineStyle(3 / scale, 0x3388ff, 1);
triangle.beginFill(0x3388ff, 0.2);
projectedPolygon.forEach(function(coords, index) {
if (index == 0) triangle.moveTo(coords.x, coords.y);
else triangle.lineTo(coords.x, coords.y);
});
triangle.endFill();
}
firstDraw = false;
prevZoom = zoom;
renderer.render(container);
}, pixiContainer);
pixiOverlay.addTo(map);
L.pixiOverlay(<function> drawCallback, <PIXI.Container> container, <options> options?)
drawCallback
- callback to draw/update overlay contents.container
- a Pixi container (a subclass ofPIXI.Container
).options
- overlay options object.
Drawing callback function
drawCallback(utils, eventOrCustomData)
utils
- helper object. Contains methods to work with layers coordinate system and scaling.eventOrCustomData
- Contains either the Leaflet event that causes the redraw (moveend
event) or a plain object{type: 'add'}
when the pixi layer is added to the map or the argument of aredraw
call.
Overlay options object
available fields:
padding
- (number; defaults to0.1
) How much to extend the drawing area around the map view (relative to its size).forceCanvas
- (bool; defaults tofalse
) Force use of a 2d-canvas for rendering.doubleBuffering
- (bool; default tofalse
) Activate double buffering to prevent flickering when refreshing display on some devices (especially iOS devices). This field is ignored if rendering is done with 2d-canvas.resolution
- (number; defaults to2
on retina devices and1
elsewhere) Resolution of the renderer.projectionZoom
- (function(map): Number; defaults to function that returns the average ofmap.getMinZoom()
andmap.getMaxZoom()
) returns the projection zoom level. Customizing this option can help if you experience visual artifacts.pane
- (string; defaults to'overlayPane'
) The Leaflet pane where the overlay container is inserted.destroyInteractionManager
- (bool; defaults tofalse
) Destroy PIXI Interaction Manager. This is useful when you do not need to use PIXI interaction.autoPreventDefault
- (bool; defaults totrue
) Customize PIXI Interaction ManagerautoPreventDefault
property. This option is ignored ifdestroyInteractionManager
istrue
. This should be set tofalse
in most situations to let all dom events flow from PIXI to leaflet but it is set by default for compatibility reason.
Utils object
available methods:
latLngToLayerPoint(latLng, zoom?)
- (function) returnsL.Point
projected fromL.LatLng
in the coordinate system of the overlay.layerPointToLatLng(point, zoom?)
- (function) returnsL.LatLng
projected back fromL.Point
into the original CRS.getScale(zoom?)
- (function) return the current scale factor of the overlay or the scale factor associated to zoom value.getRenderer()
- (function) return the current PIXI renderer.getContainer()
- (function) return the PIXI container used in the overlay.getMap()
- (function) return the current map.
redraw(data)
- (function) trigger a refresh of the layer.data
is passed as second argument ofdrawCallback
function. This is useful for example when you modify something in thecontainer
or if you want to animate usingPIXI.ticker.Ticker
.
- Bug fixes
- Add options for PIXI Interaction Manager
- Improved documentation
- Improved behavior when
doubleBuffering
is enabled - Remove event listeners on layer remove wih Leaflet 0.7.x
- Add second argument to
drawCallback
, improving control over redraw logic - No need to recompute container transform on
redraw
calls (performance improvement)
- Add
redraw
method
- Add
doubleBuffering
option to get rid of flickering on iOS devices
- Minor improvements
- Add support for [email protected] (thanks to dzwiedzmin)
- Initial release.
This code is provided under the MIT License (MIT).