KineticJS: Animate an item to go back to initial position when not dropped in drop target - drag-and-drop

I made an application which performs drag and drop of different items: images and shapes. I limited the drop target to a specific layer: rightLayer in my case using a simple test with if ... else. Everything works great, except that I want to make an item revert back to its original position in the leftLayer when it doesn't attempt the borders of rightLayer (just like jquery, but in kineticJS). Or just disappear instantly.
Here's a JSFIDDLE . For a better understanding, try this use case:
drag the rectangle,
drop it right before the grid,
click on an item from the left layer.

You can self-destruct any clone dropped other than in the dropzone with a test in dragend.
A Demo: http://jsfiddle.net/m1erickson/2T68g/
clone1.on("dragend",function(){
// destroy this clone if dropped outside the dropzone
if(this.x()<dropzone.x()){
this.destroy();
layer.draw();
}
});

Related

In Scratch, how can the clone A of Sprite2 detect if it's touching another clone B of the same Sprite2 and delete both clones?

This is for a mini program in Scratch.
What I want to do:
When a clone A of Sprite2 touches another clone B of the same Sprite2, both clones are deleted, but any other clone stays existing and executing.
What I have tried:
I have tried finding if there was an option like "touching another clone", but I haven't found it.
I also tried putting a sensor that detects if a clone is making contact with its same color (if[color{red}is touching color{red}] then) => (delete clone), but it didn't work, it entered an infinite loop where the page begun to get choppy so I deleted that.
I even made the function outside the sprite (where I could find the option (touching [sprite2] ?)) and then moved the function inside sprite2 but it ignores that new inserted function.
Do you know how this could be done?
As seen in your screenshot, the dropdown list of the 'touching' block shows a list of all sprites in the project (in this case Sprite1) except the current sprite (Sprite2).
Fortunately, it is possible to have a 'touching Sprite2' block within Sprite2.
It's a bit of a hack, but it works. Follow these steps:
Go to the code area of Sprite1. (Any sprite will do except Sprite2. If Sprite2 is the only sprite in the project, add a dummy sprite; you can safely remove it after step 4.)
From the 'sensing' group, drag a 'touching' block onto the code area.
Open the block's dropdown and select Sprite2.
Drag the block from the code area to Sprite2 (as seen in the sprite collection, bottom right).
Go to Sprite2. Notice there's a 'touching Sprite2' block there. Drag it to the script where you need it.
When using this to make clones disappear as they collide, you may notice that only one clone will disappear, and the other will survive.
This is a 'race condition': simultaneous events never happen exactly at the same time.
The first clone to detect the collision deletes itself, thereby erasing the incident before the other clone has had a chance to detect it.
In most cases, this can be fixed by adding a 'wait 0 seconds' block immediately above the 'delete this clone' block.
Waiting zero seconds may seem like a no-op, but it actually has effect:
it gives other threads (scripts, clones, sprites) the time to catch up with the current one.
Live demo:
https://scratch.mit.edu/projects/704352756/

Can QML drag-and-drop mechanic work without drag item moving?

I have a listview and a rectangle on top of it. The ListView's delegates have DropAreas in them and the rectangle has drag enabled on Y axis with its relevant properties (hotspot, target).
When I move the rectangle up and down on the ListView, the DropAreas of the delegates are registering onEntered signals. Working as intended.
However, I am using SmoothedAnimation to scroll the list up and down when the rectangle is at the most top and bottom coordinates (list.y = 0 and list.height). So the rectangle is not moving, and the DropAreas of the list's delegates are moving under it. In that case, the onEntered is not registered because there is no dragging, the rectangle is completely still and although its hotspot is entering and leaving the DropAreas, there is no interaction.
This is because dragging mechanic is sending events all the time when moving and any DropAreas it comes inside can register the event. In my case there is no dragging and therefore no events.
Question: Can drag events be manually activated? Can I somehow simulate drag?
At first, you should change the drag.target: parent to drag.target: this. In this way instead of dragging the parent item, you drag only the mouseArea. After that, you should grab an image from the item that you want to drag. The code is here:
Rectangle {
id: rec
width: 100
height: 100
Drag.active: dragArea.drag.active
Drag.dragType: Drag.Automatic
Drag.supportedActions: Qt.CopyAction
MouseArea {
id: dragArea
anchors.fill: parent
drag.target: this
onPressed:{
parent.grabToImage(function(result) {
parent.Drag.imageSource = result.url
})
}
}
}
I have managed to induce drag events by manually changing the hotSpot property of the rectangle above the list. QML Drag documentation says:
Changes to hotSpot trigger a new drag move with the updated position.
So I have done this every time Listview contentY changes (vertical scrolling happens)
onContentYChanged:
{
rectangle.Drag.hotSpot.x += 0.0001
rectangle.Drag.hotSpot.x -= 0.0001
}
In hindsight, however, this is a 'hacky' solution. hotSpot property is a QPointF class property (link). This means it can be set using various methods (setX, setY, rx, ry..). For example, this:
rectangle.hotSpot += Qt.point(0,0)
or
rectangle.hotSpot = Qt.point(rectangle.hotSpot.x,rectangle.hotSpot.y)
should work in theory by resetting the hotSpot point when contentY changes, but testing revealed it unfortunately does not trigger a new drag move. (bug or intended, I don't know)
Now some of you that are more into Qt and QML might know more about this and how to properly adress the issue, but the above solution works for me and after testing everything I could imagine to get a cleaner solution, I settled on it.

Konva drag drop without moving drag element

My question is how to drag and drop a shape, but with cloning the draggable shape, and dragging that clone to the droppable shape.
I am new to Konva. While looking around the documentation & examples I could find how to drag and drop a shape.
I found reference to cloning of the shape, but I am not sure how to do this.
If someone could show me the way that would be very much appreciated.
Thank you
rect.on('dragstart', function() {
// stop dragging original rect
rect.stopDrag();
// clone it
var clone = rect.clone({
x : 50,
y : 50
});
// events will also be cloned
// so we need to disable dragstart
clone.off('dragstart');
// then add to layer and start dragging new shape
layer.add(clone);
clone.startDrag();
});
http://jsbin.com/hujulasaro/1/edit?html,js,output
for drop events see demo: http://konvajs.github.io/docs/drag_and_drop/Drop_Events.html

Detect drop target with HammerJS

I'm using HammerJS to abstract drag, scale and rotate for desktop and mobile. All I'm missing is drop. How do I define an element as a drop target that throws an event when another element is dragged over or dropped onto it? Something like jQueryUI's droppable that will work with HammerJS?
Thanks.
Just solved that today.
On dropping object, set a global "look for me" flag. and then setTimeout() to shortly (say 30ms) set it back to false.
Hide (and move) the dropped object, putting it back after a short time allowing the onMouseOver and onMouseOut events to trigger on the drop target object.
Watch those events for the "look for me" flag.
I haven't really tried it much yet.
(My first post.)
The only one fast way for detect drop target element is to use
document.elementFromPoint
Like this:
function dragEnd($event){
var targetEl = document.elementFromPoint($event.gesture.center.pageX, $event.gesture.center.pageX);
your code
}

Click-through markers and polylines in Leaflet

In Leaflet, is it possible to define a marker or polyline with {clickable:false}, so that a click is passed through to whatever lies beneath - be it the map or a clickable geometry object?
At the moment I solve this problem by making the marker/polyline clickable and passing the event onwards myself. But this leads to the mouse cursor always showing as the hand symbol. Ideally, the mouse cursor should look like the normal pointer or the hand, depending on whether what is beneath the marker/polyline is clickable.
This may not be the answer you are looking for, but you can use featureGroups to have all of your clickable polylines come to the front so that the actions are surfaced.
var lg_noclick = new L.FeatureGroup().addTo(map);
var lg_click = new L.FeatureGroup().addTo(map);
// Add lines
lg_click.bringToFront();
updated fiddle
Also if you can afford to know your lines before hand, correct ordering of when you add the lines it will work as well.
I know this is not ideal but it suited my situation just fine, so it might be good for you as well.
This hides the icon and brings it back after a second using mouseenter and mouseleave events:
$('.leaflet-marker-icon').mouseenter(function() {
$(this).hide();
});
$('.leaflet-marker-icon').mouseleave(function() {
$(this).delay(1000).show(0);
});