I am trying to draw some shapes using paperjs using CompoundPath. But the corners of the shapes are not intersecting and there is some space between the segments. For example, if I try to draw a triangle as follows:
var point0 = new Point(448, 217);
var point1 = new Point(110, 565);
var point2 = new Point(785, 565);
console.log(point0);
var path = new CompoundPath({
children: [
new Path.Line(point0, point1),
new Path.Line(point1, point2),
new Path.Line(point2, point0)
]
});
path.strokeWidth = 15;
path.strokeColor = "black";
The corners of this triangle are not connected. Here is the Sketch link for the same: Sketch Link.
How I can make connected corners in these cases?
You don't need to use CompoundPath to connect some lines, you can build a Path including them.
Here is a sketch demonstrating the solution.
var point0 = new Point(448, 217);
var point1 = new Point(110, 565);
var point2 = new Point(785, 565);
var path = new Path({
segments: [
point0,
point1,
point2
],
strokeWidth: 15,
strokeColor: 'black',
closed: true
});
Related
I have to create with "here maps" routing with the possibility of manipulating it (eg: add drag on some points on a polyline, move it somewhere, add there next checkpoint, and recalculate the route). I have no problem with clicking on polyline and get coordination of new checkpoint. I know, more or less, how to add drag and drop to it. But however I try, I can't add new point on polyline.
I try to get something like that: https://wego.here.com/directions/drive/ulica-Kolejarzy,-44-102-Gliwice,-Poland:loc-dmVyc2lvbj0xO3RpdGxlPXVsaWNhK0tvbGVqYXJ6eTtsYW5nPXBsO2xhdD01MC4zMDYwNDtsb249MTguNjkwNztzdHJlZXQ9dWxpY2ErS29sZWphcnp5O2NpdHk9R2xpd2ljZTtwb3N0YWxDb2RlPTQ0LTEwMjtjb3VudHJ5PVBPTDtkaXN0cmljdD1HbGl3aWNlO3N0YXRlPVdvai4rJUM1JTlBbCVDNCU4NXNraWU7Y291bnR5PUdsaXdpY2U7Y2F0ZWdvcnlJZD1zdHJlZXQtc3F1YXJlO3NvdXJjZVN5c3RlbT1pbnRlcm5hbDtwZHNDYXRlZ29yeUlkPTkwMC05NDAwLTA0MDE/ulica-Mostowa,-43-600-Jaworzno,-Poland:loc-dmVyc2lvbj0xO3RpdGxlPXVsaWNhK01vc3Rvd2E7bGFuZz1wbDtsYXQ9NTAuMjA3Njk7bG9uPTE5LjI1NTc0O3N0cmVldD11bGljYStNb3N0b3dhO2NpdHk9SmF3b3J6bm87cG9zdGFsQ29kZT00My02MDA7Y291bnRyeT1QT0w7ZGlzdHJpY3Q9SmF3b3J6bm87c3RhdGU9V29qLislQzUlOUFsJUM0JTg1c2tpZTtjb3VudHk9SmF3b3J6bm87Y2F0ZWdvcnlJZD1zdHJlZXQtc3F1YXJlO3NvdXJjZVN5c3RlbT1pbnRlcm5hbDtwZHNDYXRlZ29yeUlkPTkwMC05NDAwLTA0MDE?map=50.25857,18.97158,11,normal . You know, thwn you can drag and drop this polyline and add more checkpoints
Belowe I put my code with some comments. There is method "manipulatePolylineOnClick" there I got new coordinates by click and want to add it to polyline. But I really don't know how.
export function createRoute(origin, destination, via, platform, map) {
let routingParameters = {
'routingMode': 'fast',
'transportMode': 'truck',
'return': 'polyline'
};
setRoutingParameters(routingParameters, origin, destination, via)
var router = platform.getRoutingService(null, 8);
var onResult = function (result) {
if (result.routes.length) {
result.routes[0].sections.forEach((section) => {
//create polyline
let linestring = H.geo.LineString.fromFlexiblePolyline(section.polyline);
let routeLine = new H.map.Polyline(linestring, {
style: {strokeColor: 'red', lineWidth: 3}
});
// needed to polyline drag and drop
let verticeGroup = new H.map.Group({
visibility: false
});
let mainGroup = new H.map.Group({
volatility: true, // mark the group as volatile for smooth dragging of all it's objects
objects: [routeLine, verticeGroup]
});
let polylineTimeout;
routeLine.draggable = true;
//my method that should add poitnts to manimupate route, and allow to do it
manipulatePolylineOnClick(routeLine, map, verticeGroup)
let startMarker = new H.map.Marker(section.departure.place.location);
let endMarker = new H.map.Marker(section.arrival.place.location);
map.addObjects([routeLine, startMarker, endMarker]);
map.getViewModel().setLookAtData({bounds: routeLine.getBoundingBox()});
});
}
};
router.calculateRoute(routingParameters, onResult,
function(error) {
alert(error.message);
});
}
function setRoutingParameters(routingParameters, origin, destination, via) {
routingParameters['origin'] = origin
routingParameters['destination'] = destination
}
function manipulatePolylineOnClick(polyline, map, verticeGroup) {
const svgCircle = '<svg width="20" height="20" version="1.1" xmlns="http://www.w3.org/2000/svg">' +
'<circle cx="10" cy="10" r="7" fill="transparent" stroke="red" stroke-width="4"/>' +
'</svg>';
// so, I have new coordinates on click in coord variable. But what I have to do, to add it to polyline?
polyline.addEventListener('tap', function (e) {
let coord = map.screenToGeo(e.currentPointer.viewportX, e.currentPointer.viewportY);
//it's not working
let vertice = new H.map.Marker(
coord,
{
icon: new H.map.Icon(svgCircle, {anchor: {x: 20, y: 20}})
}
);
vertice.draggable = true;
// vertice.setData({'verticeIndex': index})
verticeGroup.addObject(vertice);
console.log('coord', coord)
})
}
I have draggable markers on a Here Map, and I'd like to detect when a marker is dragged and dropped onto a Polyline. I haven't been able to find a good way to detect that the marker is dropped on or near the polyline. It would be nice if I could add an "dragend" event listener to the Polyline object, but that doesn't seem to be supported on objects other than the actual map.
Another approach would be to determine the distance to the Polyline from the point that the dragend occurs, but I haven't found a straightforward way to calculate that distance. (Though I've found the example for finding the nearest marker to a point.)
Any suggestions?
It is possible to add dragend event listener on map objects.
This code should work for you (in 3.0 API version):
var lineString = new H.geo.LineString([0, 0, 0, 50, 50, 0]),
polyline = new H.map.Polyline(lineString, {style: {lineWidth: 15, strokeColor: 'red'}}),
marker = new H.map.Marker({lat: 30, lng: 0});
// Ensure that the marker can receive drag events
marker.draggable = true;
// add objects to the map
map.addObjects([polyline, marker]);
// set map center and zoom
map.setCenter({lat: 30, lng: 0});
map.setZoom(3);
// disable map's behavior and calculate the offset between mouse and target's position
// when starting to drag a marker object:
marker.addEventListener('dragstart', function(ev) {
var target = ev.target,
pointer = ev.currentPointer,
targetPosition = map.geoToScreen(target.getGeometry());
target['offset'] = new H.math.Point(pointer.viewportX - targetPosition.x, pointer.viewportY - targetPosition.y);
behavior.disable();
}, false);
// Listen to the drag event and move the position of the marker
marker.addEventListener('drag', function(ev) {
var target = ev.target,
pointer = ev.currentPointer;
target.setGeometry(map.screenToGeo(pointer.viewportX - target['offset'].x, pointer.viewportY - target['offset'].y));
}, false);
// re-enable behavior and check if marker was dropped on polyline
marker.addEventListener('dragend', function(ev) {
behavior.enable();
var pointer = ev.currentPointer,
objects = map.getObjectsAt(pointer.viewportX, pointer.viewportY),
droppedOnPolyline = false;
objects.forEach(function(object) {
if (object === polyline) {
droppedOnPolyline = true;
}
});
console.log('marker dropped on polyline? %s', droppedOnPolyline);
}, false);
I was wondering if it's possible to add a relief to the bubbles on the Kendo UI Bubble charts, because, with the 15 given themes, all bubbles stay flat :
http://demos.telerik.com/kendo-ui/bubble-charts/index
It would be nice to add a 3D-style like the pie chart (Uniform style):
http://demos.telerik.com/kendo-ui/pie-charts/index
I guess it could be done by adding a CSS to the SVG, but I'm kind of lost.
Any ideas ?
Thanks :D
A colleague of mine found a solution. You have to call this code after every refresh or draw call :
var svg = $('svg');
var circles = svg.find('circle');
var svgEl = svg[0];
$.each(circles, function (key, circle) {
var fillColor = $(this).attr('fill');
var id = fillColor.replace('#', 'kgrad');
var stops = [
{offset: '0', 'stop-color': fillColor, 'stop-opacity': 0.3},
{offset: '0.84', 'stop-color': fillColor, 'stop-opacity': 0.95},
{offset: '0.85', 'stop-color': fillColor, 'stop-opacity': 0.7},
{offset: '0.99', 'stop-color': fillColor, 'stop-opacity': 1}];
if (svg.find('#' + id).length === 0) {
var svgNS = svgEl.namespaceURI;
var grad = document.createElementNS(svgNS, 'radialGradient');
grad.setAttribute('id', id);
for (var i = 0; i < stops.length; i++) {
var attrs = stops[i];
var stop = document.createElementNS(svgNS, 'stop');
for (var attr in attrs) {
if (attrs.hasOwnProperty(attr))
stop.setAttribute(attr, attrs[attr]);
}
grad.appendChild(stop);
}
var defs = svgEl.querySelector('defs') || svgEl.insertBefore(document.createElementNS(svgNS, 'defs'), svgEl.firstChild);
defs.appendChild(grad);
}
$(this).attr('fill', 'url(#' + id + ')');
}, this);
I'm making a map with OpenLayers 3, I have coordinates (EPSG:3857) in PostgreSQL and the map layer is OSM (same projection that the icons, EPSG:3857).
The problem is that when I increment the zoom, the icons disappear... But if I decrement then the icons won't disappear.
Someone told me that the projection's ICONS and LAYER must be the same.
Can someone help me, please?
I'm new in StackOverFlow,
Thank you for your time,
Enrique.
Note: My code is in JSFiddle, can see here: jsfiddle.net/y3sLksg6/
Try to set the style to each of your markers individually as in the exaple below, which is a copy from your jsfiddle:
function AddMarkers() {
//create a bunch of icons and add to source vector
var sizeY = Object.size(coordenadas);
var x = null;
var y = null;
for (var i = 0; i < sizeY; i++) {
x = coordenadas[i].Longitude;
y = coordenadas[i].Latitude;
var iconFeature = new ol.Feature({
geometry: new ol.geom.Point([x, y]),
name: 'Marker ' + i,
population: 4000,
rainfall: 500
});
markers[i] = [x, y];
var iconStyle = new ol.style.Style({
image: new ol.style.Icon(({
anchor: [0.5, 46],
anchorXUnits: 'fraction',
anchorYUnits: 'pixels',
opacity: 0.75,
src: './img/circleRed.png'
}))
});
// This is new !
iconFeature.setStyle(iconStyle);
vectorSource.addFeature(iconFeature);
}
return vectorLayer;
}
I am experimenting with Meteor and KineticJS. What I'm trying to do is to create a shape, and move it towards a mouse click on the stage. The position should be saved to the mongoDB so that all connected clients can be updated.
I haven't gotten far yet, but this is what I've got. I basically need a way to do two things:
How can I make a shape move towards the mouse click on the stage
and stop when it gets there?
Is there a better way of checking
the current position of a shape, other than the gameLoop that I
tried below? It works, but it feels wrong.
Thank you!
//client.js code
var player = null;
var playerAnim = null;
Template.container.rendered = function () {
var myCanvas = document.getElementById('myCanvas');
var stage = new Kinetic.Stage({
container: myCanvas,
width: 1024,
height: 1024
});
var layer = new Kinetic.Layer();
// add the layer to the stage
stage.add(layer);
// add click listener for the stage
$(stage.getContent()).on('click', function(evt) {
//stage was clicked
//Find the player shape in the database
Players.find().forEach(function (dbShape) {
player = new Kinetic.RegularPolygon(dbShape);
// setup an animation to move the player to the right
playerAnim = new Kinetic.Animation(function(frame) {
var velocity = 50;
var dist = velocity * (frame.timeDiff / 1000);
player.move(dist, 0);
Players.update(dbShape._id, {$set: {x: player.attrs.x, y: player.attrs.y}});
}, layer);
playerAnim.start();
layer.add(player);
layer.draw();
});
});
//make a gameLoop to check the position and stop the animation
Meteor.setInterval(function(gameLoop){
if(player.attrs.x > 500){
playerAnim.stop();
}
}, 500);
Meteor.autosubscribe(function () {
// clear the canvas
if (layer) {
layer.removeChildren();
layer.clear();
}
// populate the canvas with the Shapes collection
Players.find().forEach(function (dbShape) {
var player = new Kinetic.RegularPolygon(dbShape);
layer.add(player);
layer.draw();
});
});
}
I would use a tween to do this. Grab your object, get mouse position, and on mousedown or click create a Tween for your node to that mouse position.
layer.on('mousedown', function() {
var mousePos = stage.getMousePosition();
var tween = new Kinetic.Tween({
node: rect,
duration: 1,
x: mousePos.x,
y: mousePos.y,
opacity: 1,
strokeWidth: 6,
scaleX: 1.5
}).play();
});
JSFiddle
Note: To make the layer clickable, we need to add a transparent rectangle with the size of the width and height of the stage to the layer. See in the jsfiddle the Kinetic.Rect I made named var bg
Would putting the check inside the animation work for you?
playerAnim = new Kinetic.Animation(function(frame) {
var velocity = 50;
var dist = velocity * (frame.timeDiff / 1000);
player.move(dist, 0);
Players.update(dbShape._id, {$set: {x: player.attrs.x, y: player.attrs.y}});
if(player.getX() > 500){
this.stop();
}
}, layer);