Cesium-Examples/libs/leaflet/plugins/Leaflet.PixiOverlay/1.9.4/L.PixiOverlay.js

421 lines
12 KiB
JavaScript
Raw Normal View History

2025-03-11 08:25:45 +00:00
// Leaflet.PixiOverlay
// version: 1.9.4
// author: Manuel Baclet <mbaclet@gmail.com>
// license: MIT
(function (factory) {
if (typeof define === 'function' && define.amd) {
// AMD
define(['leaflet', 'pixi.js'], factory);
} else if (typeof module !== 'undefined') {
// Node/CommonJS
module.exports = factory(require('leaflet'), require('pixi.js'));
} else {
// Browser globals
if (typeof window.L === 'undefined') {
throw new Error('Leaflet must be loaded first');
}
if (typeof window.PIXI === 'undefined') {
throw new Error('Pixi.js must be loaded first');
}
factory(window.L, window.PIXI);
}
}(function (L, PIXI) {
var round = L.Point.prototype._round;
var no_round = function () { return this; };
function setEventSystem(renderer, destroyInteractionManager, autoPreventDefault) {
var eventSystem = (PIXI.VERSION < "7") ? renderer.plugins.interaction : renderer.events;
if (destroyInteractionManager) {
eventSystem.destroy();
} else if (!autoPreventDefault) {
eventSystem.autoPreventDefault = false;
}
}
function projectionZoom(map) {
var maxZoom = map.getMaxZoom();
var minZoom = map.getMinZoom();
if (maxZoom === Infinity) return minZoom + 8;
return (maxZoom + minZoom) / 2;
}
var pixiOverlayClass = {
options: {
// @option padding: Number = 0.1
// How much to extend the clip area around the map view (relative to its size)
// e.g. 0.1 would be 10% of map view in each direction
padding: 0.1,
// @option forceCanvas: Boolean = false
// Force use of a 2d-canvas
forceCanvas: false,
// @option doubleBuffering: Boolean = false
// Help to prevent flicker when refreshing display on some devices (e.g. iOS devices)
// It is ignored if rendering is done with 2d-canvas
doubleBuffering: false,
// @option resolution: Number = 1
// Resolution of the renderer canvas
resolution: L.Browser.retina ? 2 : 1,
// @option projectionZoom(map: map): Number
// return the layer projection zoom level
projectionZoom: projectionZoom,
// @option destroyInteractionManager: Boolean = false
// Destroy PIXI EventSystem
destroyInteractionManager: false,
// @option
// Customize PIXI EventSystem autoPreventDefault property
// This option is ignored if destroyInteractionManager is set
autoPreventDefault: true,
// @option resolution: Boolean = false
// Enables drawing buffer preservation
preserveDrawingBuffer: false,
// @option resolution: Boolean = true
// Clear the canvas before the new render pass
clearBeforeRender: true,
// @option shouldRedrawOnMove(e: moveEvent): Boolean
// filter move events that should trigger a layer redraw
shouldRedrawOnMove: function () { return false; },
},
initialize: function (drawCallback, pixiContainer, options) {
L.setOptions(this, options);
L.stamp(this);
this._drawCallback = drawCallback;
this._pixiContainer = pixiContainer;
this._rendererOptions = {
resolution: this.options.resolution,
antialias: true,
forceCanvas: this.options.forceCanvas,
preserveDrawingBuffer: this.options.preserveDrawingBuffer,
clearBeforeRender: this.options.clearBeforeRender
};
if (PIXI.VERSION < "6") {
this._rendererOptions.transparent = true;
} else {
this._rendererOptions.backgroundAlpha = 0;
}
this._doubleBuffering = PIXI.utils.isWebGLSupported() && !this.options.forceCanvas &&
this.options.doubleBuffering;
},
_setMap: function () { },
_setContainerStyle: function () { },
_addContainer: function () {
this.getPane().appendChild(this._container);
},
_setEvents: function () { },
onAdd: function (targetMap) {
this._setMap(targetMap);
if (!this._container) {
var container = this._container = L.DomUtil.create('div', 'leaflet-pixi-overlay');
container.style.position = 'absolute';
this._renderer = PIXI.autoDetectRenderer(this._rendererOptions);
setEventSystem(
this._renderer,
this.options.destroyInteractionManager,
this.options.autoPreventDefault
);
container.appendChild(this._renderer.view);
if (this._zoomAnimated) {
L.DomUtil.addClass(container, 'leaflet-zoom-animated');
this._setContainerStyle();
}
if (this._doubleBuffering) {
this._auxRenderer = PIXI.autoDetectRenderer(this._rendererOptions);
setEventSystem(
this._auxRenderer,
this.options.destroyInteractionManager,
this.options.autoPreventDefault
);
container.appendChild(this._auxRenderer.view);
this._renderer.view.style.position = 'absolute';
this._auxRenderer.view.style.position = 'absolute';
}
}
this._addContainer();
this._setEvents();
var map = this._map;
this._initialZoom = this.options.projectionZoom(map);
this._wgsOrigin = L.latLng([0, 0]);
this._wgsInitialShift = map.project(this._wgsOrigin, this._initialZoom);
this._mapInitialZoom = map.getZoom();
var _layer = this;
this.utils = {
latLngToLayerPoint: function (latLng, zoom) {
zoom = (zoom === undefined) ? _layer._initialZoom : zoom;
var projectedPoint = map.project(L.latLng(latLng), zoom);
return projectedPoint;
},
layerPointToLatLng: function (point, zoom) {
zoom = (zoom === undefined) ? _layer._initialZoom : zoom;
var projectedPoint = L.point(point);
return map.unproject(projectedPoint, zoom);
},
getScale: function (zoom) {
if (zoom === undefined) return map.getZoomScale(map.getZoom(), _layer._initialZoom);
else return map.getZoomScale(zoom, _layer._initialZoom);
},
getRenderer: function () {
return _layer._renderer;
},
getContainer: function () {
return _layer._pixiContainer;
},
getMap: function () {
return _layer._map;
}
};
this._update({ type: 'add' });
},
onRemove: function () {
L.DomUtil.remove(this._container);
},
getEvents: function () {
var events = {
zoom: this._onZoom,
move: this._onMove,
moveend: this._update
};
if (this._zoomAnimated) {
events.zoomanim = this._onAnimZoom;
}
return events;
},
_onZoom: function () {
this._updateTransform(this._map.getCenter(), this._map.getZoom());
},
_onAnimZoom: function (e) {
this._updateTransform(e.center, e.zoom);
},
_onMove: function (e) {
if (this.options.shouldRedrawOnMove(e)) {
this._update(e);
}
},
_updateTransform: function (center, zoom) {
var scale = this._map.getZoomScale(zoom, this._zoom),
viewHalf = this._map.getSize().multiplyBy(0.5 + this.options.padding),
currentCenterPoint = this._map.project(this._center, zoom),
topLeftOffset = viewHalf.multiplyBy(-scale).add(currentCenterPoint)
.subtract(this._map._getNewPixelOrigin(center, zoom));
if (L.Browser.any3d) {
L.DomUtil.setTransform(this._container, topLeftOffset, scale);
} else {
L.DomUtil.setPosition(this._container, topLeftOffset);
}
},
_redraw: function (offset, e) {
this._disableLeafletRounding();
var scale = this._map.getZoomScale(this._zoom, this._initialZoom),
shift = this._map.latLngToLayerPoint(this._wgsOrigin)
._subtract(this._wgsInitialShift.multiplyBy(scale))._subtract(offset);
this._pixiContainer.scale.set(scale);
this._pixiContainer.position.set(shift.x, shift.y);
this._drawCallback(this.utils, e);
this._enableLeafletRounding();
},
_update: function (e) {
// is this really useful?
if (this._map._animatingZoom && this._bounds) { return; }
// Update pixel bounds of renderer container
var p = this.options.padding,
mapSize = this._map.getSize(),
min = this._map.containerPointToLayerPoint(mapSize.multiplyBy(-p)).round();
this._bounds = new L.Bounds(min, min.add(mapSize.multiplyBy(1 + p * 2)).round());
this._center = this._map.getCenter();
this._zoom = this._map.getZoom();
if (this._doubleBuffering) {
var currentRenderer = this._renderer;
this._renderer = this._auxRenderer;
this._auxRenderer = currentRenderer;
}
var view = this._renderer.view;
var b = this._bounds,
container = this._container,
size = b.getSize();
if (!this._renderer.size || this._renderer.size.x !== size.x || this._renderer.size.y !== size.y) {
if (this._renderer.gl) {
this._renderer.resolution = this.options.resolution;
if (this._renderer.rootRenderTarget) {
this._renderer.rootRenderTarget.resolution = this.options.resolution;
}
}
this._renderer.resize(size.x, size.y);
view.style.width = size.x + 'px';
view.style.height = size.y + 'px';
if (this._renderer.gl) {
var gl = this._renderer.gl;
if (gl.drawingBufferWidth !== this._renderer.width) {
var resolution = this.options.resolution * gl.drawingBufferWidth / this._renderer.width;
this._renderer.resolution = resolution;
if (this._renderer.rootRenderTarget) {
this._renderer.rootRenderTarget.resolution = resolution;
}
this._renderer.resize(size.x, size.y);
}
}
this._renderer.size = size;
}
if (this._doubleBuffering) {
var self = this;
requestAnimationFrame(function () {
self._redraw(b.min, e);
self._renderer.gl.finish();
view.style.visibility = 'visible';
self._auxRenderer.view.style.visibility = 'hidden';
L.DomUtil.setPosition(container, b.min);
});
} else {
this._redraw(b.min, e);
L.DomUtil.setPosition(container, b.min);
}
},
_disableLeafletRounding: function () {
L.Point.prototype._round = no_round;
},
_enableLeafletRounding: function () {
L.Point.prototype._round = round;
},
redraw: function (data) {
if (this._map) {
this._disableLeafletRounding();
this._drawCallback(this.utils, data);
this._enableLeafletRounding();
}
return this;
},
_destroy: function () {
this._renderer.destroy(true);
if (this._doubleBuffering) {
this._auxRenderer.destroy(true);
}
},
destroy: function () {
this.remove();
this._destroy();
}
};
if (L.version >= "1") {
L.PixiOverlay = L.Layer.extend(pixiOverlayClass);
} else {
// backport some leaflet@1.0.0 methods
L.Map.prototype.getZoomScale = function (toZoom, fromZoom) {
var crs = this.options.crs;
fromZoom = fromZoom === undefined ? this._zoom : fromZoom;
return crs.scale(toZoom) / crs.scale(fromZoom);
};
L.DomUtil.setTransform = function (el, offset, scale) {
var pos = offset || new L.Point(0, 0);
el.style[L.DomUtil.TRANSFORM] =
(L.Browser.ie3d ?
'translate(' + pos.x + 'px,' + pos.y + 'px)' :
'translate3d(' + pos.x + 'px,' + pos.y + 'px,0)') +
(scale ? ' scale(' + scale + ')' : '');
};
// patch pixiOverlayClass for leaflet@0.7.7
pixiOverlayClass.includes = L.Mixin.Events;
pixiOverlayClass.addTo = function (map) {
map.addLayer(this);
return this;
};
pixiOverlayClass._setMap = function (map) {
this._map = map;
this._zoomAnimated = map._zoomAnimated;
};
pixiOverlayClass._setContainerStyle = function () {
var self = this;
[
'-webkit-transform-origin',
'-ms-transform-origin',
'transform-origin'
].forEach(function (property) {
self._container.style[property] = '0 0';
});
};
pixiOverlayClass._addContainer = function () {
this._map.getPanes()[this.options.pane || 'overlayPane']
.appendChild(this._container);
};
pixiOverlayClass._setEvents = function () {
var events = this.getEvents();
for (var evt in events) {
this._map.on(evt, events[evt], this);
}
};
pixiOverlayClass.onRemove = function () {
this._map = null;
var parent = this._container.parentNode;
if (parent) {
parent.removeChild(this._container);
}
var events = this.getEvents();
for (var evt in events) {
this._map.off(evt, events[evt], this);
}
};
pixiOverlayClass.destroy = function () {
var map = this._map || this._mapToAdd;
if (map) {
map.removeLayer(this);
}
this._destroy();
};
L.PixiOverlay = L.Class.extend(pixiOverlayClass);
}
// @factory L.pixiOverlay(drawCallback: function, pixiContainer: PIXI.Container, options?: L.PixiOverlay options)
// Creates a PixiOverlay with the given arguments.
L.pixiOverlay = function (drawCallback, pixiContainer, options) {
return L.Browser.canvas ? new L.PixiOverlay(drawCallback, pixiContainer, options) : null;
};
}));