Google maps API JAVASCRIPT - Add more rectangles (dynamic) - javascript

I have a little problem with my "app" using google maps. I just want to dynamic add a rectangle into my map and each rectangle add a little event...
My code:
google.maps.event.addListener(this.canvas, "click", function(event)
{
var left = event.latLng.lng() - 0.1;
var right = event.latLng.lng() + 0.1;
var top = event.latLng.lat() - 0.1;
var bottom = event.latLng.lat() + 0.1;
var rectangle = new google.maps.Rectangle({
bounds: {north: top, south: bottom, east: right, west: left},
editable: true,
draggable: true,
fillColor: 'blue',
strokeColor: 'blue'
});
rectangle.setMap(map.canvas);
rectangle.addListener("rightclick", function ()
{
if(rectangle.editable)
{
rectangle.setOptions({
editable: false,
draggable: false,
fillColor: "black",
strokeColor: "black"
});
}
else
{
rectangle.setOptions({
editable: true,
draggable: true,
fillColor: "blue",
strokeColor: "blue"
});
}
});
});
All what I want is just add new rectangle after click, and when I use right click -> enable / disable rectangle...
This code works fine, but when I lock one or more rectangles, all rectangles does not move and they are !draggable.
Can you help me with this? Thanks!
live demo : https://jsfiddle.net/3fuf5bqo/ just 2x click on the map (create 2 rectangles) and after this just click (right click) on one of them - both of them does not move

HMMMM, the problem was in "rightclick" event, when I use just "click" or "dbclick" the problem was solved... I do not get it... :-D but it works

Related

How to create a paper.js Path.Circle that can be scaled/translated with affine matrix, but keep circle radius always fixed?

I have a paper.js layer where users can draw different paths (circles, line, etc). This layer can be panned or zoomed using mouse scrolling or dragging. I use affine matrix transformation to zoom/pan paths in this layer. This works rather well.
What i'm looking for is to create a circle (Path.Circle object) that can be panned and zoomed using matrix, just its radius has to be always fixed (5px for example). So basically matrix transformation needs to be applied only to position of circle, but not to outline of it.
Below is sample of a circle with radius 20px transformedPath, that is zoomed to 2x. Questions is how to keep radius of circle transformedPath fixed (radius = 20px), while applying the matrix transformation.
var transformedPath = new paper.Path.Circle(100,100,20);
transformedPath.strokeColor = 'black';
paper.project.activeLayer.matrix = new paper.Matrix(
2, 0,
0, 2,
0, 0
);
UPDATE. Here's a more general sketch (code below) that is based on solution suggested by sasensi. In this sample blue circle radius stays fixed (this is correct), but problem is that blue circle also stays on the same place instead.
The desired outcome is that both circles move to new position, but blue circle radius stays fixed.
// draw a normal circle
var normalCircle = new Path.Circle({
center: new Point(100,100),
radius: 50,
fillColor: 'orange',
});
// draw another circle that will have scale transformation reversed
var notScalingCircle = new Path.Circle({
center: new Point(100,100),
radius: 30,
fillColor: 'blue',
});
// draw instructions
new PointText({
content: 'press mouse button down to zoom in and see that blue circle size does not change',
point: view.center + [0, -80],
justification: 'center'
});
function transformLayer(matrix) {
// scale layer
// project.activeLayer.applyMatrix = false;
project.activeLayer.matrix = matrix;
// scale item with inverted amount to make it display like if it was not scaled with the layer
notScalingCircle.matrix = matrix.clone().invert();
}
var matrix = new paper.Matrix(
2,0,
0,1.5,
50,30
);
// on mouse down...
function onMouseDown() {
// ...scale up
transformLayer(matrix);
}
// on mouse up...
function onMouseUp() {
// ...scale down
transformLayer(matrix.clone().invert());
}
I think that the best way do that is, when you scale your layer with a given amount, to scale your circle with the inverted amount.
That will make your circle look like if it was not scaled.
Here is a sketch demonstrating the solution:
// draw a normal circle
var normalCircle = new Path.Circle({
center: view.center,
radius: 50,
fillColor: 'orange'
});
// draw another circle that will have scale transformation reversed
var notScalingCircle = new Path.Circle({
center: view.center,
radius: 30,
fillColor: 'blue'
});
// draw instructions
new PointText({
content: 'press mouse button down to zoom in and see that blue circle size does not change',
point: view.center + [0, -80],
justification: 'center'
});
function scaleLayer(amount) {
// scale layer
project.activeLayer.scale(amount, view.center);
// scale item with inverted amount to make it display like if it was not scaled with the layer
notScalingCircle.scale(1 / amount);
}
// on mouse down...
function onMouseDown() {
// ...scale up
scaleLayer(3);
}
// on mouse up...
function onMouseUp() {
// ...scale down
scaleLayer(1 / 3);
}
Edit
In response to the new example, you just have to invert the scaling transformation on the item and not all the matrix (which also include translation and rotation).
Here is the corrected sketch:
// draw a normal circle
var normalCircle = new Path.Circle({
center: new Point(100, 100),
radius: 50,
fillColor: 'orange'
});
// draw another circle that will have scale transformation reversed
var notScalingCircle = new Path.Circle({
center: new Point(100, 100),
radius: 30,
fillColor: 'blue'
});
// draw instructions
new PointText({
content: 'press mouse button down to zoom in and see that blue circle size does not change',
point: view.center + [0, -80],
justification: 'center'
});
function transformLayer(matrix) {
// scale layer
// project.activeLayer.applyMatrix = false;
project.activeLayer.matrix = matrix;
// just invert the scale and not all matrix
notScalingCircle.scale(1 / matrix.scaling.x, 1 / matrix.scaling.y);
}
var matrix = new paper.Matrix(
2, 0,
0, 1.5,
50, 30
);
// on mouse down...
function onMouseDown() {
// ...scale up
transformLayer(matrix);
}
// on mouse up...
function onMouseUp() {
// ...scale down
transformLayer(matrix.clone().invert());
}

Openlayers3 - How to anchor a text label to a point?

I am working on an application using Openlayers3. On the map there are a couple of line segments and text labels. Each line has a color and an associated label.
For the map, I would like to have the text label anchored at a point of a line segment that is drawn on the map. So if I move the map or zoom in or out, that the label sticks to the point. However, if I zoom in or out the labels move (a lot). Dragging the map does not have this effect. Somehow I would like them to stick at a point on the line rather than move around.
Does anyone has some clever advice or links where to look? Googling for terms like 'anchor' or 'fixed point' and trying some of the recommendations did not solve the issue for me. Any help would be very much appreciated!
maybe you can be inspered by the "arrow" example wich use a style function that use geometry segments:
http://jsfiddle.net/davidhequet/7asg74Lc/
var styleFunction = function(feature, resolution) {
var geometry = feature.getGeometry();
var styles = [
// linestring
new ol.style.Style({
stroke: new ol.style.Stroke({
color: '#ffcc33',
width: 2
})
})
];
geometry.forEachSegment(function(start, end) {
var dx = end[0] - start[0];
var dy = end[1] - start[1];
var rotation = Math.atan2(dy, dx);
// arrows
styles.push(new ol.style.Style({
geometry: new ol.geom.Point(end),
text: new ol.style.Text({
textAlign: 'left',
textBaseline: 'bottom',
font: 'Arial',
text: 'test text',
fill: new ol.style.Fill({color: 'red'}),
stroke: new ol.style.Stroke({color: 'white', width: '2'}),
offsetX: 0,
offsetY: 0,
rotation: 0
})
}));
});
return styles;
};

Animation in KineticJS

I have a circle added to a layer. In the top of the layer I added a text. I would like to run an animation when the mouse is over the circle, but when the mouse reaches the text the mouseout callback function is called. How can I prevent that?
var circle = new Kinetic.Circle({
x: j * xcenterstep + xshift,
y: i * ycenterstep + yshift,
radius: t_radius,
fill: t_fill,
stroke: t_stroke,
strokeWidth: t_stroke_w,
strokeOpacity: 0.1,
opacity: 0.3 + t_number * 0.05,
});
if (t_number) {
circle.tw;
circle.on("mouseover", function () {
this.tw = new Kinetic.Tween({
node: this,
duration: 0.3,
strokeWidth: 6
});
this.tw.play();
});
circle.on("mouseout", function () {
this.tw.reverse();
});
}
// Adding the text
var radiusText = new Kinetic.Text({
x : circle.getX(),
y : circle.getY(),
text : t_number,
fontSize : radius,
fill : '#fff',
fontStyle: 'bold',
align : 'center'
});
radiusText.setOffset({
x : radiusText.getWidth()/2,
y : radiusText.getHeight()/2
});
bgLayer.add(circle);
bgLayer.add(radiusText);
I think it is better to use mouseenter event. You can disable text's events to prevent mouseout from circle.
radiusText.listening(false)
Reviewing your code, you were missing a } to close the if (t_number) {. I am not sure if it was supposed to encompass the mouseover and mouseout events, but it might have caused your code to respond differently than you are expecting.

Draggable group, doesn't change nodes positions which are in group

var stage = new Kinetic.Stage({
container: 'container',
width: 500,
height: 500,
});
var layer = new Kinetic.Layer();
var selectedGroup = new Kinetic.Group({
draggable: true,
});
var circle = new Kinetic.Circle({
x: 10,
y: 10,
fill: 'red',
radius: 10,
});
circle.on('dblclick', function () {
console.log('x: ' + circle.getX() + ' y: ' + circle.getY());
});
selectedGroup.add(circle);
layer.add(selectedGroup);
stage.add(layer);
layer.draw();
http://jsfiddle.net/cekB3/3/
When I double click on the circle, its position is [10,10]
When I move that circle and I double click on it, its position is [10,10]
Why isn't the position changing? Am i doing something wrong? or is it a bug?
I've noticed that when I change circle to draggable, then its coordinates change, but then I have an issue with 2 circles in one group and I want to be able to move them all at the same time and have their x and y changing.
To add to #thescottknight's good answer:
You can move an object between containers using myObject.moveTo(newContainer)
So you can move circle2 from selectedGroup to the same coordinate position on layer like this:
circle2.on('dblclick', function () {
circle2.setX(selectedGroup.getX()+circle2.getX());
circle2.setY(selectedGroup.getY()+circle2.getY());
circle2.moveTo(layer);
layer.draw();
});
The reason that the circle's position isn't changing is that getX and getY are relative to the parent element. The parent element is the selectedGroup draggable. There are 2 ways to get the changing position of the circle.
Use the getAbsolutePosition function on the circle to get its position:
pos = circle.getAbsolutePosition();
console.log('position=(' + pos.x + ', ' + pos.y + ')');
Use the position of the draggable and the offset of the circle:
console.log('x: ' + (selectedGroup.getX() + circle.getX()) + ' y: ' + (selectedGroup.getY() + circle.getY()));

Letting users draw curved lines on a google map?

Does anyone have any examples or source for letting users draw curved maps from point a to point b?
Thanks,
Alex
You can draw Bezier curves this way:
var GmapsCubicBezier = function(lat1, long1, lat2, long2, lat3, long3, lat4, long4, resolution, map){
var points = [];
for(it = 0; it <= 1; it += resolution) {
points.push(this.getBezier({x:lat1, y:long1},{x:lat2, y:long2},{x:lat3, y:long3},{x:lat4, y:long4}, it));
}
for(var i = 0; i < points.length - 1; i++) {
var Line = new google.maps.Polyline({
path: [new google.maps.LatLng(points[i].x, points[i].y), new google.maps.LatLng(points[i+1].x, points[i+1].y)],
geodesic: true,
strokeOpacity: 0,
strokeColor: 'yellow',
icons: [{
icon: {
path: 'M 0,-2 0,2',
strokeColor: 'violet',
strokeOpacity: 1,
strokeWeight: 4
},
repeat: '36px'
},{
icon: {
path: 'M -1,-2 -1,2',
strokeColor: 'black',
strokeOpacity: 1,
strokeWeight: 2
},
repeat: '36px'
}]
});
Line.setMap(map);
}
};
GmapsCubicBezier.prototype = {
B1 : function (t) { return t*t*t; },
B2 : function (t) { return 3*t*t*(1-t); },
B3 : function (t) { return 3*t*(1-t)*(1-t); },
B4 : function (t) { return (1-t)*(1-t)*(1-t); },
getBezier : function (C1,C2,C3,C4, percent) {
var pos = {};
pos.x = C1.x*this.B1(percent) + C2.x*this.B2(percent) + C3.x*this.B3(percent) + C4.x*this.B4(percent);
pos.y = C1.y*this.B1(percent) + C2.y*this.B2(percent) + C3.y*this.B3(percent) + C4.y*this.B4(percent);
return pos;
}
};
You can modify the code, to provide differents strategies to draw the lines. The one implemented is pointed with "shadow".
The usage is pretty easy:
var curvedLine = new GmapsCubicBezier(initLat, initLong, control1Lat, control1Long, control2Lat, control2Long, endLat, endLong, 0.1, map);
you might have to use some sort of layer on top of google map. I know there's a cloud app that allows you to scrabble on a google map, but it uses flash to embed the google map scribblemaps.com/… i don't think it's possible to use two points to create a curve perhaps more than two points.
If i understand your application correctly, based on your website, the goal that you wish to achieve is to let users to "blaze a trail"? If that is the case maybe you can create a form where the users can submit Lat Lng coordinates of the "trials" that they've "blazed," and then use Polyline to draw the curve line similar to this google map draw curved line.
However, if users just want to know how to hike from point a to point b and etc, then you can use DirectionService and DirectionRenderer, and set the DirectionsTravelMode to google.maps.DirectionsTravelMode.WALKING and render the direction on the map that way so the user would know how to hike a route with directions drawn on the map + actual direction instructions.

Categories