Copy link to clipboard
Copied
Hi, I've just been asked if I can produce an "Incident" map where various symbols of personnel and vehicles can be dragged onto a map to demonstrate what is to be done in response to an emergency.
I have some fairly basic experience in Animate so the "drag and drop" functionality is manageable, but what I really need to be able to do is have multiple/indefinite numbers of each symbol available to the use, so when a symbol is dragged from a menu area and dropped onto the map, another version of that symbol pops up in its place on the menu, ready for dragging and dropping if required - effectively re-spawned.
Is this something that can be achieved and, if so, how would it be done?
1 Correct answer
Here is a sample.
Preview:
JavaScript code:
const root = this;
let spawnedItem;
function main()
{
createjs.Touch.enable(stage);
stage.mouseMoveOutside = true;
root.stop();
root.menu.children.forEach(child => child.mouseChildren = false);
root.menu.on("mousedown", menuDown);
root.menu.on("pressmove", menuMove);
root.menu.on("pressup", menuUp);
root.map.on("mousedown", mapDown);
root.map.on("pressmove", mapMove);
}
function menuDown(e)
{
spawnedItem = new e.t
...
Copy link to clipboard
Copied
Hi.
One approach would be to add a new symbol instance from Library (using addChild or addChildAt) on top of the selected menu item in a mouse down event handler and then add the drag and drob behavior to this new instance.
Meaning that you'll add the same drag and drop behavior you already have but to a instance that has just been instantiated at runtime.
Please let us know if you need further assistance.
Regards,
JC
Copy link to clipboard
Copied
Thank you for your assistance JC - and yes, with my limited experience, I probably will need further assistance! 🙂
Copy link to clipboard
Copied
is this an html5 app?
Copy link to clipboard
Copied
Yes, oops sorry... I forgot to mention that
Copy link to clipboard
Copied
assign a linkage to each library symbol (eg, S) you want the ability to add, and use
var s = new lib.S(); // to create an instance
this.addChild(s); // to add the instance to the stage at 0,0
Copy link to clipboard
Copied
Here is a sample.
Preview:
JavaScript code:
const root = this;
let spawnedItem;
function main()
{
createjs.Touch.enable(stage);
stage.mouseMoveOutside = true;
root.stop();
root.menu.children.forEach(child => child.mouseChildren = false);
root.menu.on("mousedown", menuDown);
root.menu.on("pressmove", menuMove);
root.menu.on("pressup", menuUp);
root.map.on("mousedown", mapDown);
root.map.on("pressmove", mapMove);
}
function menuDown(e)
{
spawnedItem = new e.target.constructor();
spawnedItem.x = e.currentTarget.x + e.target.x;
spawnedItem.y = e.currentTarget.y + e.target.y;
spawnedItem.mouseChildren = false;
root.addChild(spawnedItem);
setDrag(spawnedItem);
}
function menuMove()
{
drag(spawnedItem);
}
function menuUp(e)
{
var dropPoint = { x: spawnedItem.x, y: spawnedItem.y };
if (root.mapRec.hitTest(dropPoint.x - root.mapRec.x, dropPoint.y - root.mapRec.y))
{
root.map.addChild(spawnedItem);
spawnedItem.x = dropPoint.x - root.map.x;
spawnedItem.y = dropPoint.y - root.map.y;
}
else
root.removeChild(spawnedItem);
spawnedItem = null;
}
function mapDown(e)
{
setDrag(e.target);
}
function mapMove(e)
{
drag(e.target, root.mapRec.nominalBounds);
}
function setDrag(target)
{
target.offset =
{
x: stage.mouseX / stage.scaleX - target.x,
y: stage.mouseY / stage.scaleY - target.y
};
}
function drag(target, dragArea)
{
target.x = stage.mouseX / stage.scaleX - target.offset.x;
target.y = stage.mouseY / stage.scaleY - target.offset.y;
if (dragArea)
{
target.x = clamp(dragArea.x, target.x, dragArea.x + dragArea.width);
target.y = clamp(dragArea.y, target.y, dragArea.y + dragArea.height);
}
}
function clamp(min, value, max)
{
if (value < min)
return min;
if (value > max)
return max;
return value;
}
main();
Download / source / files:
https://bit.ly/3W9A6wy
Regards,
JC
Copy link to clipboard
Copied
Hi JC,
Thank you for that - I shall give it a try and let you know how I get on 🙂
Copy link to clipboard
Copied
That works brilliantly - thank you JC 😄
Copy link to clipboard
Copied
is there a way that I can give the user the ability to zoom in and out on any area of the map?
Copy link to clipboard
Copied
sorry... one more question. If a symbol is dragged onto the map by mistake, is there a way to remove it? I really appreciate all of the help
Copy link to clipboard
Copied
Hey, @Robb Nemo . I've been away to assist my wife with our newborn. 😄
But how do you want the instances to be removed? By only clicking on them? Will there be a delete button somewhere?
Copy link to clipboard
Copied
Congratulations to you and your wife 🙂 Newborns definitely add a whole new dimension to time management lol.
Re: the instance removal - ideally I'd like to remove the individual instances just by dragging them off the map onto the menu, but it would be useful to have an additional "clear all" button option to remove all of the icons on the map. Any help is much appreciated 🙂
Copy link to clipboard
Copied
use the code i suggested in your duplicate post.
Copy link to clipboard
Copied
Hi kglad,
thanks for responding and apologies - I started another thread because I thought this one had died... but it's obviously still active 🙂
I added your code
function removeF(obj){
if(obj.parent){
obj.parent.removeChild(obj);
}
}
to the one that JoãoCésar posted, but I couldn't seem to make it do anything - I think I must be missing something but, as I mentioned earlier, I'm not exactly a genius when it comes to coding so I 'm extremely grateful for all contributions and help 🙂
Copy link to clipboard
Copied
you have to call removeF. when ypu want to remove your object. do you know any coding?
Copy link to clipboard
Copied
My real talents lie in the visual arts and the world of music composition. Sadly, when it comes to coding, beyond the basics, my brain functions resemble more of a Jackson Pollock than a Mondrian painting, so the skills and logical approach of someone like yourself elude me! Each to their own 🙂
Copy link to clipboard
Copied
if you're using the drag/drop code above, isn't the dragged item removed when it's dropped outside map?
Copy link to clipboard
Copied
if you're using the drag/drop code above, isn't the dragged item removed when it's dropped outside map?
By kglad
It would be ideal if it could do that, but at the moment, on the intial drag (without dropping) the item will disappear when dropped outside the map area, but once dropped within the map, although the item remains draggable, it becomes confined to the map area and can't be moved outside the map perimeters
Copy link to clipboard
Copied
Hi again!
Thank you very much for the compliments! And, yeah, they also add a whole new dimension to wrtiting code while we hold them in our arms! 😄
Just added a v2. Hopefully it will address the remaining requested features.
Preview:
JavaScript code:
const root = this;
const SPACE_KEY = "Space";
let keys, spawnedItem;
function main()
{
createjs.Touch.enable(stage);
stage.mouseMoveOutside = true;
keys = {};
root.stop();
root.map.minZoom = 1;
root.map.maxZoom = 3;
root.map.zoomStep = 0.05;
root.menu.children.forEach(child => child.mouseChildren = false);
root.menu.on("mousedown", menuDown);
root.menu.on("pressmove", menuMove);
root.menu.on("pressup", menuUp);
root.map.on("mousedown", mapItemDown);
root.map.on("pressmove", mapItemMove);
root.map.on("pressup", mapUp);
root.mapRec.on("mousedown", mapDown);
root.mapRec.on("pressmove", mapMove);
root.clearAllButton.on("click", clearMap);
window.addEventListener("keydown", onKeyDown);
window.addEventListener("keyup", onKeyUp);
canvas.addEventListener('mousewheel', onMouseWheel);
canvas.addEventListener('DOMMouseScroll', onMouseWheel);
}
function menuDown(e)
{
spawnedItem = new e.target.constructor();
spawnedItem.x = e.currentTarget.x + e.target.x;
spawnedItem.y = e.currentTarget.y + e.target.y;
spawnedItem.mouseChildren = false;
root.addChild(spawnedItem);
setDrag(spawnedItem);
}
function menuMove()
{
drag(spawnedItem);
}
function menuUp(e)
{
const dropPoint = { x: spawnedItem.x, y: spawnedItem.y };
if (root.mapRec.hitTest(dropPoint.x - root.mapRec.x, dropPoint.y - root.mapRec.y))
{
let localPos;
root.map.addChild(spawnedItem);
localPos = root.map.globalToLocal(dropPoint.x * stage.scaleX, dropPoint.y * stage.scaleY);
spawnedItem.x = localPos.x;
spawnedItem.y = localPos.y;
spawnedItem.fromMenu = true;
}
else
root.removeChild(spawnedItem);
spawnedItem = null;
}
function mapItemDown(e)
{
if (keys[SPACE_KEY])
setDrag(e.currentTarget);
else
{
if (e.target.fromMenu)
setDrag(e.target);
}
}
function mapItemMove(e)
{
if (keys[SPACE_KEY])
drag(e.currentTarget);
else
{
if (e.target.fromMenu)
drag(e.target);
}
}
function mapDown(e)
{
if (keys[SPACE_KEY])
setDrag(root.map);
}
function mapMove(e)
{
if (keys[SPACE_KEY])
drag(root.map);
}
function mapUp(e)
{
const pos = e.target.localToLocal(0, 0, root.mapRec);
if (!keys[SPACE_KEY] && !root.mapRec.hitTest(pos.x, pos.y))
{
e.target.parent.removeChild(e.target);
e.target = null;
}
}
function onKeyDown(e)
{
keys[e.code] = true;
}
function onKeyUp(e)
{
delete keys[e.code];
}
function onMouseWheel(e)
{
const evt = window.event || e;
const mouseWheelDelta = clamp(-1, evt.wheelDelta || -evt.detail, 1);
const localCursorPosBefore = root.map.globalToLocal(stage.mouseX, stage.mouseY);
let localCursorPosAfter;
root.map.regX = localCursorPosBefore.x;
root.map.regY = localCursorPosBefore.y;
localCursorPosAfter = root.map.globalToLocal(stage.mouseX, stage.mouseY);
root.map.x += (localCursorPosAfter.x - localCursorPosBefore.x) * root.map.scaleX;
root.map.y += (localCursorPosAfter.y - localCursorPosBefore.y) * root.map.scaleY;
root.map.scale = clamp(root.map.minZoom, root.map.scale + mouseWheelDelta * root.map.zoomStep, root.map.maxZoom);
}
function clearMap(e)
{
let i, child;
for (i = root.map.numChildren - 1; i > -1; i--)
{
child = root.map.children[i];
if (child.fromMenu)
{
child.parent.removeChild(child);
child = null;
}
}
}
function setDrag(target)
{
const pos = target.parent.globalToLocal(stage.mouseX, stage.mouseY);
target.offset =
{
x: pos.x - target.x,
y: pos.y - target.y
};
}
function drag(target)
{
const pos = target.parent.globalToLocal(stage.mouseX, stage.mouseY);
target.x = pos.x - target.offset.x;
target.y = pos.y - target.offset.y;
}
function clamp(min, value, max)
{
if (value < min)
return min;
if (value > max)
return max;
return value;
}
main();
Download / source / files:
https://bit.ly/3W9A6wy
Copy link to clipboard
Copied
JoãoCésar Thank you so much, the dag and drop works brilliantly. I notice the script looks like it uses touch gestures for the map zoom and drag. Although it will some times be used on a tablet, the map will be mainly used on desktops/laptops, and on something like a Prowise board for presentations, so is there any way that the zoom and drag functions can be added to buttons, similar to the way that Google maps work?

