This is what I need in KineticJS:
I have a large 300x300 image, I want to be able to drag it, but only if I click-drag in the upper quarter of the image. if I try to drag the rest of this image, I don't want it to move. Is this possible?
Furthermore, If I try to drag this image, how can I make it drag the rest of the items in the group along with it?
the easiest thing to do would be to create a custom hit region function that defines a rectangular region in the top right corner of the image. Here's an example:
http://www.html5canvastutorials.com/kineticjs/html5-canvas-kineticjs-custom-hit-function-tutorial/
See here: http://jsfiddle.net/NnD5q/
box.on('mousedown', function(e){
var bX = box.attrs.x, bY = box.attrs.y;
// set draggable false if they aren't in our click range
// (a 20x20 square in the top left)
if (e.x > bX + 20 || e.y > bY + 20)
box.setDraggable(false);
});
window.onmouseup = function(e){
box.setDraggable(true); // set draggable true on **window** mouseup.
};
Another option would be to create a drag handle object, group.setDraggable(true) on mousedown for that drag handle, then group.setDraggable(false) on window mouseup. This second option is likely much cleaner.
Related
I am using next code to force content of canvas to follow finger touch movement on screen (drag and drop).
document.addEventListener('touchmove', function(e){
if(e.targetTouches.length ==1) {
var canavasMovex=e.targetTouches[0].pageX-canvasLeftofset-canvas.width/2;
var canavasMovey=e.targetTouches[0].pageY-canvasTopofset-canvas.height/2;
document.getElementById("a").innerHTML= canavasMovex;
document.getElementById("b").innerHTML= canavasMovey;
var delta = new fabric.Point(-canavasMovex,-canavasMovey);
canvas.absolutePan(delta);
canvas.renderAll();
}
}, false);
Note: "-canavasMovex,-canavasMovey" values have the negative sign (I had to use it because otherwise the canvas was moving opposite to finger moment(I think you can ignore this fact and that it has noting to do with offset, which I am trying to solve asking for help here))
I have displacement of position proportional to the distance of touch point from the centre of canvas. If I start the movement pressing from the centre of screen, then displacement is not so notable. But if I start from top corner (for example) I get centre of canvas there in that touch point. From attached drawing I was trying with taking of consideration of "d" parameter (distance of touching point to the centre of canvas), to find right value for the equation for the canvas.absolutePan() function, but no success. Can you help me with this case,pleas? I was trying to use some solutions from browsing the internet to find the way to move canvas content. But then I had lost some of functions of my app because "new" libraries were not interacting correctly with my existing fabric.min.js library. Image info(external rectangle-web page,internal rectangle-canvas): a-canvas offset,b-distance to centre of canvas,c- touch point,d-distance from touch point to centre of canvas. So on the end I am trying to get to accomplish this task in this way.
Malfunction:
Bigger than distance "d" is on starting of dragging , bigger is then the offset. (actuary if I start dragging from canvas corner, canvas content transfers its centre there)
The solution is to get the finger position, calculate the difference to previous position, add difference to the previous position and then finally do the panning.
var canvasMovexoold = 0;
var canvasMoveyoold = 0;
document.addEventListener('touchstart', function(e){
canvasMovexoold = canvasLeftofset+canvas.width/2-e.targetTouches[0].pageX;
canvasMoveyoold =canvasTopofset+canvas.height/2- e.targetTouches[0].pageY;
}, false);
document.addEventListener('touchmove', function(e){
if(e.targetTouches.length ==1) {
var canvasMovexo += canvasLeftofset+canvas.width/2-e.targetTouches[0].pageX-canvasMovexoold ;
var canvasMoveyo +=canvasTopofset+canvas.height/2- e.targetTouches[0].pageY-canvasMoveyoold ;
var delta = new fabric.Point(canvasMovexo,canvasMoveyo);
canvas.absolutePan(delta);
canvasMovexoold = canvasLeftofset+canvas.width/2-e.targetTouches[0].pageX;
canvasMoveyoold =canvasTopofset+canvas.height/2- e.targetTouches[0].pageY;
}
}, false);
I've been using easelJS within the createJS framework for a project and have enjoyed it a lot until recently hitting a roadblock. I have multiple objects that I'd like to move simultaneously when one of the group is dragged. Here is my current situation:
What I'd like to do is when the red circle is moved, the red crosshairs would also move so that they appear to be "locked" to the circle. The same with the green circle.
I have been able to accomplish something very close to this by adding the circles and crosshairs to a container, as mentioned in the answers to this question:
Easeljs Scrollable Container
But the issue I encounter is that the container is actually a rectangle, such that I can click anywhere between the circle and crosshairs to move the various objects contained within the container. Instead I would like for the objects to be moved only when I click on a circle.
Does anyone have any idea how to accomplish this? Am I correct in thinking this can be accomplished somehow with easelJS containers?
Containers should be fine. You can turn off mouseEnabled on the cross-hair in order to make it ignore the mouse.
You could also just store the offset for each cross-hair/circle, and just set the cross-hair position when the circle moves.
Here is a quick demo:
http://jsfiddle.net/lannymcnie/kah9of6e/
// Set the offset when the circle is pressed
circle.on("mousedown", function(e) {
circle.offset = new createjs.Point(crosshair.x-circle.x, crosshair.y-circle.y);
});
// Add drag and drop to each shape
circle.on("pressmove", handleDrag);
crosshair.on("pressmove", handleDrag);
function handleDrag(e) {
// Move the target to the mouse
e.target.x = e.stageX; e.target.y = e.stageY;
// If the target is the circle, also move the cross-hair
if (e.target == circle) {
// Move the cross-hair
crosshair.x = circle.x + circle.offset.x;
x.y = circle.y + circle.offset.y;
}
}
I have a canvas that's initially panned so that the 0,0 point is in the middle of the screen. I'm trying to move a programmatically created group, but for some reason the group moves relative to the upper left corner of the visible canvas instead of the 0,0 point of the canvas. After that first movement the panning works correctly and the group moves around that position, until I discard it and create it again, and then it's relative to the upper left corner again, without taking the pan into account. If I create a group selection using the selection tool, it works correctly every time.
I pan the canvas with this:
var offsetX = -canvas.getWidth()/2;
var offsetY = -canvas.getHeight()/2;
canvas.absolutePan(new fabric.Point(offsetX, offsetY));
This is how I create the group:
var group = new fabric.Group();
objects.forEach(function (o) {
group.addWithUpdate(o);
canvas.remove(o);
});
canvas.add(group);
Then I try to move it with this:
group.set("left", 0);
canvas.renderAll();
And then the group is right at the left edge of the canvas element. But if I select the group with my mouse and use this instead, it appears right where it should be - in the center:
canvas.getActiveGroup().set("left", 0);
canvas.renderAll();
So, how do I get this to work properly? I know I could just calculate an offset from the canvas transformations, but I feel like this should be compensated for in the library itself and I'm either somehow using it wrong or it's a bug.
this is the code I wrote until now: http://jsfiddle.net/wQ8YA/1/
I'm trying to implement a drag & drop using jQuery and KineticJS. I did it and it's working greatly except from some details :
1- When I drag something (shape/image), it's dragged "behind" the grid, and appears only when I release the mouse.
2- The drop point is NOT where the image is rendered, it's not drawn where I drop it! This problem showed up only when I decided to make the drop zone a grid, next to an accordion.
3- I can't move a group of shapes (a rectangle + an image inside of it)
I need help, please tell me if I missed a line or a detail in the code. Here's the dragDrop function. To see the whole code and understand well my problem, see the fiddle above.
$stageContainer.droppable({
drop: dragDrop
});
// handle a drop into the Kinetic container
function dragDrop(e, ui) {
// get the drop point
var x = parseInt(ui.offset.left - offsetX, 10);
var y = parseInt(ui.offset.top - offsetY, 10);
// get the drop payload (here the payload is the image)
var element = ui.draggable;
var data = element.data("url");
var theImage = element.data("image");
// create a new Kinetic.Image at the drop point
// be sure to adjust for any border width (here border==1)
var image = new Kinetic.Image({
name: data,
x: x,
y: y,
image: theImage,
draggable: true
});
layer.add(image);
var $clone = ui.helper.clone();
if (!$clone.is('.inside-droppable')) {
$(this).append($clone.addClass('inside-droppable').draggable({
containment: $stageContainer,
tolerance: 'fit',
position: 'relative'
}));
if ($clone.is(".imag") === false) {
$clone.resizable({
containment: $stageContainer
});
}
}
}
Fix #1 (dragged object goes behind canvas): put the kinetic container before the accordion in the html.
Fix #2 The dropzone has been moved to the right when the accordion is sized by jQuery, so you need to recalculate offsetX and offsetY after the accordion has been sized.
Fix #3 You can create a draggable Kinetic.Group and put your children shapes inside that group. When the group is dragged the children will be dragged also.
Cheers!
I am trying to get the x and y of an html button to that of a mouseclick by the user, I am doing this as follows:
function buttonPressed(event, id){
var mainEvent = event ? event : window.event;
var mousex=event.clientX;
var mousey=mainEvent.screenY;
var y= $('#'+id).position();
var x= document.getElementById(id).offsetLeft;
console.log(y);
console.log(mousey);
This shows 2 different ways to get these value of both the button and the mouse (event.clientX,mainEvent.screenY,$('#'+id).position()(uses jquery),and offsetLeft).
However none of these techniques seem to work as I would like them to as the values do not line up ie when I click on the top left of the button the values are not the same or even similar. Additionally it seems like the difference changes, for example: if I have a button top left and one top right on the top left the values may differ by 100, whereas the bottom they will differ by -100. How can I acheive what I am wanting (to be able to compare the mousex and the button x)?
client X/Y Mouse pointer X/Y coordinate relative to window
offset X/Y Mouse pointer X/Y coordinate relative to element that fired the event
screen X/Y Relative to the top left of the physical screen/monitor
Thats why you are getting difference here
var mousex=event.clientX;
var mousey=mainEvent.screenY;
Use clientX for both