The current scenario I need to solve, is rotating an image with the mousewheel.
As KineticJS does not have a specific hook for the mousewheel event (in that it's not a standard one anyway), I've used jquery-mousewheel to hook into the surrounding canvas, and KineticJS to store, on mouseover, the image that requires rotation.
On the mousewheel event, it checks if KineticJS has marked an image for rotation, it then goes ahead and rotates the image.
I'm not sure this is the best solution for the situation, as it doesn't take into account overlapped images (although I could probably prioritise the marking of 'active' shape to the topmost on the stack), or if this is even the most efficient solution.
Essentially:
on each shape-
this.image.on("mouseover", function() { Engine.scrolling = _this.image;})
this.image.on("mouseout", function() { Engine.scrolling = null;})
on the outer container -
$("#DraftingBoard").mousewheel(function(event, delta, deltaX, deltaY){
if(Engine.scrolling != null)
{
Engine.scrolling.rotateDeg(90);
Engine.scrolling.getLayer().draw();
event.preventDefault();
}
Related
I have a Konva stage that currently displays a series of shapes. I would like to have a shapes panel, where I can drag shapes and insert into the canvas.
There are currently two ways of doing this:
Adding the Shapes Panel to the Konva stage as it's own layer and entity
Having the Shapes Panel as a standalone HTML element outside the Konva stage and implement a draggable js library to handle dragging behaviour
I'd rather option 2; being able to style the shapes panel with CSS and yield a number of other DOM related benefits is more attractive to me right now.
I have the dragging behaviour sorted, but there is one issue: even though I've implemented stage mouseover events, dragging an element that originates from outside the canvas to on top of the canvas doesn't actually trigger the stage event listeners.
Is there a way around this?
What's interesting is that if you click and hold the mouse outside the element and hover over the canvas, the event listeners fire. But, when you're actually dragging an element (text, image), the event listeners do not fire...
Take a look into this demo: https://konvajs.org/docs/sandbox/Drop_DOM_Element.html
var con = stage.container();
con.addEventListener('dragover', function(e) {
e.preventDefault(); // !important
});
con.addEventListener('drop', function(e) {
e.preventDefault();
// now we need to find pointer position
// we can't use stage.getPointerPosition() here, because that event
// is not registered by Konva.Stage
// we can register it manually (with private method):
stage.setPointersPositions(e);
// now you can add a shape. We will add an image
Konva.Image.fromURL('/assets/yoda.jpg', function(image) {
layer.add(image);
image.position(stage.getPointerPosition());
image.draggable(true);
layer.draw();
});
});
I have a transparent drag layer on top of a shape layer. Works great to make interaction distinct so I can toggle what dragging does (between scrolling the view or editing the shape positions). However, unless I turn off drag mode (by hiding the intervening transparent Rect), none of the other mouseover events fire on the shape layer beneath it. I need to propogate the non-drag mouse events to the layer below it. There are A LOT of shapes with mouse over events.
Is there an easy way to propogate the mouse over events to the layer beneath it or do I need to write a custom handler to fire events for every shape?
I managed to solve this without having to propagate events between layers. I put a draggable surface behind the shapes on the shape layer only if a shape isn't clicked. Then to cover if a shape is clicked, on the shape dragstart event, if a layerdraggable flag is set, I do a stopDrag() on the shape and a startDrag() on the layer. This allowed me to toggle with a simple flag whether I want the whole layer dragging, or just the shape.
I had to clean up a little of the shape position on the dragend event, but alternatively you can do that with a dragbounds on the shape.
shape.on('dragstart', function () {
if (layerDraggable) {
shape.stopDrag();
shapeLayer.startDrag();
}
}
I'm making a game where the bubbles (circles) appear on the screen and move upwards and I'm using HTML5 and JavaScript only which means no frameworks like kinetic and no jQuery at all.
I've come to a point where I want to add an event listener to the bubble itself, now I understand that because the bubble is an object on the canvas, it has no method 'addEventListener' so I can't directly add a click event to the bubble, I was wondering if anybody could help me with this problem I'm having? Here is a fiddle of what happens so far...
Bubbles
I have tried to add the event listener to the bubble as specified before by doing this...
bubbles[i].addEventListener('click', function);
I have also tried adding mouseevents such as
bubbles[i].onmouseenter = function () { console.log("blah") }
But now, I'm seriously at a loss
Thanks in advance!
I have updated your sample on jsfiddle demonstrating hit-testing. This sample uses an onmousemove event handler bound to the canvas and performs the actual hit-test when this event occurs. The hit-test in your case is "Is the mouse coordinate with in the bubble's circle?"
Summary of changes:
A "bubble" has a color property to demonstrate the effect of a hit test.
function hitTest(x, y) { ... } used to test whether the passed in coordinates are within the bubble.
function getMouse(e, canvas) ... used to transform the mouse coordinates to canvas relative coordinates. i.e, the mouse coordinate needs to be relative to the upper left hand corner of the canvas to be accurate.
I'm working in a tool to draw in a canvas using the framework Paper.js
I got an issue using iPad. When I'm drawing with one finger, that works. When I'm drawing with two fingers, one in the canvas and one outside the canvas, the second finger event is caught by the event onMouseDrag, and that put some stroke from the first finger to the second finger, not a good behaviour for me.
Example:
At the beginning, I start to draw with one finger. After I put the second finger outside the canvas and I continue to move my first finger. This is what happen.
Do you have any idea to avoid event when I'm outside the canvas?
Thanks.
If you don't want the finger outside to be detected, limit the target to your canvas.
var canvasElement = document.getElementById('canvasId') //or element
tool.onMouseDrag = function(event) {
if (event.event.target === canvasElement) { //my target canvas was nested like this
path.add(event.point);
path.smooth();
}
}
Well, you could test event.point.isInside(view.bounds). This will likely kill your performance if you test it while drawing, but you could cull the points after you're finished.
I want to create sort of a 3D effect with the shapes I generated with KineticJS on my canvas.
When I drag them to the top, the need to become smaller, and when dragged to the bottom, they need to become bigger.
The closest I got to what I wanted is with the mousemove event you see here
$.each(bubbles, function(){
var bubble = this;
bubble = new Kinetic.Circle({x:this.x, y:this.y, radius:this.r, fill:'#000000', draggable:true});
bubble.on("mousemove",function(){
bubble.setRadius((bubble.getY()/5));
});
layer.add(bubble);
});
But this only changes the radius when ending dragging and click the shape again.
It would be very nice if I can make it possible to change them "realtime", when dragging.
Does anyone have any idea how to solve this?
Here's my JSFiddle http://jsfiddle.net/ZsADd/1/
Thank you!
I think what you want is bubble.on("dragmove"). Here is an example of it in action. For more info on drag events, look into the documentation which I found here.
To detect drag and drop events with KineticJS, we can use the on()
method to detect dragstart , dragmove, or dragend events. The on()
method requires an event type and a function to be executed when the
event occurs.