elfalem / leaflet.curve Goto Github PK
View Code? Open in Web Editor NEWA Leaflet plugin for drawing Bézier curves and other complex shapes.
License: Other
A Leaflet plugin for drawing Bézier curves and other complex shapes.
License: Other
Do you have an idea of what it would take to implement support for canvas animation? I ask as I know it will eventually come up in the fear future and I'd like to have a reasonable response as to what effort would be involved. I'd be happy to help implement it.
For my specific case, it would be updating the offset of a dashed line to indicate movement from one coordinate to another.
how the timer has to be set for the curve?
curve should disappear along with the markers.
Hi,
First, thanks a lot for this great lib for Leaflet. I integrated it into my project and it works great.
I only have a browser compatibility issue with Safari (here version 10.0.3). It looks that some (SVG?) features are not natively supported. While drawing curve on amp, I get the following error:
Leaflet.curve:l182
TypeError: path.animate is not a function. (In 'path.animate([
{strokeDashoffset: length},
{strokeDashoffset: 0}
], layer.options.animate)', 'path.animate' is undefined)
Any idea how to fix/workaround it?
Olivier
I'd like the line to start with one color and end with another. I am wondering if this is possible with leaflet curve. thanks so much
A path with animate option set keeps getting re-animated when the map is panned or zoom level is changed.
Any plan?
I have a code pen demonstrating the issue at https://codepen.io/ericg_off/pen/JjLGWLw
I am using:
To reproduce:
The following error will appear:
t-spatial.esm.js:522 Uncaught TypeError: Cannot read properties of undefined (reading 'type')
at t (t-spatial.esm.js:522:15)
at calc.ts:6:20
at Array.filter (<anonymous>)
at U (calc.ts:58:35)
at e.finish (lasso-handler.ts:189:34)
at e.onDocumentMouseUp (lasso-handler.ts:151:14)
t @ t-spatial.esm.js:522
(anonymous) @ calc.ts:6
U @ calc.ts:58
e.finish @ lasso-handler.ts:189
e.onDocumentMouseUp @ lasso-handler.ts:151
iframeConsoleRunner-7549a40147ccd0ba0a6b5373d87e770e49bb4689f1c2dc30cccc7463f207f997.js:1 mouseup event was missed
I am not sure if the actual bug is in the lasso code or in the curve code.
Hello, I'd like to bring to your attention 2 modifications that we have made to a fork of your library and ask if they are something you would like us to pull request back into your library.
The changes we made are to (1)add a function that is called internally from leaflet.Path.setStyle(), and (2)to add a function to Leaflet.curve that a library we are using references but does not exist in Leaflet.curve. We did not modify any existing functionality.
We are using Leaflet.curve to draw a curve between 2 points on a map in a React application using react-leaflet and react-leaflet-ant-path to draw an animation along the curve. In our initial implementation without dynamic reloading of data on the map we are able to successfully integrate Leaflet.curve and the other 2 libraries. When we added dynamic reloading of the map source data we found that our map would error due to Leaflet.curve.setStyle() being called (which inherits from Leaflet.Path), and also error due to trying to call Leaflet.curve.setLatLngs() which was not implemented in Leaflet.curve.
We made the following changes to a fork of Leaflet.curve as we determined that would be the simplest changes we could make to use the libraries together.
In the setStyle() method of Leaflet.Path, Leaflet.Path._updateBounds() is called and causes an error. The _updateBounds() method is not implemented in Leaflet.Path, Leaflet.Layer (parent to Leaflet.Path), or Leaflet.curve. We have added this function as an empty function to satisfy the method call, which appears to work for our purposes but may need further attention in the future.
Function calling _updateBounds:
Our change:
When passing Leaflet.curve to react-leaflet-ant-path as the line type to draw with an animation, react-leaflet-ant-path will eventually call Leaflet.curve.setLatLngs() as part of updating the rendered map once React has determined what to re-render. The function setLatLngs() is not in this library. The method setLatLngs() is not implemented in Leaflet.Path but is implemented by Leaflet.Polyline (which similarly takes a series of points along the line). While I think it could be said that for full support of Leaflet.curve to be claimed by react-leaflet-ant-path that library should handle Leaflet.curve differently and not expect the setLatLngs() method, I am instead posing the question "should Leaflet.curve.setLatLngs() exist since Leaflet.Polyline implements the exact method name and a number of other leaflet components implement a similarly named method?". With classes extending Polyline and other leaflet components using a very similar name I can also see it being beneficial for Leaflet.curve to follow this pattern and have a setLatLngs() method to potentially be more easily integrated with other libraries.
Separate functions that follow the naming convention of setLatLngs():
Our change:
We are interested to hear your thoughts on our changes and if you would like to include them in the Leaflet.curve library. If you would like to include the changes, I can create a fork branch to pull request with only the 2 specific function additions so as not to pick up the other changes I have made to allow us to reference the project as an npm dependency from GitHub.
Thank you in advance for your time.
First of all, thanks for implementing the helpful trace method. In a react app I wanted to use the new method and I got the error mentioned in the title. Drawing the curve works just fine.
Here is the used code snippet
if (this.map != null) {
let curve = L.curve(path,
this.props.polylineOptions).addTo(this.map);
const points = curve.trace([0.25, 0.5, 0.75]);
console.log('Curve trace *****', points)
// this.addArrowDecorators(points);
}
I am using leaflet 1.1.0 and the newest (0.5) Leaflet.curve. Any idea what is going wrong?
https://gyazo.com/5e24d35d712bc53c98bd9654bae3ca8a
I think this is because the length of the path does not change during zoom, so when I zoom in, its so long that you don't see the animation, and then its smaller, you see small chunks of paths moving.
My code:
`
const attackerIcon = LeafletMap.divIcon({
className: 'attacker',
html: '
LeafletMap.curve(['M', [41.224374, 0.145053],
'C', [47.387311, 21.503481],
[45.406853, 38.448971],
[32.638331, 36.582095]], { animate: {duration: 1600, iterations: Infinity, easting: 'ease-in-out'} }).addTo(this.map);
const target1 = LeafletMap.divIcon({
className: 'target',
html: '<div></div>'
});
LeafletMap.marker([32.638331, 36.582095], {icon: target1}).addTo(this.map);
LeafletMap.curve(['M', [41.224374, 0.145053],
'C', [44.285435, -25.579085],
[31.887952, -66.536115],
[6.414813, -73.040021]], { animate: {duration: 1600, iterations: Infinity, easting: 'ease-in-out'} }).addTo(this.map);
const target2 = LeafletMap.divIcon({
className: 'target',
html: '<div></div>'
});
LeafletMap.marker([6.414813, -73.040021], {icon: target2}).addTo(this.map);
`
when going to one curve line using M and Q we have to put midpoint statically.
EX:
L.curve(
[
'M', latlng1,
'Q', latlng1,
[14.33,23.66]//we don't know this
], dash_straight).addTo(this.map);
so need a way to create that midpoint automatically from the plugin.
using your plugin I created sample project to do that https://github.com/lifeeka/leaflet.bezier/tree/supun-dev
Provide a way to access the Animation object returned by Element.Animate(). This would allow pausing and restarting animations among other things. https://developer.mozilla.org/en-US/docs/Web/API/Animation
I have an example of a curve drawn between Australia and California. The expected curve would have crossed the pacific ocean for the shortest path. Instead, it seems to cross Africa and the Atlantic Ocean.
I'd like to understand better why that is and if there is a solution to this. Thanks for your time.
Hello,
First of all awesome plugins, I can see by the demo and it is exactly what I need.
However, I can't get it to work with Angular 10.
I am using the following packages:
"@asymmetrik/ngx-leaflet": "^13.0.0",
"@elfalem/leaflet-curve": "^0.9.2",
"leaflet": "^1.9.3",
I use @asymmetrik/ngx-leaflet for the types.
I get the following error after importing import '@elfalem/leaflet-curve';
:
Invalid module name in augmentation. Module 'leaflet' resolves to an untyped module at '/node_modules/leaflet/dist/leaflet-src.js', which cannot be augmented.
When I added the following to tsconfig compilerOptions:
"skipLibCheck": true
It didn't show the error, however, it did not render any curves I added from the demos.
Any idea how can I get this to work?
Thanks a lot.
im getting this error: ERROR ReferenceError: coord is not defined
when i try to do this: L.curve(['S', [place.lat ,place.lon],[-23.5437811, -46.6470027]], {color:'green',fill:true}).addTo(this.map);
how can i do this work?
(i'm using angular)
Hi I created an angular application where I'm using leaflet with leaflet.curve.
I used the same points as in the example and I'm seeing my map and the curves but the curves are not animating. Did I maybe miss some packages or modules?
import { Component, OnInit } from '@angular/core';
import "leaflet";
import "leaflet-curve";
@Component({
selector: 'app-map',
templateUrl: './map.component.html',
styleUrls: ['./map.component.css']
})
export class MapComponent implements OnInit {
constructor() { }
ngOnInit() {
const map = L.map('leafletmap').setView([46.05, 11.05], 5);
L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png', {
attribution:
'© <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
}).addTo(map);
const 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);
const pathTwo = L.curve(
[
'M',
[50.54136296522163, 28.520507812500004],
'C',
[52.214338608258224, 28.564453125000004],
[48.45835188280866, 33.57421875000001],
[50.680797145321655, 33.83789062500001],
'V',
[48.40003249610685],
'L',
[47.45839225859763, 31.201171875],
[48.40003249610685, 28.564453125000004],
'Z',
'M',
[49.55372551347579, 29.465332031250004],
'V',
[48.7822260446217],
'H',
[33.00292968750001],
'V',
[49.55372551347579],
'Z'
],
{ color: 'red', fill: true }
).addTo(map);
const pathThree = L.curve(
[
'M',
[49.35375571830993, 6.240234375],
'Q',
[49.38237278700955, 9.843750000000002],
[47.754097979680026, 9.360351562500002],
[46.95026224218562, 6.635742187500001],
[45.67548217560647, 8.437500000000002],
[44.5278427984555, 5.5810546875],
[45.85941212790755, 3.0761718750000004],
[47.517200697839414, 4.218750000000001],
[49.009050809382074, 3.7353515625000004],
[48.45835188280866, 5.800781250000001],
[48.8936153614802, 5.493164062500001],
'Z'
],
{ fill: true, color: 'orange' }
).addTo(map);
const pathFour = L.curve(
[
'M',
[46.86019101567027, -29.047851562500004],
'Q',
[50.48547354578499, -23.818359375000004],
[46.70973594407157, -19.907226562500004],
'T',
[46.6795944656402, -11.0302734375]
],
{ dashArray: 5, animate: { duration: 3000, iterations: Infinity } }
).addTo(map);
function onMapClick(e) {
console.log(e.latlng);
}
map.on('click', onMapClick);
}
ngOnDestroy(): void {}
}
First of all, thank you for this amazing plugin. But, I've got an issue.
I create a curve with those parameters :
"M"
[-32.39851580247402, 114.31549072265626]
"C"
[-32.39851580247402, 114.31549072265626]
[-30.751277776257812, 115.44049072265629]
[-30.751277776257812, 118.18267822265626]
"S"
[-32.39851580247402, 122.08502197265629]
[-32.39851580247402, 122.08502197265629]
"V"
[-37.885259175825965, 122.08502197265629]
"H"
[-37.885259175825965, 114.28033447265625]
"V"
[-32.39851580247402, -179.76654052734378]
"Z"
The curve is ok, and is displayed at the wright place.
But when I call getCenter on the curve, I get those :
lat: -34.31826847604189
lng: 42.099881398415164
lat is ok, but lng is not what it should be.
I'm using a custom map with a width twice as wide as the height. My code loads an SVG file and creates layers on the fly. Here is the SVG with only the path used for the curve :
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 27.3.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px"
y="0px" viewBox="0 0 2048 1024" style="enable-background:new 0 0 2048 1024;" xml:space="preserve">
<g id="interaction">
<path style="fill:#0A0A0A;enable-background:new;" d="M836.5,609.5c0,0,3.2-5.5,11-5.5s11.1,5.5,11.1,5.5v19.1h-22.2V609.5z"/>
</g>
</svg>
But again, the curve is displayed at the right place.
getCenter on leaflet legacy objects (L.polygon, for instance) works fine.
Thanks.
Hello, I am using this plugin in leaflet to show curved links that do not overlap each other. I have programmed that when you click on a link, it stands out in a different color, but the problem I have is that when I click on a link through the map, another one that is not it stands out.
I create a curve like this:
var coords = [ 'M', [nodeAxPosition, nodeAyPosition], 'Q', midpointLatLng, [nodeBxPosition, nodeByPosition] ]; polyline = new L.curve(coords, options).addTo(map);
And I activate the click event in this curve as follows:
polyline.on('click', function (e: any) { /*my code*/ });
On the map, as you move the mouse near the curves, you can see the mouse state change from normal to pointer at a greater distance from the curve, as if you could click on a curve where the curve is not being represented. .
Thanks in advance!
I have this error when rendering curve.
leaflet.curve.js:84 Uncaught (in promise) TypeError: this._renderer._updatecurve is not a function
at NewClass._updatePath (leaflet.curve.js:84)
I use Typescript with webpack.
declare var L:any
import "leaflet";
import '@elfalem/leaflet-curve'
....
export default class PolyLineContainer {
var path = L.curve(['M',[50.54136296522163,28.520507812500004],
'C',[52.214338608258224,28.564453125000004],
[48.45835188280866,33.57421875000001],
[50.680797145321655,33.83789062500001],
'V',[48.40003249610685],
'L',[47.45839225859763,31.201171875],
[48.40003249610685,28.564453125000004],'Z'],
{color:'red',fill:true}).addTo(this.mapObject.map);
}
Here's the use case:
Zoom out to zoom level 3 and click on Trace Curves
Then start to zoom in; you'll see that after a certain zoom level, the deviation starts to be perceptive.
See the images below:
Originally posted by @aasilva in #20 (comment)
The type declaration file was added in #38. However, it looks like the declaration file is not being published to NPM so it doesn't show up in the node_modules/@elfalem/leaflet-curve
.
Based on the Typescript docs the two main ways are either via NPM with the library or through the @types organization on NPM.
https://www.typescriptlang.org/docs/handbook/declaration-files/publishing.html
The previous PR included the types in the package.json
and I also see someone already has submitted a version to the @types organization that separate from the ones included in this repository.
https://www.typescriptlang.org/dt/search?search=leaflet-curve
So, my guess is that it just got missed during the npm publish process?
Is threre some way to animate it?
Nice plugin.
I hope I am wrong, but shapes do not seem to be drawn in IE and Edge.
Is there any plan to provide support for the Canvas renderer in the future? Due to performance issues using SVG and animations (with the amount of data we have to render at once) I'd love to switch over to using the canvas renderer but we lose all of our arcs, and I've yet to find a good replacement.
Hello,
I added a leaflet.browser.print button to print the map with the flows but it always returns a map without flows curves any advice or recommendations to show the curves in the maps.
Best regards.
This is related to #49
As noted in the related leaflet-lasso ticket ( zakjan/leaflet-lasso#50 ), there may be something this project can do to support such functionality.
The primary issue, I believe, is the lack of a .getBounds() method.
I am wondering how difficult it would be to add such a method to this project...?
Hi! Perfect work!
Can you add some features ?
it's will be great!
please tell me ,or make an example
When having a lot of curves animating, by adding/removing them from the map every time, the javascript heap size always increases along with the amount of nodes in the DOM.
I am not sure why, but it's definitely not in how I handle the curves. If I remove all layers in the map, the heap size/amount of nodes does not decrease, it's something in the library and I am unsure why.
lefalet-curve dont work using CRS.simple :/
Hello!
I'm trying to draw an arrow in the middle of a L.Curve, using Leaflet.PolylineDecorator library.
What I'd like to do is:
var curve = L.Curve(...).addTo(map);
var arrowDecorator = L.polylineDecorator(curve, {
patterns: [
// arrow at 50% of the path
{offset: '50%', repeat: 0, symbol: L.Symbol.arrowHead({pixelSize: 15, polygon: false, pathOptions: {stroke: true}})}
]
}).addTo(map);
However PolylineDecorator only accepts L.Polyline, L.Polygon or an array of L.LatLng as a parameter.
Is there maybe any way to extract an array of latlngs from the curve and use that?
Thanks!
Hello!
I ran into this problem when tried to zoom map.
For example - your demo http://elfalem.github.io/Leaflet.curve/
Zoom in animated curve with dashes until animation became slow and the browser starts to hang.
It happens not only with animated curves but with simple curves with dashes.
Hi ! Is it, or will it be possible to draw marker on the curve ?
Is there a way? To use this "lib" but with Leaflet 0.7.5?
With leaflet v1.7.1 and Leaflet.curve 1.0.0, calling setStyle to change line weight blows out.
Reproducible in this codepen.
Uncaught TypeError: this._updateBounds is not a function
setStyle Path.js:109
This is where the error occurs.
When defining a renderer for the curve, which has a pane defined, pane is ignored and each curve creates a canvas for itself and makes the page very heavy and irresponsible.
map.createPane("customPane");
var canvasRenderer = L.canvas({pane:"customPane"});
var pathOptions = {
renderer: canvasRenderer
};
var path =
['M', [50.14874640066278, 14.106445312500002],
'Q', [51.67255514839676, 16.303710937500004],
[50.14874640066278, 18.676757812500004],
'T', [49.866316729538674, 25.0927734375]];
for (var i = 0; i < 500; i += 1) {
var curvedPath = L.curve(path, pathOptions);
curvedPath.addTo(map);
}
Leaflet 1.7.1
If a curve is not added to a map, invoking trace()
on it results the following error:
this._points is undefined
I have draw a curve in leaflet map between two points. How to add text in middle of curve line.
my code is like that :
var curvedPath = L.curve(
[
'M', latlng1,
'Q', midpointLatLng,
latlng2
], pathOptions).addTo(map);
Hello there! I hope you are had an amazing weekend. I have been using your leaflet plugin since a while and am absolutely grateful for it. I was wondering if you would be interested in adding type support for this plugin? I am willing to create a TypeScript declaration file for this extension 😃 Hope you have a wonderful week!
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.