Another frustrating issue I have with Jvectormap, I wish to focus on a Marker on page/map load via lngLat, how would I do this? Ideally it would be good to say focus on this marker or focus on latlng. I will only be displaying 1 marker per map but I won't know the x/y just the lngLat or possibly countrycode. There might be an easier way altogether to do this so suggestions would be welcome. Thanks for your help in advanced
var markers = [ {latLng: [47.774099, -52.793427], name: "loc 1", label: "This blahblah"}]
$(function(){
$('#map1').vectorMap({
map: 'world_mill_en',
scale: ['#C8EEFF', '#0071A4'],
normalizeFunction: 'polynomial',
hoverOpacity: 0.7,
hoverColor: false,
markerStyle: {
initial: {
fill: '#F8E23B',
stroke: '#383f47'
}
},
backgroundColor: '#383f47',
markers: markers,
focusOn:{
latLng: [47.774099, -52.793427],
scale: 5
},
onMarkerLabelShow: function(event, label, index) {
label.html( ''+markers[index].label+'');
}
});
});
I needed the same thing as you and came across your unanswered question. This is the code I wrote (slash copied, pasted & modified from jVectorMap source) to solve the problem for myself. I hope you and others find it helpful.
Simply pass the scale, longitude, and latitude to setFocusLatLng.
I may attempt to get this or something similar accepted into the jVectorMap project on GitHub, so there may be a better way to do this later.
Disclaimer: Points on the edge of the map will not be centered. They should be in the view, though.
EDIT: As requested, here is the whole thing on jsfiddle:
http://jsfiddle.net/BryanTheScott/rs7H5/
EDIT: Also added the rest of the JS below:
$(function(){
var smallMap = $('#my_map_container').vectorMap({
map: 'world_mill_en',
zoomOnScroll: true,
zoomMax:5,
zoomMin:5,
regionStyle: {
initial: {
fill: '#222222',
"fill-opacity": 1,
stroke: '#444444',
"stroke-width": 1,
"stroke-opacity": 0.7
},
hover: {
"fill-opacity": 0.8,
fill: '#333333'
}
},
markerStyle: {
initial: {
fill: "#000000",
"stroke": "#7FC556",
"stroke-width": 2,
r: 3
}
},
markers: [[37.770172,-122.422771]]
});
var mapObj = $('#my_map_container').vectorMap('get', 'mapObject');
mapObj.setFocusLatLng = function(scale, lat, lng){
var point,
proj = jvm.WorldMap.maps[this.params.map].projection,
centralMeridian = proj.centralMeridian,
width = this.width - this.baseTransX * 2 * this.baseScale,
height = this.height - this.baseTransY * 2 * this.baseScale,
inset,
bbox,
scaleFactor = this.scale / this.baseScale,
centerX,
centerY;
if (lng < (-180 + centralMeridian)) {
lng += 360;
}
point = jvm.Proj[proj.type](lat, lng, centralMeridian);
inset = this.getInsetForPoint(point.x, point.y);
if (inset) {
bbox = inset.bbox;
centerX = (point.x - bbox[0].x) / (bbox[1].x - bbox[0].x);
centerY = (point.y - bbox[0].y) / (bbox[1].y - bbox[0].y);
this.setFocus(scale, centerX, centerY);
}
}
mapObj.setFocusLatLng(5, 37.770172,-122.422771);
});
Very late to the party here, but I needed a way to center on a marker even after the map had initially loaded, and here is what I came up with:
var yourMapHere = $(yourMapObject).vectorMap('get', 'mapObject');
var point = yourMapHere.latLngToPoint(yourMarkerLat, yourMarkerLng);
var x = yourMapHere.transX - point.x / yourMapHere.scale;
var y = yourMapHere.transY - point.y / yourMapHere.scale;
yourMapHere.setScale(yourScaleValueHere, x, y, true, true);
Related
I´m trying to draw an arc using mouse events with paper.js
The user must be able to draw an arc from 0 degree to 360 degree.
The issue that I´m facing is that I can draw 270 degree arc but more than 270, the arc flips to another quadrant.
Start point must be located anywhere
A sketch can be found here:
http://sketch.paperjs.org/#V/0.12.7/S/nVTBjpswEP2VEZeQXYcG2l6IOFTpZQ+RVruHHkpVeR1nQSE2MoZNFPHvtbHdeCGtorWEsOf5zTyex5wDhg80SIPnPZWkCFBA+FavOywAC/KbNHSVs5zptcDbsm2yZLlcmQChTFKRMfoGj7xkMvyyXCL1zC3eSCzkCP5qYJeTxJDBsAPLIlqXglQ0POcM1DDpU/tGJmhEpJDY9a6sqjWvuNo3e6kw2c9y1s9XoAvYD/AquNR6NFLwPXVcQbczNAZ/lFtZpBBPgDWuNYe3TLEADKzLAgyV4TJyJjmvIs42vG3ohndaz65lRJachbRTHzeHsyNpT2rPsgGPaj2PjshfnbSNjtLF2WD2wnjlI0lWT6OYvVY0C7skGmYP7EnZilmz6OJRxFXxuIJ0uMq0ueun7+GEgSZZ0bBE9hzNCb7Pa08qEvSgDAodaMNeh3wTJDQC9J5e2+a8BKcIV3WBYzS8kqu1TRfYhqKyFQy8xtgJfkj9gB5H14fREe5tF95ttCTCG1tyjt5zTn85pxGnKZnjXCi9R5eFaq7X4iYZcAcjIQoys2Rhq3xKbhHnMl3kXc30D8n8Q6bdj/J/xMRJjusKb7/xn/974+11t03Um7+Z+ne+CIr3w+1sgvTnr/4P
and this is the implemented code:
var arc_cse;
var radius=200;
var center=new Point(400,400);
var start=new Point(400,500);
var c1 = new Path.Circle({
center: center,
radius: 2,
fillColor: 'black'
});
arc_cse = new Path({
strokeColor: 'red',
strokeWidth: 1,
strokeCap: 'round',
});
tool.onMouseMove = function(event) {
var p=new Point(event.point.x,event.point.y);
var v1=start-center;
var v2=p-center;
var angle=(v2.angleInRadians-v1.angleInRadians);
var arcval=arc_CRD(v1.angleInRadians,v2.angleInRadians,angle,center,radius);
arc_cse.remove();
arc_cse= new Path.Arc(arcval);
}
function arc_CRD(alpha1,alpha2,angle,center,radius){
return {
from: {
x: center.x + radius*Math.cos(alpha1),
y: center.y + radius*Math.sin(alpha1)
},
through: {
x: center.x + radius * Math.cos(alpha1 + (alpha2-alpha1)/2),
y: center.y + radius * Math.sin(alpha1 + (alpha2-alpha1)/2)
},
to: {
x: center.x + radius*Math.cos(alpha1+(alpha2-alpha1)),
y: center.y + radius*Math.sin(alpha1+(alpha2-alpha1))
},
strokeColor: 'red',
strokeWidth: 3,
strokeCap: 'round'
}
}
Thanks in advance
There are certainly tons of ways to do this but here's how I would do it: sketch.
This should help you finding the proper solution to your own use case.
function dot(point, color) {
const item = new Path.Circle({ center: point, radius: 5, fillColor: color });
item.removeOnMove();
}
function drawArc(from, center, mousePoint) {
const radius = (from - center).length;
const circle = new Path.Circle(center, radius);
const to = circle.getNearestPoint(mousePoint);
const middle = (from + to) / 2;
const throughVector = (middle - center).normalize(radius);
const angle = (from - center).getDirectedAngle(to - center);
const through = angle <= 0
? center + throughVector
: center - throughVector;
const arc = new Path.Arc({
from,
through,
to,
strokeColor: 'red',
strokeWidth: 2
});
circle.removeOnMove();
arc.removeOnMove();
// Visual helpers
dot(from, 'orange');
dot(center, 'black');
dot(mousePoint, 'red');
dot(to, 'blue');
dot(middle, 'lime');
dot(through, 'purple');
circle.strokeColor = 'black';
return arc;
}
function onMouseMove(event) {
drawArc(view.center + 100, view.center, event.point);
}
Edit
In answer to your comment, here is a more mathematical approach: sketch.
This is based on your code and has exactly the same behavior so you should have no difficulty using it.
The key of both implementation is the Point.getDirectedAngle() method which allow you to adapt the behavior depending on the through point side.
const center = new Point(400, 400);
const start = new Point(400, 500);
const c1 = new Path.Circle({
center: center,
radius: 2,
fillColor: 'black'
});
let arc;
function getArcPoint(from, center, angle) {
return center + (from - center).rotate(angle);
}
function drawArc(from, center, mousePoint) {
const directedAngle = (from - center).getDirectedAngle(mousePoint - center);
const counterClockwiseAngle = directedAngle < 0
? directedAngle
: directedAngle - 360;
const through = getArcPoint(from, center, counterClockwiseAngle / 2);
const to = getArcPoint(from, center, counterClockwiseAngle);
return new Path.Arc({
from,
through,
to,
strokeColor: 'red',
strokeWidth: 1,
strokeCap: 'round'
});
}
function onMouseMove(event) {
if (arc) {
arc.remove();
}
arc = drawArc(start, center, event.point);
}
i need to draw a graph of semi circle on a leaflet map.
It should look like the following image:
How can i do it?
Thanks
Efrat
Have you seen leaflet-semicircle? Not exactly what you need, but might give you enough clues to implement what you want.
Did a quick example (demo here):
function rangerings (latlng, options) {
options = L.extend({
count: 8,
interval: 1000,
direction: 0,
spread: 120
}, options);
var layer = L.featureGroup();
for (var i = 1; i <= options.count; i++) {
L.semiCircle(latlng, {
radius: i * options.interval,
fill: false,
color: '#000',
weight: 1
}).setDirection(options.direction, options.spread).addTo(layer);
}
return layer;
}
code on github
I'm resizing the symbol this way:
google.maps.event.addListener(map_object, 'zoom_changed', (function(arrow) { return function() {
var zoom = map_object.getZoom();
var scale = 2.48676567E-2 * Math.exp(0.143700035 * zoom);
arrow.icons[0].icon.scale = scale;
}})(arrow));
When I inspect the arrow object, the scale property changes properly on zoom_changed, but it's not changing its size in the map.
Is there something I'm forgetting to do?
UPDATE
The arrow object is defined as follow:
var sym = {
path: "M0 15 L30 0 L60 15",
rotation: angle,
scale: 0.25,
strokeWeight: 3,
};
var arrow = new google.maps.Polyline({
path: [{lat: lat, lng: lng},{lat: lat2, lng: lng}],
geodesic: true,
strokeColor: color,
strokeOpacity: 0.9,
icons: [{
icon: sym,
offset: '100%'
}]
});
Just for future references.
I solved my problem using the setOptions method from Polyline class, instead of setting the scale property.
My code becomes to this:
google.maps.event.addListener(map_object, 'zoom_changed', (function(arrow) { return function() {
var zoom = map_object.getZoom();
var scale = 2.48676567E-2 * Math.exp(0.143700035 * zoom);
var icon = arrow.icons[0].icon;
icon.scale = scale;
arrow.setOptions({icons: [{icon: icon, offset: '100%'}]});
}})(arrow));
Now, the arrow size is changing on map zoom in the right way.
I'm struggling to implement a little things on canvas with KineticJS.
I want to create a circle + a line which form a group (plane).
The next step is to allow the group to rotate around itself with a button that appears when you click on the group.
My issue is that when I click on the rotate button, it does not rotate near the button but elsewhere. Have a look :
My rotation atm : http://hpics.li/b46b73a
I want the rotate button to be near the end of the line. Not far away..
I tried to implement it on jsfiddle but I'm kinda new and I didn't manage to put it correctly , if you could help me on that, I would be thankful !
http://jsfiddle.net/49nn0ydh/1/
function radians (degrees) {return degrees * (Math.PI/180)}
function degrees (radians) {return radians * (180/Math.PI)}
function angle (cx, cy, px, py) {var x = cx - px; var y = cy - py; return Math.atan2 (-y, -x)}
function distance (p1x, p1y, p2x, p2y) {return Math.sqrt (Math.pow ((p2x - p1x), 2) + Math.pow ((p2y - p1y), 2))}
jQuery (function(){
var stage = new Kinetic.Stage ({container: 'kineticDiv', width: 1200, height:600})
var layer = new Kinetic.Layer(); stage.add (layer)
// group avion1
var groupPlane1 = new Kinetic.Group ({
x: 150, y: 150,
draggable:true
}); layer.add (groupPlane1)
// avion 1
var plane1 = new Kinetic.Circle({
radius: 10,
stroke: "darkgreen",
strokeWidth: 3,
}); groupPlane1.add(plane1);
var trackPlane1 = new Kinetic.Line({
points: [10, 0, 110, 0],
stroke: "darkgreen",
strokeWidth: 2
}); groupPlane1.add(trackPlane1);
groupPlane1.on('click', function() {
controlGroup.show();
});
groupPlane1.setOffset (plane1.getWidth() * plane1.getScale().x / 2, plane1.getHeight() * plane1.getScale().y / 2)
var controlGroup = new Kinetic.Group ({
x: groupPlane1.getPosition().x + 120,
y: groupPlane1.getPosition().y ,
opacity: 1, draggable: true,
}); layer.add (controlGroup)
var signRect2 = new Kinetic.Rect({
x:-8,y: -6,
width: 20,
height: 20,
fill: 'white',
opacity:0
});
controlGroup.add(signRect2);
var sign = new Kinetic.Path({
x: -10, y: -10,
data: 'M12.582,9.551C3.251,16.237,0.921,29.021,7.08,38.564l-2.36,1.689l4.893,2.262l4.893,2.262l-0.568-5.36l-0.567-5.359l-2.365,1.694c-4.657-7.375-2.83-17.185,4.352-22.33c7.451-5.338,17.817-3.625,23.156,3.824c5.337,7.449,3.625,17.813-3.821,23.152l2.857,3.988c9.617-6.893,11.827-20.277,4.935-29.896C35.591,4.87,22.204,2.658,12.582,9.551z',
scale: {x:0.5, y:0.5}, fill: 'black'
}); controlGroup.add (sign)
controlGroup.setDragBoundFunc (function (pos) {
var groupPos = groupPlane1.getPosition();
var rotation = degrees (angle (groupPos.x, groupPos.y, pos.x, pos.y));
var dis = distance (groupPos.x, groupPos.y, pos.x, pos.y);
groupPlane1.setRotationDeg (rotation);
layer.draw()
return pos
})
controlGroup.on ('dragend', function() {
controlGroup.hide();
layer.draw()
})
controlGroup.hide();
layer.draw()
})
You can adjust the rotation point by setting the offsetX and offsetY of the group.
I have the following circles in my game. The player drags them into different locations in the game. When the player selects, play again, I want the shapes to go back to the original position stated in the init function. How should I go about this? Thank you.
stage = new Kinetic.Stage({
container: "container",
width: 900,
height: 550
});
shapes = new Kinetic.Layer();
function init() {
circle1 = new Kinetic.Circle({
x: stage.getWidth() / 3.2,
y: stage.getHeight() / 3.2,
radius: radius,
fill: "blue",
stroke: "black",
strokeWidth: 4,
name: "circle",
draggable: true
});
shapes.add(circle1)
stage.add(shapes)
Store defaults in a separate variable, then use .setPosition( x, y ) to reset it:
//store settings
var settings = {
x: stage.getWidth() / 3.2,
y: stage.getHeight() / 3.2,
radius: radius,
fill: "blue",
stroke: "black",
strokeWidth: 4,
name: "circle",
draggable: true
};
//use settings
circle1 = new Kinetic.Circle(settings);
//after move, reset using:
circle1.setPosition(settings.x,settings.y);
you can also use the super handy setAttrs method like this:
circle1.setAttrs(settings);
Cheers!
I know this question is fairly old but I just solved something like this.
stage.removeChildren();
stage.setAttrs(stage.defaultNodeAttrs);
The stage.reset() doesn't work anymore, but this should do what you want.