Skip to content

Commit

Permalink
#33 use supplied pane when rendering curves for canvas
Browse files Browse the repository at this point in the history
  • Loading branch information
elfalem committed Nov 24, 2020
1 parent 77f13a0 commit 5e8d9e8
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 92 deletions.
22 changes: 13 additions & 9 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<head>
<meta charset="utf-8">
<title>Leaflet.curve plugin demo</title>
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.0.0/dist/leaflet.css" />
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.1.0/dist/leaflet.css" />
<style>
#map { height: 500px; }
</style>
Expand All @@ -12,19 +12,25 @@


<script src="https://unpkg.com/[email protected]/dist/leaflet-src.js"></script>
<!-- <script src="https://cdnjs.cloudflare.com/ajax/libs/tween.js/17.2.0/Tween.min.js"></script> -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/tween.js/17.2.0/Tween.min.js"></script>
<script src="src/leaflet.curve.js"></script>

<script>
//set up map
var map = L.map('map'/*, {preferCanvas: true}*/).setView([46.05, 11.05], 5);
var map = L.map('map').setView([46.05, 11.05], 5);
L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png', {attribution: '&copy; <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'}).addTo(map);

//use a mix of renderers
var customPane = map.createPane("customPane");
var canvasRenderer = L.canvas({pane:"customPane"});
customPane.style.zIndex = 399; // put just behind the standard overlay pane which is at 400

//quadratic bezier curve
var pathOne = L.curve(['M',[50.14874640066278,14.106445312500002],
'Q',[51.67255514839676,16.303710937500004],
[50.14874640066278,18.676757812500004],
'T',[49.866316729538674,25.0927734375]], {animate: 3000}).addTo(map);
'T',[49.866316729538674,25.0927734375]], {animate: 3000, renderer: canvasRenderer}).addTo(map);


//cubic bezier curve (and straight lines)
var pathTwo = L.curve(['M',[50.54136296522163,28.520507812500004],
Expand All @@ -37,8 +43,7 @@
'M',[49.55372551347579,29.465332031250004],
'V',[48.7822260446217],
'H',[33.00292968750001],
'V',[49.55372551347579],'Z'],{color:'red',fill:true}).addTo(map);

'V',[49.55372551347579],'Z'],{color:'red',fill:true, renderer: canvasRenderer }).addTo(map);


var pathThree = L.curve(['M',[49.35375571830993,6.240234375],
Expand Down Expand Up @@ -68,10 +73,9 @@
[47.96050238891509, -15.644531250000002],
'Z'], {color: 'red', fill: true, dashArray: '5', animate: {duration: 3000, iterations: Infinity, delay: 1000}});

function onMapClick(e) {
map.on('click', function(e) {
console.log(e.latlng);
}
map.on('click', onMapClick);
});

function traceCurves(){
pathOne.trace([0, 0.25, 0.75, 1]).forEach(i => L.circle(i, {color: 'green'}).addTo(map));
Expand Down
117 changes: 34 additions & 83 deletions src/leaflet.curve.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,14 @@ L.Curve = L.Path.extend({
},

_updateBounds: function() {
// Empty function to satisfy L.Path.setStyle() method
var tolerance = this._clickTolerance();
var tolerancePoint = new L.Point(tolerance, tolerance);

//_pxBounds is critical for canvas renderer, used to determine area that needs redrawing
this._pxBounds = new L.Bounds([
this._rawPxBounds.min.subtract(tolerancePoint),
this._rawPxBounds.max.add(tolerancePoint)
]);
},

getPath: function(){
Expand Down Expand Up @@ -128,20 +135,25 @@ L.Curve = L.Path.extend({
return this._bounds.getCenter();
},

// _update() is invoked by Path._reset()
_update: function(){
if (!this._map) { return; }

// TODO: consider implementing this._clipPoints(); and this._simplifyPoints(); to improve performance
this._updatePath();
},

_updatePath: function() {
// the following can be thought of as this._renderer.updateCurve() in both SVG/Canvas renderers
// similar to Canvas._updatePoly(), Canvas._updateCircle(), etc...
if(this._usingCanvas){
this._updateCurveCanvas();
}else{
this._updateCurveSvg();
}
},

//_project() is invoked by Path._reset()
_project: function() {
var coord, lastCoord, curCommand, curPoint;

Expand All @@ -155,22 +167,29 @@ L.Curve = L.Path.extend({
}else {
switch(coord.length){
case 2:
curPoint = this._latLngToPointFn.call(this._map, coord);
curPoint = this._map.latLngToLayerPoint(coord);
lastCoord = coord;
break;
case 1:
if(curCommand == 'H'){
curPoint = this._latLngToPointFn.call(this._map, [lastCoord[0], coord[0]]);
curPoint = this._map.latLngToLayerPoint([lastCoord[0], coord[0]]);
lastCoord = [lastCoord[0], coord[0]];
}else{
curPoint = this._latLngToPointFn.call(this._map, [coord[0], lastCoord[1]]);
curPoint = this._map.latLngToLayerPoint([coord[0], lastCoord[1]]);
lastCoord = [coord[0], lastCoord[1]];
}
break;
}
this._points.push(curPoint);
}
}

if(this._bounds.isValid()){
var northWestLayerPoint = this._map.latLngToLayerPoint(this._bounds.getNorthWest());
var southEastLayerPoint = this._map.latLngToLayerPoint(this._bounds.getSouthEast());
this._rawPxBounds = new L.Bounds(northWestLayerPoint, southEastLayerPoint);
this._updateBounds();
}
},

_curvePointsToPath: function(points){
Expand Down Expand Up @@ -202,7 +221,6 @@ L.Curve = L.Path.extend({

this._usingCanvas = this._renderer instanceof L.Canvas;

this._latLngToPointFn = this._usingCanvas ? map.latLngToContainerPoint : map.latLngToLayerPoint;
if(this._usingCanvas){
this._pathSvgElement = document.createElementNS('http://www.w3.org/2000/svg', 'path');
}
Expand All @@ -217,18 +235,10 @@ L.Curve = L.Path.extend({
L.Path.prototype.onAdd.call(this, map); // calls _update()

if(this._usingCanvas){
this._animationCanvasElement = this._insertCustomCanvasElement();

this._resizeCanvas();

map.on('resize', this._resizeCanvas, this);

if(this.options.animate && typeof(TWEEN) === 'object'){
this._pathLength = this._pathSvgElement.getTotalLength();

this._normalizeCanvasAnimationOptions();

this._tweenedObject = {offset: this._pathLength};
this._tweenedObject = {offset: this._pathSvgElement.getTotalLength()};
this._tween = new TWEEN.Tween(this._tweenedObject)
.to({offset: 0}, this.options.animate.duration)
// difference of behavior with SVG, delay occurs on every iteration
Expand Down Expand Up @@ -258,16 +268,6 @@ L.Curve = L.Path.extend({
}
},

onRemove: function(map){
L.Path.prototype.onRemove.call(this, map);

if(this._usingCanvas){
this._clearCanvas();
L.DomUtil.remove(this._animationCanvasElement);
map.off('resize', this._resizeCanvas, this);
}
},

// SVG specific logic
_updateCurveSvg: function(){
this._renderer._setPath(this, this._curvePointsToPath(this._points));
Expand All @@ -293,16 +293,6 @@ L.Curve = L.Path.extend({
},

// Canvas specific logic below here
_insertCustomCanvasElement: function(){
var element = L.DomUtil.create('canvas', 'leaflet-zoom-animated');
var originProp = L.DomUtil.testProp(['transformOrigin', 'WebkitTransformOrigin', 'msTransformOrigin']);
element.style[originProp] = '50% 50%';
var pane = this._map.getPane(this.options.pane);
pane.insertBefore(element, pane.firstChild);

return element;
},

_normalizeCanvasAnimationOptions: function(){
var opts = {
delay: 0,
Expand All @@ -327,71 +317,32 @@ L.Curve = L.Path.extend({
},

_updateCurveCanvas: function(){
this._project();

var pathString = this._curvePointsToPath(this._points);
this._pathSvgElement.setAttribute('d', pathString);

if(this.options.animate && typeof(TWEEN) === 'object' && this._canvasSetDashArray){
this._pathLength = this._pathSvgElement.getTotalLength();
this.options.dashArray = this._pathLength + '';
this.options.dashArray = this._pathSvgElement.getTotalLength() + '';
this._renderer._updateDashArray(this);
}

this._path2d = new Path2D(pathString);

if(this._animationCanvasElement){
this._resetCanvas();
}


this._curveFillStroke(new Path2D(pathString), this._renderer._ctx);
},

_animationCanvasElement: null,

_resizeCanvas: function() {
var size = this._map.getSize();
this._animationCanvasElement.width = size.x;
this._animationCanvasElement.height = size.y;

this._resetCanvas();
},

_resetCanvas: function() {
var topLeft = this._map.containerPointToLayerPoint([0, 0]);
L.DomUtil.setPosition(this._animationCanvasElement, topLeft);

this._redrawCanvas();
},

_redrawCanvas: function(){
if(!this._canvasAnimating){
this._clearCanvas();
var ctx = this._animationCanvasElement.getContext('2d');
this._curveFillStroke(this._path2d, ctx);
}
},

_clearCanvas: function() {
this._animationCanvasElement.getContext('2d').clearRect(0, 0, this._animationCanvasElement.width, this._animationCanvasElement.height);
},

_animateCanvas: function(time){
TWEEN.update(time);

var ctx = this._animationCanvasElement.getContext('2d');
ctx.clearRect(0, 0, this._animationCanvasElement.width, this._animationCanvasElement.height);
ctx.lineDashOffset = this._tweenedObject.offset;

this._curveFillStroke(this._path2d, ctx);
_animateCanvas: function(){
TWEEN.update();

// clear out area and re-render all layers
this._renderer._updatePaths();

if(this._canvasAnimating){
this._animationFrameId = L.Util.requestAnimFrame(this._animateCanvas, this);
}
},

// similar to Canvas._fillStroke(ctx, layer)
_curveFillStroke: function (path2d, ctx) {
_curveFillStroke: function (path2d, ctx) {
ctx.lineDashOffset = this._canvasAnimating ? this._tweenedObject.offset : 0.0;

var options = this.options;

if (options.fill) {
Expand Down

0 comments on commit 5e8d9e8

Please sign in to comment.