HTML Canvas - Drag object along a path

Engaged ,
Mar 16, 2022 Mar 16, 2022

Copy link to clipboard

Copied

Looking for an example of dragging an object (e.g. symbol) along a path. In this case just aound a circle path.

Views

311

Likes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Adobe Community Professional ,
Mar 16, 2022 Mar 16, 2022

Copy link to clipboard

Copied

you can code that 100% or create a tween of the object moving along the circle and then code that.

Likes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Engaged ,
Mar 16, 2022 Mar 16, 2022

Copy link to clipboard

Copied

@kglad   Do you have an example?

Likes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Adobe Community Professional ,
Mar 16, 2022 Mar 16, 2022

Copy link to clipboard

Copied

no, i don't.

Likes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Engaged ,
Mar 16, 2022 Mar 16, 2022

Copy link to clipboard

Copied

Well that's not helping at all...

Likes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Adobe Community Professional ,
Mar 17, 2022 Mar 17, 2022

Copy link to clipboard

Copied

if i had or have time, i'll work on that for you.  but, as far as i know, no one in these forums is obligated to do your work for you.

 

anything i can do within a few minutes, i'll usually do to help others, including you.  but once you get past 10 minutes of work, you should be willing to pay for that work.  you may not be charged, but if you're not willing, don't complain.

 

and you're not the only one asking for your work to be done for you.  i just saw this today too, Html5 abacus - Adobe Support Community - 12819568.  after starting my reply, this op posted a link so someone can do his/her work for them, too.

Likes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Adobe Community Professional ,
Mar 17, 2022 Mar 17, 2022

Copy link to clipboard

Copied

here's the code for the top half of the circle:

 

var r = 150;
var tol = 5000;
var cx = 300
var cy = 250;

this.c.addEventListener("pressmove",moveF.bind(this));


function moveF(e){
if( (stage.mouseX-cx)*(stage.mouseX-cx)+(stage.mouseY-cy)*(stage.mouseY-cy) < r*r+tol && (stage.mouseX-cx)*(stage.mouseX-cx)+(stage.mouseY-cy)*(stage.mouseY-cy) > r*r-tol ){
this.c.x = Math.min(stage.mouseX,cx+r);
this.c.x = Math.max(stage.mouseX,cx-r);
this.c.y = cy-Math.sqrt(r*r-(this.c.x-cx)*(this.c.x-cx));
}
}

Likes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Engaged ,
Mar 17, 2022 Mar 17, 2022

Copy link to clipboard

Copied

@kglad   I do appreciate your assistance, as well as your knowledge and experience, having seen your website, not just here on Adobe...   

 

BTW, I'm not asking for any work to be done on my behalf, just examples or tips that might help, as I do from time-to-time on other forums, e.g. Stack Overflow.  I'm here to learn Animate/Create.js/Easel.js as an Ed Tech developer in LAMP stacks.  The only way to learn properly is through application of knowledge.  Sometimes you just need some guidance.

 

Thanks for the code which will give me something to work from!  

 

Peter

Likes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Adobe Community Professional ,
Mar 18, 2022 Mar 18, 2022

Copy link to clipboard

Copied

here's the rest of the code though to make the dragging smooth when the mouse x is changing little (ie, east and west), you should defined this.c.y first and then this.c.x.

 

var r = 150;  // circle radius
var tol = 5000;  // tolerance (of mouse to circle)
var cx = 300  // center x of circle
var cy = 250;  // center y of circle

 

this.c.addEventListener("pressmove",moveF.bind(this));


function moveF(e){
if( (stage.mouseX-cx)*(stage.mouseX-cx)+(stage.mouseY-cy)*(stage.mouseY-cy) < r*r+tol && (stage.mouseX-cx)*(stage.mouseX-cx)+(stage.mouseY-cy)*(stage.mouseY-cy) > r*r-tol ){
var prev = this.c.x;
this.c.x = Math.min(stage.mouseX,cx+r);
this.c.x = Math.max(stage.mouseX,cx-r);
var sqrt = Math.sqrt(r*r-(this.c.x-cx)*(this.c.x-cx));
if(sqrt){
if(stage.mouseY<=cy){
this.c.y = cy-sqrt;
} else {
this.c.y = cy+sqrt;
}
} else {
this.c.x = prev;
}
}
}

Likes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Engaged ,
Mar 18, 2022 Mar 18, 2022

Copy link to clipboard

Copied

@kglad   Thanks very much for helping with this!

 

I have tested the code, but it's behaving very slowly.  

 

What do you mean by "you should defined this.c.y first and then this.c.x"?

 

 

Like this?

 

function moveF(e){
if( (stage.mouseX-cx)*(stage.mouseX-cx)+(stage.mouseY-cy)*(stage.mouseY-cy) < r*r+tol && (stage.mouseX-cx)*(stage.mouseX-cx)+(stage.mouseY-cy)*(stage.mouseY-cy) > r*r-tol ){
var prev = this.c.x;
this.c.x = Math.min(stage.mouseX,cx+r);
this.c.x = Math.max(stage.mouseX,cx-r);
var sqrt = Math.sqrt(r*r-(this.c.x-cx)*(this.c.x-cx));
if(sqrt){
if(stage.mouseX<=cx){
this.c.x = cx-sqrt;
} else {
this.c.x = cx+sqrt;
}
} else {
this.c.y = prev;
}
}
}

Likes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Engaged ,
Mar 18, 2022 Mar 18, 2022

Copy link to clipboard

Copied

@kglad   I really appreciate your help @kglad 

 

The problem with the code is that it's working really slow and quite clunky, sorry to say!  I don't know why.  

 

So, I had a look for create.js/easel.js code to do similar and found this:

 

https://stackoverflow.com/questions/38832698/rotating-one-object-around-another-in-createjs-easeljs

 

It not drag, but I adapted it a bit:

var angle = 270;

root.streakRotatorKnob.addEventListener("pressmove",moveF.bind(this));

function moveF(evt){
	var item = evt.currentTarget;
	item.drag = true;
	if (item.drag) {
  angle++;
  if(angle > 360)
  	angle = 1;
    
    var rads = angle * Math.PI / 180;
    var x = 80 * Math.cos(rads);
    var y = 80 * Math.sin(rads);
    item.x = x + 454;
    item.y = y + 175;
    
   stage.update();
  }
}

 

It works to a point and is reasonably smooth, but a bit slow and lacks fidelity/responsiveness. 

 

The main problem apart from slowness/fidelity/responsiveness, is the rotating object needs to only move when the cursor is over the object.  As you can see in the video below, the object moves even when the cursor is a distance away from the object.

 

 

 

Likes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Engaged ,
Mar 18, 2022 Mar 18, 2022

Copy link to clipboard

Copied

Also, the rotating object needs to be able to move anti-clockwise around the circle.  Currently it will only go clockwise.

 

Likes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Engaged ,
Mar 19, 2022 Mar 19, 2022

Copy link to clipboard

Copied

I meant both directions around the circle...

 

Likes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Adobe Community Professional ,
Mar 19, 2022 Mar 19, 2022

Copy link to clipboard

Copied

if you don't care where the mouse is located, as long as it starts over the drag object, use:

 

var ctrX = 300;
var ctrY = 250;
var radius = 150;


this.c.addEventListener("pressmove",moveF.bind(this));

 

function moveF(e){
var rads = Math.atan2(stage.mouseY-ctrY,stage.mouseX-ctrX);
e.currentTarget.x = ctrX + radius * Math.cos(rads);
e.currentTarget.y = ctrY + radius * Math.sin(rads);
stage.update();
}

Likes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Engaged ,
Mar 19, 2022 Mar 19, 2022

Copy link to clipboard

Copied

@kglad   Thanks again! This is helping me to understand this quite a bit.   I do want the object to move ONLY when the cursor is over that object.   What would the code look like to do that?  

Likes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Engaged ,
Mar 19, 2022 Mar 19, 2022

Copy link to clipboard

Copied

@kglad   Also, the code works MUCH better now, very smooth and responsive!

 

Apart from needing to be moveable only when the cursor is over the object, streakRotatorKnob (replacing 'c'), the object jumps on pressmove to an angle on the circumference of the circle. 

 

Instead, I want it to just be moveable from its original position. 

 

Note knob_X and knob_Y and the radius variable place the knob in the correct position to rotate around the compass object. 

 

See the video below:

 

var knob_X = 454;
var knob_Y = 175;
var radius = 80;

this.streakRotatorKnob.addEventListener("pressmove",moveF.bind(this));

function moveF(e){
var rads = Math.atan2(stage.mouseY-knob_Y,stage.mouseX-knob_X);
e.currentTarget.x = knob_X + radius * Math.cos(rads);
e.currentTarget.y = knob_Y + radius * Math.sin(rads);
stage.update();
}

 

Likes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Engaged ,
Mar 19, 2022 Mar 19, 2022

Copy link to clipboard

Copied

The other problem is that the knob moves more around the circle as the cursor moves away from the knob, and moves less when the cursor  is closer to the knob.  The ideal is for the kob to move a constant amount only when the cursor is on the knob, e.g. like a proper drag.

Likes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Engaged ,
Mar 19, 2022 Mar 19, 2022

Copy link to clipboard

Copied

The knob rotates around a compass widget which controls the rotation of the light streak on the eye.  The knob starting location on the compass widget is at 90 degrees as indicated.

 

2022-03-20_14-00-40.jpg

 

However, the image below shows the knob position around the circle immediately after the knob is clicked.  

 

2022-03-20_13-56-51.jpg

 

The knob needs to start from the 90 degree rotation mark, so that it is relative to the light streak on the eye for rotation.

 

 

The code so far:

//Rotate streakRotatorKnob

var knob_X = 454;
var knob_Y = 169;
var radius = 80;
var streakAngle;

root.streakRotatorKnob.addEventListener("pressmove", moveF.bind(this));

function moveF(e) {
	var rads = Math.atan2(stage.mouseY - knob_Y, stage.mouseX - knob_X);
	e.currentTarget.x = knob_X + radius * Math.cos(rads);
	e.currentTarget.y = knob_Y + radius * Math.sin(rads);
	stage.update();
	streakAngle = rads * (180 / Math.PI) + 180;
	//console.log(rads);
	root.streakMainRight.rotation = streakAngle;
	//console.log(root.streakMainRight.rotation);
}

 

I can sort of compensate for the position of the knob by using:

 

	e.currentTarget.x = knob_X + radius * Math.cos(rads -1.35);
	e.currentTarget.y = knob_Y + radius * Math.sin(rads -1.35);

 which positions the knob above the 90 degree mark. But then I need to compensate for the light streak, I haven't worked that out, and this isn't the right way to do it, is it?

Likes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Engaged ,
Mar 19, 2022 Mar 19, 2022

Copy link to clipboard

Copied

OK, using the rads fudge factor works. 

 

The main issue now is that the knob should move only when the cursor is on the knob.  At the moment, it gets difficult moving the knob around the compass circle, as it requires moving the mouse cursor some distance away from the knob to get it to move adequatly - sort of an elastic band effect.  You can see this in the video below:

 

Likes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Engaged ,
Mar 19, 2022 Mar 19, 2022

Copy link to clipboard

Copied

Code:

 

var knob_X = 454;
var knob_Y = 169;
var radius = 80;
var streakAngle;

root.streakRotatorKnob.addEventListener("pressmove", moveF.bind(this));

function moveF(e) {
	var rads = Math.atan2(stage.mouseY - knob_Y, stage.mouseX - knob_X);
	e.currentTarget.x = knob_X + radius * Math.cos(rads -1.35);
	e.currentTarget.y = knob_Y + radius * Math.sin(rads -1.35);
	stage.update();
	streakAngle = (rads + 0.22)* 180 / Math.PI;
	root.streakMainRight.rotation = streakAngle;
}

Likes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Engaged ,
Mar 19, 2022 Mar 19, 2022

Copy link to clipboard

Copied

Actually that rads fudge is not going to work.  Everytime I click the knob, it goes anti-clockwise by some incremental amount the further it is from the 90 degree mark...  Any ideas how I shoul be setting the startng point at the 90 degree mark on the compass symbol?  That is, the original position on stage??

Likes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Adobe Community Professional ,
Mar 20, 2022 Mar 20, 2022

Copy link to clipboard

Copied

that's too many messages to extract what you want.  i read the first two.

 

here's the code to drag only when the cursor is over the object:

 

stage.enableMouseOver(10);
var ctrX = 300;
var ctrY = 250;
var radius = 150;
var move = moveF.bind(this);
this.c.addEventListener("mouseover",overF.bind(this));   // if you don't want it to be moveable after the first drag, don't call overF to add the pressmove event.  just add it here.
this.c.addEventListener("mouseout",outF.bind(this));

function overF(){
this.c.addEventListener("pressmove",move);
}
function outF(){
this.c.removeEventListener("pressmove",move);
}

function moveF(evt){
var item = evt.currentTarget;

var rads = Math.atan2(stage.mouseY-ctrY,stage.mouseX-ctrX);
item.x = ctrX + radius * Math.cos(rads);
item.y = ctrY + radius * Math.sin(rads);
stage.update();
}

Likes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Engaged ,
Mar 20, 2022 Mar 20, 2022

Copy link to clipboard

Copied

@kglad   Thanks again. 

 

Sorry about the multiple posts, I was testing and found issues that I nneded to add to the thread.  It would of course be better if I could just edit my posts...

 

The new code has a problem with user interaction.  As the object is only moveable when the cursor is over the object, there is struggle to keep the object moving and maintain the position of the cursor over the object.  I was hoping for functionality mimiking drag, but this not user friendly, sorry to say.

 

I am wondering now if there is a different approach based on a tween perhaps where the user can control the movement intuitively of the object around the circle. 

 

I am surprised at the difficulty of all of this with what should be a simple and commonly required functionality - user controlling the movement of an object along a path.

 

Years ago I used Macromedia Director to move a bead along (backwards and forwards) a wavy line - a sort of timeline interaction.  Not at all uncommon, but apparently difficult in Animate.

Likes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Engaged ,
Mar 20, 2022 Mar 20, 2022

Copy link to clipboard

Copied

Here is a video of the problem with the new code.  Also apart from the user interaction problem, the object 'c'  won't go around the full circle.

 

Likes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Engaged ,
Mar 20, 2022 Mar 20, 2022

Copy link to clipboard

Copied

@kglad  I have changed your code a bit and disabled the line for mouseout.  This works very responsively and the mouseout disabling doesn't present a problem.  I think the main issue was keeping the mouse over the object, which was probably not a good idea from me...

 

 

Code:

 

stage.enableMouseOver();
var knob_X = 454;
var knob_Y = 169;
var radius = 90;
var root = this;


root.c.addEventListener("mouseover", mouseover);
//root.c.addEventListener("mouseout", mouseout);

function mouseover(evt)
{
    root.c.addEventListener("pressmove", moveF);
}
function mouseout(evt)
{
    root.c.removeEventListener("pressmove", moveF);
}
function moveF(evt)
{
    var rads = Math.atan2(stage.mouseY - knob_Y, stage.mouseX - knob_X);
    evt.currentTarget.x = knob_X + radius * Math.cos(rads);
    evt.currentTarget.y = knob_Y + radius * Math.sin(rads);
    stage.update();
}

Likes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines