KonvaJS Graph Editor Move Nodes - zooming

I am developing a Graph Editor with Nodes and Branches. With Pan/Zoom. I am starting with the (1) Pan/Zoom (done), (2) Add Nodes (done), (3) Select Nodes (done), (4) Move Nodes (disable the Pan). I am stuck here. I made the stage draggable for the Pan. When I want to move (drag) the nodes, I put draggable of the stage to false. But I don't see how to drag the nodes.
The use of the Graph Editor is (+) Nodes to create the nodes.
Thanks for any help.
Here is a jsbin
https://jsbin.com/suqisak/4/edit?html,js,output
function evtFct_OnMouseDragStart(event) {
var realMousePos = getRelativePointerPosition(group);
console.log('DragStart');
if (Nodes_list.length > 0) {
var SelectedNode = getSelected_Node(realMousePos);
if (SelectedNode !== null) {
SelectedNode.circle.draggable(true);
}
}
}
I dont see how to make the nodes (circles) draggable.
the event DragStart Doesn't fire !!!
Then I created a group with the circle + label, and made the group draggable.
draw() {
this.View = new Konva.Group({draggable: true});
this.circle = new Konva.Circle({
x: this.x,
y: this.y,
radius: nodeSize,
fill: nodeColor,
draggable: true,
id: this.node_id
});
this.label = new Konva.Text({
x: this.x - 20,
y: this.y - 10,
text: this.node_id,
width: 40,
height: 20,
fontSize: 8,
fontFamily: 'sans-serif',
fill: 'blue',
verticalAlign: 'middle',
align: 'center'
});
this.View.add(this.circle);
this.View.add(this.label);
group.add(this.View);
}
And I could drag the nodes, BUT !!! I lost the node x, and y.
When I click on the node (near the node center), I knew near which node, I clicked. But Now !!! I lost the the x, and y of the new position !!!
Remark : In fact, I select the node by my own, I get the mouse click position. I loop through the nodes_list, to check if the position of the click and the circle center, have a distance less than the circle radius.
Finally, the question became, how to get the Node position coordinates (x,y) after the drag ?

As you are making a group draggable, you just need to set position to it. Then for a circle and a text, you need to set position relative to the group:
this.View = new Konva.Group({draggable: true, x: this.x, y: this.y });//added
this.circle = new Konva.Circle({
radius: nodeSize,
fill: nodeColor,
draggable: true,
id: this.node_id
});
this.label = new Konva.Text({
x: - 20,
y: - 10,
text: this.node_id,
width: 40,
height: 20,
fontSize: 8,
fontFamily: 'sans-serif',
fill: 'blue',
verticalAlign: 'middle',
align: 'center'
});
Then you just read the position from the group.
https://jsbin.com/yevozeyeza/1/edit?html,js,output

Related

Google Maps custom label x and y position

I am trying to adjust the x and y position of my custom label. Is this possible?
I haven't come across any documentation regarding this issue as of yet.
numberMarkerImg = {
url: '../images/mobile/map-marker.png',
size: new google.maps.Size(32, 38),
scaledSize: new google.maps.Size(32, 38)
};
// Letter markers
marker = new google.maps.Marker({
position : point,
map : map,
icon : numberMarkerImg,
draggable: false,
labelClass: "labels",
label: {
text: saved_label,
color: 'black',
fontSize: '12px',
x: '200',
y: '100'
}
});
"labelOrigin" ended up having to to be passed in since I am using a custom marker.
numberMarkerImg = {
url: '../images/mobile/map-marker.png',
size: new google.maps.Size(32, 38),
scaledSize: new google.maps.Size(32, 38),
labelOrigin: new google.maps.Point(9, 9)
};
Google Maps API v3 doesn't let you set MarkerLabel position, there're no x and y options.
The doc also says:
If you are using it with a custom marker, you can reposition it with the labelOrigin property in the Icon class.
As I can see you're using custom marker so maybe this is the way to go for you.
Alternatively, have a look at MarkerWithLabel. Is an extension to the default Marker object with more options available. Small demo: http://jsfiddle.net/LLd4drvx/239/.
Another option I don't see mentioned here. You can set a CSS class for the label, then set the position using CSS. First, add className to the label:
label: {
text: saved_label,
color: 'black',
fontSize: '12px',
className: 'marker-position',
}
And for the CSS:
.marker-position {
bottom: 6px;
left: 0;
position: relative;
}
For v3, you can use it like this. The blue pointer shown in the picture is an icon I use as svg. with the appropriate label position for this icon.
iconSVG = {
path: `M13.04,41.77c-0.11-1.29-0.35-3.2-0.99-5.42c-0.91-3.17-4.74-9.54-5.49-10.79c-3.64-6.1-5.46-9.21-5.45-12.07
c0.03-4.57,2.77-7.72,3.21-8.22c0.52-0.58,4.12-4.47,9.8-4.17c4.73,0.24,7.67,3.23,8.45,4.07c0.47,0.51,3.22,3.61,3.31,8.11
c0.06,3.01-1.89,6.26-5.78,12.77c-0.18,0.3-4.15,6.95-5.1,10.26c-0.64,2.24-0.89,4.17-1,5.48C13.68,41.78,13.36,41.78,13.04,41.77z
`,
fillColor: '#0084ff',
fillOpacity: 1,
strokeColor: '#ffffff',
strokeWeight: 1,
anchor: new google.maps.Point(14, 43),
labelOrigin: new google.maps.Point(13.5, 15)
};
This sequence is a faster way to find the right position. size, anchor, labelOrigin

Kineticjs Groups of shapes can be dragged out of stage and mousedown outside stage, loses the shapes

Kineticjs Groups of shapes can be dragged out of stage and mousedown outside the stage loses the shapes.
Yes...
By default shapes can be dragged out of the group and even dragged off stage.
You can limit the shapes drag to a specified area using dragBoundFunc.
Here's a Fiddle: http://jsfiddle.net/m1erickson/bP92U/
var rect = new Kinetic.Rect({
x: 20,
y: 20,
width:50,
height:30,
fill: 'blue',
draggable: true,
dragBoundFunc: function(pos) {
var w=this.getWidth();
var h=this.getHeight();
if(pos.x<0){pos.x=0;}
if(pos.x+w>sw){pos.x=sw-w;}
if(pos.y<0){pos.y=0;}
if(pos.y+h>sh){pos.y=sh-h;}
return {
x: pos.x,
y: pos.y
}
}
});

How to make KineticJs custom shape

I am trying to make KineticJs html 5 custom shape.
But it is not working in Google chrome. Not draggable in Firefox and also shape are not same in size.
Can anybody tell why?
live code http://jsfiddle.net/prantor19/wGE2a/8/
var stage = new Kinetic.Stage({
container: 'canvas-container',
width: 500,
height: 500,
});
var layer = new Kinetic.Layer();
drawWindow = function(canvas) {
var context = canvas.getContext();
context.beginPath();
context.moveTo(this.attrs.x,this.attrs.y);
context.lineTo(this.attrs.width,this.attrs.y);
context.lineTo(this.attrs.width,this.attrs.height);
context.lineTo(this.attrs.x,this.attrs.height);
context.closePath();
context.clip();
context.drawImage(img,this.attrs.img_x,this.attrs.img_y);
}
img = document.createElement('img');
img.src= "http://upload.wikimedia.org/wikipedia/commons/thumb/1/14/Nature_reserve_Kladrubska_hora_in_summer_2011_(17).JPG/1024px-Nature_reserve_Kladrubska_hora_in_summer_2011_(17).JPG";
var window1 = new Kinetic.Shape({
drawFunc: drawWindow,
x: 0,
y: 0,
width: 100,
height: 100,
img:img,
img_x:0,
img_y:0,
draggable: true
});
var window2 = new Kinetic.Shape({
drawFunc: drawWindow,
x: 10,
y: 60,
width: 100,
height: 100,
img:img,
img_x:-250,
img_y:0,
draggable: true
});
pointercursor = function() {
document.body.style.cursor = 'pointer';
}
defaultCursor = function() {
document.body.style.cursor = 'default';
}
window1.on('mouseover',pointercursor );
window1.on('mouseout', defaultCursor);
window2.on('mouseover',pointercursor );
window2.on('mouseout', defaultCursor);
layer.add(window1);
layer.add(window2);
stage.add(layer);
Your script has errors in it
Unable to get image data from canvas because the canvas has been tainted by cross-origin data. kinetic-v4.3.2-beta.js:4365
Uncaught Error: SecurityError: DOM Exception 18
Chrome refuse to work with cross domain images on cavas.
For dragging, you need to add this set stroke for the shape
stroke: 'black',
and at the end of drawFunc
canvas.fillStroke(this);
Here is the my working version from yours
http://jsfiddle.net/W7SGT/
You should be using the canvas renderer when drawing a custom shape in KienticJS, or else it has no way to handle the events on the shape. Here's a tutorial on custom shapes:
http://www.html5canvastutorials.com/kineticjs/html5-canvas-kineticjs-shape-tutorial/
you might also take a look at the Kinetic.Image shape to see how it handles images specifically:
https://github.com/ericdrowell/KineticJS/blob/master/src/shapes/Image.js

KineticJS layer index when dragging

So my problem seems to be that a draggable object always is drawn over other objects.
Check out my fiddle.
and my code:
<!DOCTYPE HTML>
<html>
<head>
<style>
body {
margin: 0px;
padding: 0px;
}
canvas {
border: 1px solid #9C9898;
}
</style>
<script src="http://www.html5canvastutorials.com/libraries/kinetic-v4.3.1-beta.js"></script>
<script>
window.onload = function() {
var stage = new Kinetic.Stage({
container: 'container',
width: 578,
height: 200
});
var cableLayer = new Kinetic.Layer();
// build cable
var cable = new Kinetic.Line({
strokeWidth: 40,
stroke: 'green',
points: [{
x: stage.getWidth() / 2,
y: stage.getHeight() / 2
}, {
x: 100,
y: 100
}],
draggable: true
});
// build center
var c1 = new Kinetic.Circle({
radius: 60,
fill: 'black',
draggable: true,
x: stage.getWidth() / 2,
y: stage.getHeight() / 2
});
var c2 = new Kinetic.Circle({
x: 100,
y: 100,
radius: 60,
fill: 'black',
draggable: true,
});
//add everything to the layer
cableLayer.add(cable);
cableLayer.add(c1);
cableLayer.add(c2);
//add all to stage
stage.add(cableLayer);
//What to do when something is changed...
cable.on('dragmove', (function () {
c1.setPosition([cable.getPosition().x + cable.getPoints()[0].x, cable.getPosition().y + cable.getPoints()[0].y]);
c2.setPosition([cable.getPosition().x + cable.getPoints()[1].x, cable.getPosition().y + cable.getPoints()[1].y]);
cableLayer.draw();
}));
c1.on('dragstart', (function () {
c1.getLayer().afterDraw(function () {
cable.attrs.points[0].x = c1.getX()-cable.getX();
cable.attrs.points[0].y = c1.getY()-cable.getY();
cableLayer.draw();
});
}));
c2.on('dragstart', (function () {
c2.getLayer().afterDraw(function () {
cable.attrs.points[1].x = c2.getX()-cable.getX();
cable.attrs.points[1].y = c2.getY()-cable.getY();
cableLayer.draw();
});
}));
}
</script>
</head>
<body onmousedown="return false;">
<div id="container"></div>
</body>
</html>
So, I tried to set the index using
cable.on('dragmove', (function () {
c1.setPosition([cable.getPosition().x + cable.getPoints()[0].x, cable.getPosition().y + cable.getPoints()[0].y]);
c2.setPosition([cable.getPosition().x + cable.getPoints()[1].x, cable.getPosition().y + cable.getPoints()[1].y]);
c2.setIndex(1);
c1.setIndex(1);
cable.setIndex(2);
cableLayer.draw();
}));
Doesn't seem to work? Why is this? How do I get the circles to draw over the line in all cases? Mainly the case that you drag the line.
Is there somewhere I'm setting this differently somewhere else?
Thanks for your help
http://jsfiddle.net/nYHrg/3/
So the problem is that kineticjs (4.3.0) added a new 'drag' layer to improve dragging performance. Any time that you drag an object, it is put in the drag layer, and when you stop dragging, it is put back in it's own layer. This does not preserve your original z-index. Anytime you create a new object and you want to override this functionality you will have to set one of the attributes of the object as:
"dragOnTop: false"
see jsfiddle for exact implementation.

Changing the anchors on a kineticJS canvas to arrows?

I have been playing about with kineticjs and the canvas as of the last couple of days. I have a drag and drop canvas that loads a resizable image. the anchors on the resizable image are circles:
var anchor;
function addAnchor(group, x, y, name) {
var stage = group.getStage();
var layer = group.getLayer();
anchor = new Kinetic.Circle({
x: x,
y: y,
stroke: "#666",
fill: "#ddd",
strokeWidth: 2,
radius: 8,
name: name,
draggable: true
});
anchor.on("dragmove", function() {
update(group, this);
layer.draw();
});
anchor.on("mousedown touchstart", function() {
group.setDraggable(false);
this.moveToTop();
});
anchor.on("dragend", function() {
group.setDraggable(true);
layer.draw();
});
// add hover styling
anchor.on("mouseover", function() {
var layer = this.getLayer();
document.body.style.cursor = "pointer";
this.setStrokeWidth(4);
layer.draw();
});
anchor.on("mouseout", function() {
var layer = this.getLayer();
document.body.style.cursor = "default";
this.setStrokeWidth(2);
layer.draw();
});
group.add(anchor);
}
I would like to turn them into arrows, or something similar to show users that infact the image is resizeable. Does anyone have a method of doing this or a tutorial that may show me how to either draw arrows or replace the anchors with an image?
Thanks for any help...
I think you'll need to change the new Kinetic.Cirle and it's properties to something like this:
var anchor = new Kinetic.RegularPolygon({
x: x,
y: y,
sides: 3,
rotation: -190,
radius: 8,
stroke: "black",
strokeWidth: 2,
name: name,
draggable: true
});
Although this is only the beginning, due to having a different rotation on each anchor, you will also have to add more variables to the group of anchors as to have each triangle face the correct direction.
I have only briefly tested this, but I hope it helps as a starting point.
Remember to double check the Docs.
EDIT: Also see here.