Leaflet geofence on multiple circles ... detecting marker inside / outside - geolocation

I have some code that detects when the market is dragged inside and outside of a circle.
This works great but I was just wondering how I can have one market and multiple circles detected instead of just one.
Here is the current code:
var mymap = L.map('mapid', {
center: [50.895763, -1.150556],
zoom: 16
});
L.tileLayer('https://api.tiles.mapbox.com/v4/{id}/{z}/{x}/{y}.png?access_token=pk.eyJ1Ijoic3RldmVuc2F0Y2giLCJhIjoiY2p5eDR6MWgzMHRvbjNocnJkN2d2MjRwaSJ9.wd0OtBUQQfUtNxdduQA3lg', {
maxZoom: 18,
attribution: 'Map data © OpenStreetMap contributors, ' +
'CC-BY-SA, ' +
'Imagery © Mapbox',
id: 'mapbox.streets'
}).addTo(mymap);
var marker = new L.marker([50.896422, -1.148444],{
draggable: true,
autoPan: true
}).addTo(mymap);
var circle = L.circle([50.895763, -1.150556], {
color: 'red',
fillColor: '#f03',
fillOpacity: 0.5,
radius: 100
}).addTo(mymap);
marker.on('drag', function(e) {
var d = mymap.distance(e.latlng, circle.getLatLng());
var isInside = d < circle.getRadius();
circle.setStyle({
fillColor: isInside ? 'green' : '#f03'
})
});
But I would like to add multiple circles instead of just one.
How can I do this?

Put the circles in an array and forEach() over them with the radius test - something like this (substitute your own method of setting up the circles)
var mymap = L.map("mapid", {
center: [50.895763, -1.150556],
zoom: 16
});
L.tileLayer(
"https://api.tiles.mapbox.com/v4/{id}/{z}/{x}/{y}.png?access_token=pk.eyJ1Ijoic3RldmVuc2F0Y2giLCJhIjoiY2p5eDR6MWgzMHRvbjNocnJkN2d2MjRwaSJ9.wd0OtBUQQfUtNxdduQA3lg",
{
maxZoom: 18,
attribution:
'Map data © OpenStreetMap contributors, ' +
'CC-BY-SA, ' +
'Imagery © Mapbox',
id: "mapbox.streets"
}
).addTo(mymap);
var marker = new L.marker([50.896422, -1.148444], {
draggable: true,
autoPan: true
}).addTo(mymap);
var circles = [];
circles[0] = L.circle([50.895763, -1.150556], {
color: "red",
fillColor: "#f03",
fillOpacity: 0.5,
radius: 100
}).addTo(mymap);
circles[1] = L.circle([some - other - coordinates], {
color: "red",
fillColor: "#f03",
fillOpacity: 0.5,
radius: 100
}).addTo(mymap);
marker.on("drag", function(e) {
circles.forEach(function(circle) {
var d = mymap.distance(e.latlng, circle.getLatLng());
var isInside = d < circle.getRadius();
circle.setStyle({
fillColor: isInside ? "green" : "#f03"
});
});
});

Related

Is it possible to rotate a group after we drag drop the certain object onto them in konvajs?

I'm trying to animate the weighing machine i.e. if the user drag and drops the balls on the weights of the machine, the machine should move according to the weights of the balls afterward.
The weighing machine would not be animated from the start but will move when the user puts some balls on either side of the machine.
I'm using konvajs, how can I make this possible?
I used the following approach to solve the above-given problem.
function createCanvas(){
var width = window.innerWidth;
var height = window.innerHeight;
var leftBalls = 0;
var rightBalls = 0;
var tries = 0;
//Initialize stage
var stage = new Konva.Stage({
container: 'container',
width: width,
height: height,
});
//Initialize Layer
var layer = new Konva.Layer();
stage.add(layer)
//Create output
var output = new Konva.Text({
x: (width/2)-134,
y: 140,
fontSize: 35,
fontFamily: 'Calibri',
});
layer.add(output);
// win text
var wintext = new Konva.Text({
x: (width/2)-134,
y: 70,
fontSize: 35,
fontFamily: 'Calibri',
});
layer.add(wintext);
// tries box
var triesText1 = new Konva.Text({
x: width-100,
y: 4,
text: "No. of tries",
fontSize: 20,
fontFamily: 'Calibri',
});
layer.add(triesText1);
var triesBox = new Konva.Rect({
x: width-90,
y: 25,
width: 70,
height: 50,
fill: 'white',
stroke: 'black',
strokeWidth: 3,
});
layer.add(triesBox);
var triesText2 = new Konva.Text({
x: width-62,
y: 36,
text: '0',
fontSize: 30,
fontFamily: 'Calibri',
});
layer.add(triesText2);
//Create Weighing Machine
var oval = new Konva.Ellipse({
x: ((width/2))+15,
y: (height-170),
radiusX: 3,
radiusY: 65,
fill: 'black',
stroke: 'black',
strokeWidth: 3,
});
layer.add(oval);
var ovalTwo = new Konva.Ellipse({
x: ((width/2))+15,
y: (height-200),
radiusX: 100,
radiusY: 3,
fill: 'black',
stroke: 'black',
strokeWidth: 3,
});
//layer.add(ovalTwo);
var LineOne = new Konva.Line({
x: (width/2)-47,
y: height-201,
stroke: 'black',
strokeWidth: 5,
points: [0,0,32,75],
});
//layer.add(LineOne);
var LineTwo = new Konva.Line({
x: (width/2)-47,
y: height-201,
stroke: 'black',
strokeWidth: 5,
points: [0,0,-33,73],
});
//layer.add(LineTwo);
var semiCircle1= new Konva.Arc({
x: (width/2)-48,
y: height-130,
innerRadius: 30,
outerRadius: 40,
angle: 180,
fill: 'black',
stroke: 'black',
strokeWidth: 1,
});
//layer.add(semiCircle);
var LineThree = new Konva.Line({
x: (width/2)+91,
y: height-201,
stroke: 'black',
strokeWidth: 5,
points: [0,0,32,75],
});
//layer.add(LineThree);
var LineFour = new Konva.Line({
x: (width/2)+91,
y: height-201,
stroke: 'black',
strokeWidth: 5,
points: [0,0,-33,73],
});
//layer.add(LineFour);
var semiCircle2= new Konva.Arc({
x: (width/2)+89,
y: height-130,
innerRadius: 30,
outerRadius: 40,
angle: 180,
fill: 'black',
stroke: 'black',
strokeWidth: 1,
});
//layer.add(semiCircle);
var wUpperPart = new Konva.Group({
x: 0,
y: 0,
});
wUpperPart.add(semiCircle1,semiCircle2,LineOne,LineTwo,LineThree,LineFour,ovalTwo);
layer.add(wUpperPart)
function moveMachineLeft(){
var tween = new Konva.Tween({
node: wUpperPart,
duration: 2,
rotation: -1.7,
easing: Konva.Easings.BackEaseOut,
onFinish: function () {
writeMessage('tween finished!');
},
});
setTimeout(function () {
tween.play();
}, 10);
}
function moveMachineRight(){
var tween = new Konva.Tween({
node: wUpperPart,
duration: 2,
rotation: 1.7,
easing: Konva.Easings.BackEaseOut,
onFinish: function () {
writeMessage('tween finished!');
},
});
setTimeout(function () {
tween.play();
}, 100);
}
//Create circle
function createCircle(x, y, fill, id) {
var circle = new Konva.Circle({
x: x,
y: y,
radius: 13,
fill: fill,
stroke: 'black',
strokeWidth: 1,
id: id,
draggable: true,
});
layer.add(circle);
var startPos = 0;
circle.on('dragstart',function() {
startPos = stage.getPointerPosition();
});
circle.on('dragend', function() {
const pointerPos = stage.getPointerPosition();
console.log(pointerPos);
console.log((width/2)+70);
console.log((width/2)+111);
if ((pointerPos.x <= (width/2)-33 && pointerPos.x >= (width/2)-85) &&
pointerPos.y<=height-103 && pointerPos.y>=height-155){
leftBalls = circle.id() + leftBalls;
console.log(leftBalls);
}
else if ((pointerPos.x >= (width/2)+67 && pointerPos.x <= (width/2)+111) &&
(pointerPos.y<=height-103 && pointerPos.y>=height-155)){
rightBalls = rightBalls + circle.id();
console.log(rightBalls);
}
if (((startPos.x >= (width/2)+67 && startPos.x <= (width/2)+111) &&
startPos.y<=height-103 && startPos.y>=height-150) &&
!((pointerPos.x >= (width/2)+67 && pointerPos.x <= (width/2)+111) &&
(pointerPos.y<=height-103 && pointerPos.y>=height-155))){
rightBalls = rightBalls - circle.id();
console.log(rightBalls);
}
if (((startPos.x <= (width/2)-33 && startPos.x >= (width/2)-85) &&
startPos.y<=height-103 && startPos.y>=height-150) &&
!((pointerPos.x <= (width/2)-33 && pointerPos.x >= (width/2)-85) &&
(pointerPos.y<=height-103 && pointerPos.y>=height-155))){
leftBalls = leftBalls - circle.id();
console.log(leftBalls);
}
});
return circle;
}
//Create balls
var id = 0;
var thousands = {};
var x = []
var boolean = [];
var i = 0;
for (i = 320; i < 470; i += 30){
x.push(i)
boolean.push(false)
circle = createCircle(i, 70, '#FF0000', 1);
thousands[id] = circle;
id = id + 1;
}
x.push(i);
circle = createCircle(i, 70, '#FF0000', 2);
thousands[id] = circle;
id = id + 1;
i = i + 30;
for (; i < 540; i += 30){
x.push(i)
boolean.push(false)
circle = createCircle(i, 70, '#FF0000', 1);
thousands[id] = circle;
id = id + 1;
}
document.getElementById('calculate').addEventListener(
'click',
function () {
if (leftBalls>rightBalls){
output.text("Left weight is heavier!");
if (leftBalls==2 && rightBalls==1){
wintext.text("You Won!");
}
tries = tries + 1;
triesText2.text(tries);
}
else if (leftBalls<rightBalls){
output.text("Right weight is heavier!");
if (rightBalls==2 && leftBalls==1){
wintext.text("You Won!");
}
tries = tries + 1;
triesText2.text(tries);
}
else if (leftBalls==rightBalls){
output.text("No weight is heavier!");
tries = tries + 1;
triesText2.text(tries);
}
else if ((leftBalls==0) && (rightBalls==0)){
output.text("No weight is filled!");
}
layer.draw();
},
false
);
layer.draw();
}
createCanvas();
document.getElementById('restart').addEventListener(
'click',
function () {
createCanvas();
},
false
);

Konvajs: Create a draggable area with some constraints on one of the childs

I'm creating a timeline with Konva and the entire timeline (stage) is draggable on all directions but I have an axis with all the years of the timeline (Konva group) that I want to restrict its movement so that it only moves horizontally.
I can't use dragBoundFunc as it will restrict the movement on all nodes of the timeline.
I tried to change the position of the element using the dragmove event:
stage.on("dragmove", function(evt) {
xaxis.y(0);
});
But the xaxis still moves on all direction while dragging the stage.
I could also use different draggable layers for the axis and the timeline itself, but then when I drag the axis it wouldn't move the timeline and the same if I move the timeline.
As the simplest solution, you can just make sure that the absolute position of your timelime group is the same:
stage.on("dragmove", function(evt) {
// read absolute position
const oldAbs = xaxis.absolutePosition();
// set new absolute position, but make sure x = 0
xaxis.absolutePosition({
x: oldAbs.x,
y: 0
});
});
Here is a slightly more capable version that allows vertical drag of the event layer whilst keeping the time line axis visible for reference. This uses two layers - one to act as the background containing the time line and grid, whilst the second shows the events.
The key technique here is using the dragMove event listener on the draggable event layer to move the background layer in sync horizontally but NOT vertically. Meanwhile the event layer is also constrained with a dragBound function to stop silly UX.
An improvement would be to add clipping to the event layer so that when dragged down it would not obscure the timeline.
var stageWidth = 800,
stageHeight = 300,
timeFrom = 1960,
timeTo = 2060,
timeRange = timeTo - timeFrom,
timeLineWidth = 1000,
timeSteps = 20, // over 100 yrs = 5 year intervals
timeInt = timeRange / timeSteps,
timeLineStep = timeLineWidth / timeSteps,
yearWidth = timeLineWidth / timeRange,
plotHeight = 500,
events = [{
date: 1964,
desc: 'Born',
dist: 10
},
{
date: 1966,
desc: 'England win world cup - still celebrating !',
dist: 20
},
{
date: 1968,
desc: 'Infant school',
dist: 30
},
{
date: 1975,
desc: 'Secondary school',
dist: 50
},
{
date: 1981,
desc: 'Sixth form',
dist: 7
},
{
date: 1983,
desc: 'University',
dist: 30
},
{
date: 1986,
desc: 'Degree, entered IT career',
dist: 50
},
{
date: 1990,
desc: 'Marriage #1',
dist: 0
},
{
date: 1996,
desc: 'Divorce #1',
dist: 0
},
{
date: 1998,
desc: 'Marriage #2 & Son born',
dist: 90
},
{
date: 2000,
desc: 'World did not end',
dist: 20
},
{
date: 2025,
desc: 'Retired ?',
dist: 0
},
{
date: 2044,
desc: 'Enters Duncodin - retirement home for IT workers',
dist: 0
},
{
date: 2054,
desc: 'Star dust',
dist: 0
}
]
function setup() {
// Set up a stage and a shape
stage = new Konva.Stage({
container: 'konva-stage',
width: stageWidth,
height: stageHeight
});
// bgLayer is the background with the grid, timeline and date text.
var bgLayer = new Konva.Layer({
draggable: false
})
stage.add(bgLayer);
for (var i = 0, max = timeSteps; i < max; i = i + 1) {
bgLayer.add(new Konva.Line({
points: [(i * timeLineStep) + 0.5, 0, (i * timeLineStep) + .5, plotHeight],
stroke: 'cyan',
strokeWidth: 1
}))
bgLayer.add(new Konva.Text({
x: (i * timeLineStep) + 4,
y: 260,
text: timeFrom + (timeInt * i),
fontSize: 12,
fontFamily: 'Calibri',
fill: 'magenta',
rotation: 90,
listening: false
}));
}
for (var i = 0, max = plotHeight; i < max; i = i + timeLineStep) {
bgLayer.add(new Konva.Line({
points: [0, i + 0.5, timeLineWidth, i + .5],
stroke: 'cyan',
strokeWidth: 1
}))
}
// add timeline
var timeLine = new Konva.Rect({
x: 0,
y: 245,
height: 1,
width: timeLineWidth,
fill: 'magenta',
listening: false
});
bgLayer.add(timeLine)
// eventLayer contains only the event link line and text.
var eventLayer = new Konva.Layer({
draggable: true,
// the dragBoundFunc returns an object as {x: val, y: val} in which the x is constricted to stop
// the user dragging out of sight, and the y is not allowed to change.
// ! position of bgLayer is moved in x axis in sync with eventLayer via dragMove event
dragBoundFunc: function(pos) {
return {
x: function() {
var retX = pos.x;
if (retX > 20) { // if the left exceeds 20px from left edge of stage
retX = 20;
} else if (retX < (stageWidth - (timeLineWidth + 50))) { // if the right exceeds 50 px from right edge of stage
retX = stageWidth - (timeLineWidth + 50);
}
return retX;
}(),
y: function() {
var retY = pos.y;
if (retY < 0) {
retY = 0;
} else if (retY > 200) {
retY = 200;
}
return retY;
}()
};
}
});
stage.add(eventLayer);
// ! position of bgLayer is moved in x axis in sync with eventLayer via dragMove event of eventLayer.
eventLayer.on('dragmove', function() {
var pos = eventLayer.position();
var bgPos = bgLayer.position();
bgLayer.position({
x: pos.x,
y: bgPos.y
}); // <--- move the bgLayer in sync with the event eventLayer.
stage.draw()
});
for (var i = 0, max = events.length; i < max; i = i + 1) {
var event = events[i];
var link = new Konva.Rect({
x: yearWidth * (event.date - timeFrom),
y: 200 - event.dist,
width: 1,
height: 55 + event.dist,
fill: 'magenta',
listening: false
});
eventLayer.add(link)
var eventLabel = new Konva.Text({
x: yearWidth * (event.date - timeFrom) - 5,
y: 190 - event.dist,
text: event.date + ' - ' + event.desc,
fontSize: 16,
fontFamily: 'Calibri',
fill: 'magenta',
rotation: -90,
listening: false
});
eventLayer.add(eventLabel);
var dragRect = new Konva.Rect({
x: 0,
y: 0,
width: timeLineWidth,
height: 500,
opacity: 0,
fill: 'cyan',
listening: true
});
eventLayer.add(dragRect);
dragRect.moveToTop()
}
stage.draw()
}
var stage, eventLayer;
setup()
.konva-stage {
width: 100%;
height: 100%;
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/konva/4.0.13/konva.js"></script>
<p>Drag the timeline left & right AND up & down...</p>
<div id="konva-stage"></div>
Just for fun, a stripped down version of my answers showing the ondrag() function without all the timeline frills.
var stage;
function setup() {
// Set up a stage and a shape
stage = new Konva.Stage({
container: 'konva-stage',
width: 600,
height: 300
});
// layer1.
var layer1 = new Konva.Layer({
draggable: false
})
stage.add(layer1);
var ln1 = new Konva.Line({
points: [10, 0, 10, 20, 10, 10, 0, 10, 20, 10],
stroke: 'cyan',
strokeWidth: 4
});
layer1.add(ln1);
var layer2 = new Konva.Layer({
draggable: true,
});
stage.add(layer2);
var ln2 = new Konva.Line({
points: [10, 0, 10, 20, 10, 10, 0, 10, 20, 10],
stroke: 'magenta',
strokeWidth: 4
});
layer2.add(ln2);
// position the crosses on the canvas
ln1.position({
x: 100,
y: 80
});
ln2.position({
x: 100,
y: 40
});
// ! position of layer1 is moved in x axis in sync with layer2 via dragMove event of layer2.
layer2.on('dragmove', function() {
var pos = layer2.position();
var bgPos = layer1.position();
layer1.position({
x: pos.x,
y: bgPos.y
}); // <--- move layer1 in sync with layer2.
stage.draw()
});
stage.draw()
}
setup()
.konva-stage {
width: 100%;
height: 100%;
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/konva/4.0.13/konva.js"></script>
<p>Drag the upper cross - only one moves vertically whilst the other is contrained in the y-axis. Both move in sync on the x-axis</p>
<div id="konva-stage"></div>
It is not entirely clear what you are asking but I have assumed you want to constrain the drag of the timeline so that it gives good UX. See working snippet below. The majority of the code is setup of the timeline. The important piece is
Include a rect covering the entire timeline that has zero opacity and is listening for mouse events.
Provide the layer with a dragBoundFunc that returns an object as {x: val, y: val} in which the x is constricted to stop the user dragging out of sight horizontally, and the y is not allowed to change. If you think of the rect and the stage as rectangles then the math is not difficult to comprehend. If your timeline is vertical, swap the x & y behaviour.
var stageWidth = 800,
timeFrom = 1960,
timeTo = 2060,
range = timeTo - timeFrom,
timeLineWidth = 1000;
yearWidth = timeLineWidth / range,
events = [{
date: 1964,
desc: 'Born'
},
{
date: 1968,
desc: 'Infant school'
},
{
date: 1975,
desc: 'Secondary school'
},
{
date: 1981,
desc: 'Sixth form'
},
{
date: 1983,
desc: 'University'
},
{
date: 1986,
desc: 'Degree, entered IT career'
},
{
date: 1990,
desc: 'Marriage #1'
},
{
date: 1998,
desc: 'Marriage #2'
},
{
date: 1999,
desc: 'Son born'
},
{
date: 2025,
desc: 'Retired ?'
},
{
date: 2044,
desc: 'Enters Duncodin - retirement home for IT workers'
},
{
date: 2054,
desc: 'Star dust'
}
]
function setup() {
// Set up a stage and a shape
stage = new Konva.Stage({
container: 'konva-stage',
width: stageWidth,
height: 500
});
layer = new Konva.Layer({
draggable: true,
// the dragBoundFunc returns an object as {x: val, y: val} in which the x is constricted to stop
// the user dragging out of sight, and the y is not allowed to change.
dragBoundFunc: function(pos) {
return {
x: function() {
retX = pos.x;
if (retX > 20) {
retX = 20;
} else if (retX < (stageWidth - (timeLineWidth + 50))) {
retX = stageWidth - (timeLineWidth + 50);
}
return retX;
}(),
y: this.absolutePosition().y
};
}
});
stage.add(layer);
// add timeline
var timeLine = new Konva.Rect({
x: 0,
y: 245,
height: 10,
width: timeLineWidth,
fill: 'magenta',
listening: false
});
layer.add(timeLine)
for (var i = 0, max = events.length; i < max; i = i + 1) {
var event = events[i];
var link = new Konva.Rect({
x: yearWidth * (event.date - timeFrom),
y: 200,
width: 5,
height: 55,
fill: 'magenta',
listening: false
});
layer.add(link)
var timeLabel = new Konva.Text({
x: yearWidth * (event.date - timeFrom) + 10,
y: 265,
text: event.date,
fontSize: 16,
fontFamily: 'Calibri',
fill: 'magenta',
rotation: 90,
listening: false
});
layer.add(timeLabel);
var eventLabel = new Konva.Text({
x: yearWidth * (event.date - timeFrom) - 5,
y: 190,
text: event.desc,
fontSize: 16,
fontFamily: 'Calibri',
fill: 'magenta',
rotation: -90,
listening: false
});
layer.add(eventLabel);
var dragRect = new Konva.Rect({
x: 0,
y: 0,
width: timeLineWidth,
height: 500,
opacity: 0,
fill: 'cyan',
listening: true
});
layer.add(dragRect);
dragRect.moveToTop()
}
stage.draw()
}
var stage, layer;
setup()
.konva-stage {
width: 100%;
height: 100%;
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/konva/4.0.13/konva.js"></script>
<p>Drag the timeline...</p>
<div id="konva-stage"></div>

how to draw line between two cliked points using Open Layer 3?

i can display json lat and lon in map but i want draw lines between two selected points.
like this Here
here i can click all place in Map but i want enable click only displayed points only.
i used this link to display my points Link2 now i want draw lines between two points
<script>
var flickrSource = new ol.source.Vector();
function flickrStyle(feature) {
var style = new ol.style.Style({
image: new ol.style.Circle({
radius: 10,
stroke: new ol.style.Stroke({
color: 'white',
width: 2
}),
fill: new ol.style.Fill({
color: 'green'
}),
}),
text: new ol.style.Text({
text: feature.getGeometryName(),
fill: new ol.style.Fill({color: 'blue'}),
stroke: new ol.style.Stroke({color: 'white', width: 1}),
offsetX: 0,
offsetY: 15
}),
});
return [style];
}
var flickrLayer = new ol.layer.Vector({
source: flickrSource,
style: flickrStyle
});
var layer = new ol.layer.Tile({
source: new ol.source.OSM()
});
var center = ol.proj.transform([-1.812, 52.443], 'EPSG:4326', 'EPSG:3857');
var view = new ol.View({
center: center,
zoom: 3
});
var source = new ol.source.Vector({wrapX: false});
var map = new ol.Map({
target: 'map',
layers: [layer, flickrLayer],
view: view
});
function successHandler(data) {
var transform = ol.proj.getTransform('EPSG:4326', 'EPSG:3857');
data.items.forEach(function(item) {
var feature = new ol.Feature(item);
feature.setGeometryName(item.name);
var coordinate = transform([parseFloat(item.longitude), parseFloat(item.latitude)]);
var geometry = new ol.geom.Point(coordinate);
feature.setGeometry(geometry);
flickrSource.addFeature(feature);
});
}
</script>
Get the co-ordinates of this two points and draw LineString
var thing = new ol.geom.LineString(points);
var featurething = new ol.Feature({
name: "Thing",
geometry: thing
});
flickrSource.addFeature(featurething);
var flickrSource = new ol.source.Vector();
var data = {
"items": [{
name: 'geo1',
longitude: "0.0",
latitude: "0.0"
}, {
name: 'geo1',
longitude: "5.0",
latitude: "5.0"
}]
};
function flickrStyle(feature) {
var style = new ol.style.Style({
image: new ol.style.Circle({
radius: 10,
stroke: new ol.style.Stroke({
color: 'white',
width: 2
}),
fill: new ol.style.Fill({
color: 'green'
}),
}),
text: new ol.style.Text({
text: feature.getGeometryName(),
fill: new ol.style.Fill({
color: 'blue'
}),
stroke: new ol.style.Stroke({
color: 'white',
width: 1
}),
offsetX: 0,
offsetY: 15
}),
});
return [style];
}
var flickrLayer = new ol.layer.Vector({
source: flickrSource
//style: flickrStyle
});
var layer = new ol.layer.Tile({
source: new ol.source.OSM()
});
var center = ol.proj.transform([0.0, 0.0], 'EPSG:4326', 'EPSG:3857');
var view = new ol.View({
center: center,
zoom: 5
});
var source = new ol.source.Vector({
wrapX: false
});
var map = new ol.Map({
target: 'map',
layers: [layer, flickrLayer],
view: view
});
function successHandler(data) {
var points = [];
data.items.forEach(function(item) {
var point = ol.proj.transform([parseFloat(item.longitude), parseFloat(item.latitude)], 'EPSG:4326', 'EPSG:3857');
points.push(point);
var geometry = new ol.geom.Point(point);
var feature = new ol.Feature({
name: item.name,
geometry: geometry
});
flickrSource.addFeature(feature);
var thing = new ol.geom.LineString(points);
var featurething = new ol.Feature({
name: "Thing",
geometry: thing
});
flickrSource.addFeature(featurething);
});
}
successHandler(data);
<link href="https://cdnjs.cloudflare.com/ajax/libs/ol3/3.20.1/ol.css" rel="stylesheet" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/ol3/3.20.1/ol.js"></script>
<div id="map"></div>
Here is the code...
Here is the vector source, layers and map:
// Vector source of data points
var flickrSource = new ol.source.Vector();
// Style function for the data points
function flickrStyle(feature) {
var style = new ol.style.Style({
image: new ol.style.Circle({
radius: 10,
stroke: new ol.style.Stroke({
color: 'white',
width: 2
}),
fill: new ol.style.Fill({
color: 'green'
})
}),
text: new ol.style.Text({
text: feature.getGeometryName(),
fill: new ol.style.Fill({color: 'blue'}),
stroke: new ol.style.Stroke({color: 'white', width: 1}),
offsetX: 0,
offsetY: 15
})
});
return [style];
}
// Layers
var osmLayer = new ol.layer.Tile({ source: new ol.source.OSM() });
var flickrLayer = new ol.layer.Vector({
source: flickrSource,
style: flickrStyle
});
// MAP
var map = new ol.Map({
target: 'map',
layers: [osmLayer, flickrLayer],
view: new ol.View({
center: ol.proj.transform([0, 20], 'EPSG:4326', 'EPSG:3857'),
zoom: 3
})
});
Then here is the data points and placing them on the map:
// Data points
var data = {
"items": [{
name: 'p1',
longitude: "0.0",
latitude: "0.0"
}, {
name: 'p2',
longitude: "50.0",
latitude: "50.0"
}, {
name: 'p3',
longitude: "50.0",
latitude: "-50.0"
}]
};
// Placing data points on the map
function placePoints(data) {
var transform = ol.proj.getTransform('EPSG:4326', 'EPSG:3857');
data.items.forEach( function(item) {
// for each item of data points we create feature geometry
// with coords contained in data and add them to the source
var feature = new ol.Feature(item);
feature.setGeometryName(item.name);
var coordinate = transform(
[parseFloat(item.longitude), parseFloat(item.latitude)]
);
var geometry = new ol.geom.Point(coordinate);
feature.setGeometry(geometry);
flickrSource.addFeature(feature);
} );
}
placePoints(data); // do the stuff of placing points
And then the interaction for drawing the lines between points:
// select interaction working on "click"
var mySelectInteraction = new ol.interaction.Select({
condition: ol.events.condition.click,
multi: false
});
// init coords of line to draw between points
var pointA = null;
var pointB = null;
// Interaction on points for drawing lines between
mySelectInteraction.on('select', function(e) {
if (e.selected.length === 0) {
// clicking nothing, so reset points coords
pointA = null;
pointB = null;
}
else {
// Feature clicked and its coords
var feature = e.target.getFeatures().item(0);
var coords = feature.getGeometry().getCoordinates();
// Definition of coords points
if (pointA === null) { pointA = coords; }
else { pointB = coords; }
if ( pointA !== null && pointB !== null) {
var LinesSource = new ol.source.Vector();
var LinesLayer = new ol.layer.Vector({ source : LinesSource });
map.addLayer( LinesLayer );
// Line construction
LinesSource.addFeature( new ol.Feature({
geometry : new ol.geom.LineString( [pointA, pointB] )
}) );
// Reset points for next drawing
pointA = null;
pointB = null;
}
}
});
map.addInteraction(mySelectInteraction);
Works great for me!

Resizing Annotation shapes

I am trying to create annotations in high charts and resizing the shapes on clicking inside a shape. I have created a js fiddle.
Run the jsfiddle: http://jsfiddle.net/1e1jnv7w/
HTML:
<h3>Add annotation via simple form</h3>
<div style="width: 1054px; float: left;">
<div id="container" style="float: left; height: 342px; width: 800px">
</div>
JAVASCRIPT:
$(function() {
var options = {
chart: {
borderWidth: 5,
borderColor: '#e8eaeb',
borderRadius: 0,
renderTo: 'container',
backgroundColor: '#f7f7f7',
//zoomType: 'x',
events: {
load: chartLoad
}
},
title: {
style: {
'fontSize': '1em'
},
useHTML: true,
x: -27,
y: 8,
text: '<span class="chart-title"> Drag and drop on a chart to add annotation <span class="chart-href"> Black Label </span> <span class="chart-subtitle">plugin by </span></span>'
},
annotationsOptions: {
enabledButtons: false
},
annotations: [{
title: {
text: '<span style="">drag me anywhere <br> dblclick to remove</span>',
style: {
color: 'red'
}
},
anchorX: "left",
anchorY: "top",
allowDragX: true,
allowDragY: true,
x: 515,
y: 55
}, {
title: 'drag me <br> horizontaly',
anchorX: "left",
anchorY: "top",
allowDragY: false,
allowDragX: true,
xValue: 3,
yValue: 10,
shape: {
type: 'path',
params: {
d: ['M', 0, 0, 'L', 110, 0],
stroke: '#c55'
}
}
}, {
title: 'on point <br> drag&drop <br> disabled',
linkedTo: 'high',
anchorX: "middle",
anchorY: "middle",
allowDragY: false,
allowDragX: false,
shape: {
type: 'circle',
params: {
r: 40,
stroke: '#c55'
}
}
}, {
x: 100,
y: 200,
title: 'drag me <br> verticaly',
anchorX: "left",
anchorY: "top",
allowDragY: true,
allowDragX: false,
shape: {
type: 'rect',
params: {
x: 0,
y: 0,
width: 55,
height: 40
}
}
}],
series: [{
data: [13, 4, 5, {
y: 1,
id: 'high'
},
2, 14, 3, 2, 11, 6
]
}]
};
var chart = new Highcharts.Chart(options, function(chart) {
var container = chart.container,
offsetX = chart.plotLeft - container.offsetLeft,
offsetY = chart.plotTop - container.offsetTop;
Highcharts.addEvent(container, 'mousedown', function(e) {
var isInside = chart.isInsidePlot(e.clientX - offsetX, e.pageY - offsetY);
});
});
function chartLoad() {
var chart = this,
container = chart.container,
annotations = chart.annotations.allItems,
annotation,
clickX,
clickY;
function getParams(e) {
function getRadius(e) {
var x = e.pageX - container.offsetLeft,
y = e.pageY - container.offsetTop,
dx = Math.abs(x - clickX),
dy = Math.abs(y - clickY);
return parseInt(Math.sqrt(dx * dx + dy * dy), 10);
}
function getPath(e) {
var x = e.pageX - container.offsetLeft,
y = e.pageY - container.offsetTop,
dx = x - clickX,
dy = y - clickY;
return ["M", 0, 0, 'L', parseInt(dx, 10), parseInt(dy, 10)];
}
function getWidth(e) {
var x = e.clientX - container.offsetLeft,
dx = Math.abs(x - clickX);
return parseInt(dx, 10) + 1;
}
function getHeight(e) {
var y = e.pageY - container.offsetTop,
dy = Math.abs(y - clickY);
return parseInt(dy, 10) + 1;
}
if (!annotation.options.shape) return;
var shape = annotation.options.shape.params;
var newShape = {};
if (shape.r) {
newShape.r = getRadius(e);
}
if (shape.d) {
newShape.d = getPath(e);
}
if (shape.width) {
newShape.width = getWidth(e);
}
if (shape.height) {
newShape.height = getHeight(e);
}
return newShape;
}
function drag(e) {
// alert("Hii");
var shape = $("input[type='radio']:checked").val(),
stroke = $("#stroke").val(),
strokeWidth = $("#strokeWidth").val(),
title = $("#title").val(),
fill = $("#fill").val(),
shapeOpt = null,
x = null,
y = null,
width = null,
height = null,
radius = 20;
clickX = e.pageX - container.offsetLeft;
clickY = e.pageY - container.offsetTop;
if (!chart.isInsidePlot(clickX - chart.plotLeft, clickY - chart.plotTop)) {
return;
}
if (shape == 'rect') {
x = 0;
y = 0;
width = 1;
height = 1;
radius = 1;
}
if (shape !== 'text') {
shapeOpt = {
type: shape,
params: {
r: shape == 'circle' ? 1 : 0,
d: shape == 'path' ? ['M', 0, 0, 'L', 1, 1] : null,
x: x,
y: y,
width: width,
height: height
}
};
title = null;
Highcharts.addEvent(document, 'mousemove', step);
}
chart.addAnnotation({
x: clickX,
y: clickY,
allowDragX: true,
allowDragY: true,
anchorX: 'left',
anchorY: 'top',
title: title,
shape: shapeOpt
});
annotation = annotations[annotations.length - 1];
}
function step(e) {
// use renderer api for better performance
annotation.shape.attr(getParams(e));
}
function drop(e) {
Highcharts.removeEvent(document, 'mousemove', step);
// store annotation details
if (annotation) {
annotation.update({
shape: {
params: getParams(e)
}
});
}
annotation = null;
}
function sal(e)
{
// Highcharts.removeEvent(container, 'dblclick', step);
var each = Highcharts.each;
each(chart.annotations.allItems, function (item, i) {
if (item.selectionMarker) {
shape = item.shape.element.localName;
}
});
// var shape = $("input[type='radio']:checked").val(),
var shapeOpt = null,
x = null,
y = null,
width = null,
height = null,
radius = null;
clickX = e.pageX - container.offsetLeft;
clickY = e.pageY - container.offsetTop;
if (!chart.isInsidePlot(clickX - chart.plotLeft, clickY - chart.plotTop)) {
return;
}
if (shape == 'rect') {
x = clickX;
y = clickY;
width = 1;
height = 1;
radius = 1;
}
if (shape !== 'text') {
shapeOpt = {
type: shape,
params: {
r: shape == 'circle' ? 1 : 0,
d: shape == 'path' ? ['M', 0, 0, 'L', 1, 1] : null,
x: x,
y: y,
width: width,
height: height
}
};
title = null;
Highcharts.addEvent(document, 'mousemove', step);
}
annotation = annotations[annotations.length - 1];
}
// Highcharts.addEvent(container, 'mousedown', drag);
Highcharts.addEvent(document, 'mouseup', drop);
Highcharts.addEvent(container, 'dblclick', sal);
$('#ann1size').click(function() {
var ann = annotations[annotations.length - 1];
ann.update({
shape: {
params: {
r: 200
}
}
})
});
}
});
double click on square shape, you can resize it now.
double click on circle shape, its still resizing square shape.
Can you please let me know how to fix this issue that no matter which shape is double clicked, square is getting resized.
I think that right now you have problem with getting right annotation in your chart. You are getting always the same rect shape because you are using fixed:
annotation = annotations[annotations.length - 1];
Instead this line, you can set your annotation object inside Highcharts.each:
var each = Highcharts.each;
each(chart.annotations.allItems, function(item, i) {
if (item.selectionMarker) {
annotation = item;
shape = item.shape.element.localName;
}
});
Here you can see an example how it can work:
http://jsfiddle.net/1e1jnv7w/3/
Best regards.

Infobox not working

I'm not a developer and i'm trying to learn javascript step by step. Now, I need to add a simple infobox in the gmaps that I'm working on. The problem is that, I add the code as explained in the google reference but it doesn't work: in the beginning i was using infowindow wich worked well but wasn't so customized. I also put the infobox.js link in that page and it is the last release.
This is test page: http://www.squassabia.com/aree_espositive_prova2.asp
What i need to do is to display the message you see in the code (boxText.innerHTML), just to understand it step by step and to keep things simple. After that I'm going to style it and add data from xml (which I think is not going to be that difficult).
As i didn't fint any solution in any of the old posts, if anyone of you can give me a clue on how to solve the problem, would be very appreciated, I've tried everything and put infobox stuff pretty much everywhere :(
Cheers
I give you the initialize() code:
//icone custom
var customIcons = {
negozio: {icon: '/images/gmaps/mc.png'},
outlet: {icon: '/images/gmaps/pin_fuc_outlet.png'},
sede: {icon: '/images/gmaps/pin_fuc_home.png'}
};
var clusterStyles = [
{
textColor: 'white',
url: '/images/gmaps/mc.png',
height: 48,
width: 48
}];
function initialize() {
//creo una istanza della mappa
var map = new google.maps.Map(document.getElementById("mapp"), {
center: new google.maps.LatLng(45.405, 9.867),
zoom: 9,
mapTypeId: 'roadmap',
saturation: 20, //scrollwheel: false
});
//stile della mappa
var pinkroad = [ //creo un array di proprietà
{
featureType: "all", //seleziono la feature
stylers: [{gamma: 0.8 },{ lightness: 50 },{ saturation: -100}]
},
{
featureType: "road.highway.controlled_access",
stylers: [{ hue: "#FF3366" },{ saturation: 50 },{ lightness: -5 }]
}
];
map.setOptions({styles: pinkroad});
var name;
//Creates content and style
var boxText = document.createElement("div");
boxText.style.cssText = "border: 1px solid black; margin-top: 8px; background: yellow; padding: 5px;";
boxText.innerHTML = "Prova Infobox<br >Successo!!Test Text";
var myOptions = {
content: boxText
,disableAutoPan: false
,maxWidth: 0
,pixelOffset: new google.maps.Size(-140, 0)
,zIndex: null
,boxStyle: {background: "url('tipbox.gif') no-repeat", opacity: 0.75, width: "280px"}
,closeBoxMargin: "10px 2px 2px 2px"
,closeBoxURL: "http://www.google.com/intl/en_us/mapfiles/close.gif"
,infoBoxClearance: new google.maps.Size(1, 1)
,isHidden: false
,pane: "floatPane"
,enableEventPropagation: false
};
var ib = new InfoBox(myOptions);
//creo il marker
downloadUrl("xml/negozi.xml", function(data) {
var xml = data.responseXML;
var markers = xml.documentElement.getElementsByTagName("marker");
for (var i = 0; i < markers.length; i++)
{
var type = markers[i].getAttribute("tipo");
var address = markers[i].getElementsByTagName("indirizzo")[0].childNodes[0].nodeValue;
var city = markers[i].getElementsByTagName("citta")[0].childNodes[0].nodeValue;
var phone = markers[i].getElementsByTagName("telefono")[0].childNodes[0].nodeValue;
name = markers[i].getElementsByTagName("nome")[0].childNodes[0].nodeValue;
var point = new google.maps.LatLng(parseFloat(markers[i].getAttribute("lat")), parseFloat(markers[i].getAttribute("lng")));
var html = name + '<br />' + address + '<br />' + city + '<br />' + phone;
var icon = '/images/gmaps/pin_fuc.png';
var marker = new google.maps.Marker({map: map, position: point, icon :'/images/gmaps/pin_fuc.png'});
/*google.maps.event.addListener(marker,"click", function(){
map.panTo(this.position);
});*/
createMarkerButton(marker);
google.maps.event.addListener(marker, "click", function (e) {
ib.open(map);
});
}
});
function createMarkerButton(marker) {
//Creates a sidebar button
var ul = document.getElementById("list");
var li = document.createElement("li");
li.appendChild(document.createTextNode(name));
ul.appendChild(li);
//Trigger a click event to marker when the button is clicked.
google.maps.event.addDomListener(li, "mouseover", function(){
marker.setAnimation(google.maps.Animation.BOUNCE);
setTimeout (function (){marker.setAnimation(null);}, 750);
});
google.maps.event.addDomListener(li, "mouseout", function(){
google.maps.event.trigger(marker, "mouseout");
});
}
}
function downloadUrl(url, callback) {
var request = window.ActiveXObject ?
new ActiveXObject('Microsoft.XMLHTTP') :
new XMLHttpRequest;
request.onreadystatechange = function() {
if (request.readyState == 4) {
request.onreadystatechange = doNothing;
callback(request, request.status);
}
};
request.open('GET', url, true);
request.send(null);
}
function doNothing() {}

Resources