Connect dots in map using JavaScript marker - javascript

So I try to make an interactive map for one of my projects.
Here what I have done:
I want a help on how these two dots can be connected with a line.
Note: This is not google maps API
Here is the code:
<script>
$(function() {
$("#world_map").vectorMap({
map: "world_mill",
normalizeFunction: "polynomial",
hoverOpacity: .7,
hoverColor: false,
regionStyle: {
initial: {
fill: "#e3eaef"
}
},
markerStyle: {
initial: {
"r": 9,
"fill": window.theme.primary,
"fill-opacity": .95,
"stroke": "#fff",
"stroke-width": 7,
"stroke-opacity": .4
},
hover: {
"stroke": "#fff",
"fill-opacity": 1,
"stroke-width": 1.5
}
},
backgroundColor: "transparent",
zoomOnScroll: false,
markers: [{
latLng: [49.009724, 2.547778],
name: "Paris"
},
{
latLng: [37.983810, 23.727539],
name: "Athens"
}
]
});
setTimeout(function() {
$(window).trigger('resize');
}, 250)
});
</script>

I can't test this, but let me know if it works. The idea is you pass into this function the index of the markers from your markers array.
Also, you'll need to add a <canvas> element to overlay your map
<canvas id="canvas" height="400" width="500"></canvas>
function drawLine(fromIndex, toIndex) {
const canvas = document.querySelector('#canvas');
var fromMarker = $('circle [data-index="'+fromIndex+'"]').position();
var toMarker = $('circle [data-index="'+toIndex+'"]').position();
if (!canvas.getContext) {
return;
}
const ctx = canvas.getContext('2d');
// set line stroke and line width
ctx.strokeStyle = 'red';
ctx.lineWidth = 1;
// draw a red line
ctx.beginPath();
ctx.moveTo(fromMarker.x, fromMarker.y);
ctx.lineTo(toMarker.x, toMarker.y);
ctx.stroke();
}
// know the indexes of the 2 markers in order of the way they're listed
drawLine(0, 1);

Related

SciChart: Working with JavaScript Heatmap Chart

I am using SciChart Library for showing JS Heatmap Chart.
According to the below documentation, the zValues variable is generated using iterate function but when I try to use it in my HTML & CSS based website, Its not working.
https://demo.scichart.com/javascript-heatmap-chart
The error I am getting is:
Uncaught SyntaxError: Unexpected token ':'
I have written the following Code:
Code:
var {sciChartSurface, wasmContext} = await SciChart.SciChartSurface.create("line_chart_3");
// Add XAxis and YAxis
sciChartSurface.xAxes.add(new SciChart.NumericAxis(wasmContext));
sciChartSurface.yAxes.add(new SciChart.NumericAxis(wasmContext));
// Create a Heatmap Data-series. Pass heatValues as a number[][] to the UniformHeatmapDataSeries
var initialZValues: number[][] = iterate(WIDTH, HEIGHT, 200, 0, MAX_SERIES);
var heatmapDataSeries = new SciChart.UniformHeatmapDataSeries(wasmContext,
{
xStart: 100,
xStep: 1,
yStart: 100,
yStep: 1,
zValues: initialZValues
});
// Create a Heatmap RenderableSeries with the color map. ColorMap.minimum/maximum defines the values in
// HeatmapDataSeries which correspond to gradient stops at 0..1
var heatmapSeries = new SciChart.UniformHeatmapRenderableSeries(wasmContext,
{
dataSeries: heatmapDataSeries,
colorMap: new SciChart.HeatmapColorMap(
{
minimum: 0,
maximum: 200,
gradientStops:
[
{ offset: 0, color: "#00008B" },
{ offset: 0.2, color: "#6495ED" },
{ offset: 0.4, color: "#006400" },
{ offset: 0.6, color: "#7FFF00" },
{ offset: 0.8, color: "#FFFF00" },
{ offset: 1.0, color: "#FF0000" }
]
})
});
The above code is arising error on: var initialZValues: number[][] = iterate(WIDTH, HEIGHT, 200, 0, MAX_SERIES);
Please help.
The following line of code is Typescript
var initialZValues: number[][] = iterate(WIDTH, HEIGHT, 200, 0, MAX_SERIES);
remove the : number[][] and it should run.

Code efficiency using VectorGrid in Leaflet

I have about 7 000 polygons in a GeoJSON file using VectorGrid, all is fine using one layer but I need to split this layer into 10 LayerGroups (10 regions with their own polygons). How can this be done without rewriting the code 10 times? That seems to be lots of waste, there must be a smarter way and I can't figure it out. This is the code Im testing with, the highlight has to be working with all 11 layers...
var all_regions = new L.layerGroup();
var region_1 = new L.layerGroup();
var region_2 = new L.layerGroup();
var region_3 = new L.layerGroup();
/* snip */
var region_10 = new L.layerGroup();
var highlight_polygon;
var clearHighlight = function () {
if (highlight_polygon) {
vectorGrid.resetFeatureStyle(highlight_polygon);
}
highlight_polygon = null;
};
var vectorTileOptions_allRegions = {
rendererFactory: L.canvas.tile,
maxNativeZoom: 13,
zIndex: 6,
vectorTileLayerStyles: {
sliced: {
weight: 2,
color: "gray",
opacity: 1,
fill: false,
//fillColor: 'white',
//stroke: true,
fillOpacity: 0,
},
},
interactive: true,
getFeatureId: function (f) {
return f.properties.id;
},
};
var vectorTileOptions_region_1 = {
rendererFactory: L.canvas.tile,
maxNativeZoom: 13,
zIndex: 6,
vectorTileLayerStyles: {
sliced: function (properties, zoom) {
var region = properties.region;
if (region === "region one") {
return {
weight: 2,
color: "gray",
opacity: 1,
fill: false,
//fillColor: 'white',
//stroke: true,
fillOpacity: 0,
};
} else {
return {
weight: 0,
opacity: 0,
fill: false,
stroke: false,
fillOpacity: 0,
interactive: false,
};
}
},
},
interactive: true,
getFeatureId: function (f) {
return f.properties.id;
},
};
// Next vectorTileOptions until all 11 of them....
$.getJSON("/data/regions.geojson", function (json) {
//Not sure this is the correct way doing it...
var vectorGrid = L.vectorGrid
.slicer(json, vectorTileOptions_allRegions, vectorTileOptions_region_1)
.on("click", function (e) {
var properties = e.layer.properties;
L.popup()
.setContent(
"<b>Name</b>: " +
properties.region_name +
"<br><b>Date</b>: " +
"<i>" +
properties.date +
"</i>"
)
.setLatLng(e.latlng)
.openOn(map);
clearHighlight();
highlight_polygon = e.layer.properties.id;
vectorGrid.setFeatureStyle(highlight_polygon, {
weight: 3,
color: "gray",
opacity: 1,
fillColor: "#ff9999",
fill: true,
radius: 6,
fillOpacity: 0.3,
});
L.DomEvent.stop(e);
});
var clearHighlight = function () {
if (highlight_polygon) {
vectorGrid.resetFeatureStyle(highlight_polygon);
}
highlight_polygon = null;
map.on("popupclose", clearHighlight);
};
//This will not work....
vectorGrid.addTo(all_regions);
vectorGrid.addTo(region_1);
});
You probably want to do something like...
var regions = []; // An array that will hold instances of VectorGrid
var vectorGridOptions = {
rendererFactory: L.canvas.tile,
maxNativeZoom: 13,
zIndex: 6,
vectorTileLayerStyles: {
sliced: {}, // Empty, because it shall be overwritten later.
},
};
var defaultStyle = {
stroke: true,
weight: 2,
};
var regionStyles = [];
regionStyles[0] = {
weight: 2,
color: "gray",
};
regionStyles[1] = {
weight: 1,
color: "red",
};
/* ...etc, up to regionStyles[9] */
fetch("/data/regions.geojson")
.then(function (response) { return response.json(); })
.then(function (json) {
// For each number between 0 and 9...
for (var i = 0; i <= 9; i++) {
// Assuming that the GeoJSON data holds a FeatureCollection,
// create a copy of said GeoJSON FeatureCollection, but holding only
// the wanted features.
// See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter
var filteredGeoJSON = {
type: "FeatureCollection",
features: json.features.filter(function (feature) {
// This assumes that each Feature has a "regionID" property with a
// numeric value between 0 and 9.
return feature.properties.regionID === i;
}),
};
// Build up the options for the i-th VectorGrid by merging stuff together.
// See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign
var fullRegionStyle = Object.assign({}, defaultStyle, regionStyles[i]);
// Overwrite some stuff in vectorGridOptions. Note that this changes the value of
// a piece of vectorGridOptions at each pass of the loop.
vectorGridOptions.vectorTileLayerStyles.sliced = fullRegionStyle;
regions[i] = L.vectorGrid.slicer(filteredGeoJSON, vectorTileOptions);
regions[i].addTo(map);
}
});
The key points here are:
Use a loop to iterate from 1 through 10
Keep things in numbered arrays instead of similarly-named variables
Filter the FeatureCollection, so each VectorGrid works with less data. Drawing invisible polygons/polylines would take as much computing time as drawing visible ones.
Refactor as much as possible, then build up concrete data structures (Object.assign, clone objects if needed)

Is there a option to use gradient as fillcolor in geoShapes?

I need to use a gradient as fill color in an geoShape on a here map.
Is there any option to do this?
if i use something like this:
// init HereMap
let platform = new H.service.Platform({
'app_id': '111',
'app_code': '111-111',
useCIT: true,
useHTTPS: false
});
let defaultLayers = this.platform.createDefaultLayers();
let map = new H.Map(
this.mapElement.nativeElement,
defaultLayers.terrain.base,
{
zoom: 6,
center: { lat: 51.22172, lng: 6.77616 }
}
);
let behavior = new H.mapevents.Behavior(new H.mapevents.MapEvents(this.map));
let ui = H.ui.UI.createDefault(this.map, defaultLayers, 'de-DE');
// set geoShape style
let customStyle = {
strokeColor: 'none',
fillColor: 'linear-gradient(90deg, rgba(2,0,36,1) 0%, rgba(0,212,255,1) 100%)',
lineWidth: 10,
lineCap: 'square',
lineJoin: 'bevel'
};
// Create a rectangle and pass the custom style as an options parameter:
var rect = new H.map.Rect(new H.geo.Rect(53.5, 12.5, 51.5, 14.5),
{ style: customStyle });
// Add the rectangle to the map:
this.map.addObject(rect);
// Zoom the map to fit the rectangle:
this.map.setViewBounds(rect.getBounds());
i get only a black object ...
thanks your help :)
As per the documentation please use the color name or RGB format to enter fillcolor values.
var customStyle = {
strokeColor: 'black',
fillColor: 'rgba(255, 255, 255, 0.5)',
lineWidth: 10,
lineCap: 'square',
lineJoin: 'bevel'
};
**fillColor** The color with which a shape's area will be filled (ignored for polylines)
https://developer.here.com/documentation/maps/dev_guide/topics/geo-shapes.html

Fabric.js line rendering when resizing object

Have an issue with line rendering when resizing object.
I've locked line endings positions to exact point on circles and when moving, scaling, rotating etc I have to edit lines connected to current circle.
Here is fiddle
Just try to resize circles and at some point you'll see that rendering is crashed a bit which corresponds to lines. Need a help for it, maybe rerender or something.
Or that's an issue of fabric.js
var circlesData = [{
id: 1,
x: 80,
y: 80,
r: 60
}, {
id: 2,
x: 440,
y: 190,
r: 90
}];
var connectionsData = [{
from: {id: 1, angle: 0, rdist: .8},
to: {id: 2, angle: 0, rdist: .4},
}]
var fcircles = [];
var fconnections = [];
var fcanvas;
init();
function init() {
fcanvas = new fabric.Canvas('c', {
imageSmoothingEnabled: false,
allowTouchScrolling: true,
});
fcanvas.preserveObjectStacking = true;
fcanvas.selection = false;
fcanvas.setBackgroundColor('#fff');
fcircles = circlesData.map(function(circleData) {
var circle = new fabric.Circle({
left: circleData.x,
top: circleData.y,
radius: circleData.r,
fill: 'rgba(100,100,255,0.2)',
originX: 'center',
originY: 'center'
});
circle.initialData = circleData;
circle.setControlsVisibility({
mt: false,
mb: false,
ml: false,
mr: false,
mtr: false,
});
return circle;
});
fconnections = connectionsData.map(function(connectionData) {
var line = new fabric.Line([0,0,0,0], {
strokeWidth: 6,
strokeLineCap: 'round',
fill: 'red',
stroke: 'red',
originX: 'center',
originY: 'center'
});
line.from = copyJson(connectionData.from);
line.to = copyJson(connectionData.to);
line.selectable = false;
return line;
});
fcircles.concat(fconnections).forEach(function(fobj){
fcanvas.add(fobj)
});
updateConnections(fconnections);
fcanvas.renderAll();
console.log(fcanvas.getObjects())
fcanvas.on('object:moving', onObjChange);
fcanvas.on('object:scaling', onObjChange);
fcanvas.on('object:rotating', onObjChange);
}
function onObjChange(e) {
if(['line'].indexOf(e.target.type) > -1) {
return;
}
var circle = e.target;
updateConnections(fconnections.filter(function(fconnection){
return fconnection.from.id === e.target.initialData.id || fconnection.to.id === e.target.initialData.id;
}))
}
function updateConnections(fconnections) {
fconnections.forEach(function(fconnection) {
var from = fcircles.filter(function(c){return c.initialData.id === fconnection.from.id})[0];
var to = fcircles.filter(function(c){return c.initialData.id === fconnection.to.id})[0];
var fromAngle = fconnection.from.angle - from.angle / 180 * Math.PI;
var toAngle = fconnection.to.angle - from.angle / 180 * Math.PI;
debugger;
fconnection.set({
x1: from.left + fconnection.from.rdist * from.radius * Math.cos(fromAngle),
y1: from.top + fconnection.from.rdist * from.radius * Math.sin(fromAngle),
x2: to.left + fconnection.to.rdist * to.radius * Math.cos(toAngle),
y2: to.top + fconnection.to.rdist * to.radius * Math.sin(toAngle)
});
fconnection.setCoords();
});
}
function copyJson(obj) {
return JSON.parse(JSON.stringify(obj));
}
Add to your Line object property:
objectCaching: false
From fabricjs documentation:
objectCaching :Boolean When true, object is cached on an additional
canvas. default to true since 1.7.0

How to use progressBar.js to draw a circle within a circle?

I am using progressBar.Circle, and this is my code that draws a single circle:
function AnimateCircle(container_id, animatePercentage,type) {
var startColor = '#FFFFFF';
var endColor = '#F18F01';
var element = document.getElementById(container_id);
var circle = new ProgressBar.Circle(element, {
color: startColor,
trailColor: '#eee',
trailWidth: 3,
duration: 1400,
easing: 'easeInOut',
strokeWidth: 3,
text: {
value: "<h4>"+type+"</h4>"+ "<h4>"+(animatePercentage )*10+ "</h1>",
className: 'progressbar__label'
},
// Set default step function for all animate calls
step: function (state, circle) {
circle.path.setAttribute('stroke', state.color);
}
});
circle.animate(animatePercentage, {
from: {
color: startColor
},
to: {
color: endColor
}
});
circle.path.style.strokeLinecap = 'round';
}
Is there a way for me to draw another circle within it? That would result in something similar to this:

Categories

Resources