I'd like my bitmap to go to a click position but I want to see a progression between the bitmap.x/bitmap.y and the click.x/click.y
How can I make this animation ?
Thanks a lot
You can create a tween using TweenJS when the stage is clicked:
stage.on("stagemousedown", function(event) {
// Tween to the new position. Override old tweens on the same object.
createjs.Tween.get(bitmapInstance, {override:true}).to({x:event.stageX, y:event.stageY}, 500, createjs.Ease.quadIn);
})
Here is a quick fiddle: http://jsfiddle.net/jemohtgh/
Or you can store the clicked position, and basically have the shape always try to reach that position (fiddle):
var pos = new createjs.Point();
stage.on("stagemousedown", function(event) {
pos.setValues(event.stageX, event.stageY);
})
function tick(event) {
// Move towards the position
s.x += (pos.x - s.x) / 2;
s.y += (pos.y - s.y) / 2;
stage.update(event);
}
You can also do the same thing with a mouse follow instead of a click (fiddle):
function tick(event) {
s.x += (stage.mouseX - s.x) / 5;
s.y += (stage.mouseY - s.y) / 5;
stage.update(event);
}
Cheers.
Related
I have two DIV's of different widths on top of each other. The top DIV displayDIV is wider than the bottom DIV captureDIV.
In the displayDIV I'm drawing a dot who's X position is proportionate to the mouse position within captureDIV.
As you move the mouse in captureDIV the dot moves proportionately in DisplayDIV.
It makes much more sense if you look at this fiddle
My code is as follows...
let capture = document.getElementById('captureDIV');
let display = document.getElementById('displayDIV');
let circle = document.getElementById('circle');
capture.addEventListener('mousemove', handleMouseMove);
function handleMouseMove(event) {
const captureRect = capture.getBoundingClientRect();
const captureWidth = captureRect.right - captureRect.left;
const relativeX = event.x - captureRect.left;
let percent = (relativeX / captureWidth) * 100;
let roundedPercent = parseFloat(Math.round(percent * 100) / 100).toFixed(2);
moveDotTo(roundedPercent);
}
function moveDotTo(percentage) {
const displayRect = display.getBoundingClientRect();
const displayWidth = displayRect.right - displayRect.left;
const circleX = displayRect.left + displayWidth * (percentage / 100);
const circleY = displayRect.top + (displayRect.height / 2);
const style = `top:${circleY}px;left:${circleX}px;`;
circle.setAttribute('style', style);
}
I also have a number of buttons that can set the position of the dot within DisplayDIV such as...
let move20 = document.getElementById('move20');
move20.addEventListener('click', function(event) {
moveDotTo(20);
});
Using Vanilla JS not CSS tricks, how can I create a function to animate (rather than move) the dot from its existing position to the new position.
function animateDotTo(percentage) {
// clever code here
}
I need to be able to call the animateDotTo(percentage) function from either a button or from the mousemove event handler.
The dot should always animate to its new position regardless of how the move is triggered. For instance if the mouse is moved out of the left side of the captureDIV round the bottom and then into the right side of the captureDIV the dot should animate across the DisplayDIV not jump as it does now. Equally pressing one of the move to x% buttons should animate the dot from its current position to the new one.
If you are drawing a circle and moving it around, I would suggest drawing to a <canvas> element instead of moving a <div> by setting its top and left properties. Even using transform: translate(x, y) might be better.
In order to smoothly transition your dot from one location to another, using JavaScript, you will want:
The dot's current position as x and y coordinates,
The dot's target position as x and y coordinates, and
The speed at which the dot moves as a scalar.
Updating the current position is done at every animation frame with window.requestAnimationFrame. With these in hand, and a way of applying the resulting calculated position to the dot, you can use a method like this one: How to move an object using X and Y coordinates in JavaScript to move your dot (the example moves a canvas, but if you know the x and y, then you can set them to top and bottom).
Answering my own question, with thanks to Billy Brown for pointing me in the right direction. Using window.requestAnimationFrame is the way to go.
var currentPercentage;
var startPercentage;
var targetPercentage;
function animateDotTo(percentage) {
targetPercentage = percentage;
startPercentage = currentPercentage;
window.requestAnimationFrame(step);
}
function step(timestamp) {
var fps = 7;
var maxStep = 30;
var distStartToTarget = Math.abs(startPercentage - targetPercentage);
var stepSize = Math.min(distStartToTarget / fps, maxStep);
if (targetPercentage < startPercentage) {
currentPercentage -= stepSize,0;
if (currentPercentage > targetPercentage) {
window.requestAnimationFrame(step);
}
} else if (targetPercentage > startPercentage) {
currentPercentage += stepSize,100;
if (currentPercentage < targetPercentage) {
window.requestAnimationFrame(step);
}
} else {
return;
}
if (currentPercentage > 100 ) { currentPercentage = 100; }
if (currentPercentage < 0 ) { currentPercentage = 0; }
moveDotTo(currentPercentage);
}
Updated fiddle
A simple trick in css transition will fix this.
Of course. You don't want it to animate when you're actually moving the mouse. So what I did is that I separate the transition css property on another class and then remove that class on mouse move, re-attaching it when we click the move buttons.
CSS
#circle {
position: absolute;
left: -100px;
top: -100px;
width: 10px;
height: 10px;
border-radius: 50%;
background-color: #000;
transition: none;
}
#circle.animate{
transition: 500ms ease;
}
JS
move20.addEventListener('click', function(event) {
moveDotTo(20); animateDotTo();
});
move60.addEventListener('click', function(event) {
moveDotTo(60);animateDotTo();
});
move80.addEventListener('click', function(event) {
moveDotTo(80);animateDotTo();
});
function moveDotTo(percentage) {
circle.classList.remove("animate");
const displayRect = display.getBoundingClientRect();
const displayWidth = displayRect.right - displayRect.left;
const circleX = displayRect.left + displayWidth * (percentage / 100);
const circleY = displayRect.top + (displayRect.height / 2);
const style = `top:${circleY}px;left:${circleX}px;`;
circle.setAttribute('style', style);
}
function animateDotTo(percentage) {
circle.classList.add("animate");
}
http://jsfiddle.net/8pm2grjd/
If you want it to animate even if you're triggering the movement using mousemove, you can disregard the class approach and just slap the transition property on the css. But this will simulate the annoying mouse delay effect similar to input delay on video games due to V-Sync.
This is a follow-on from this question: Animation based on scroll position
The goal is to loop through each element, and change it's rotation and perspective based on the users scroll position. I guess from an organic UX viewpoint, you'd want the top of the browser window to 'squash' the topmost item, and smoothy flip the element down.
Here's a screenshot for guidance:
Here is a Fiddle: https://jsfiddle.net/nfquerido/0zpc2a76/
And the loop function:
var _items = function () {
forEach(items, function (item) {
var scrollTop = _scrollTop(),
elementTop = item.offsetTop,
documentHeight = _getDocumentHeight(),
// Transform the item based on scroll
rotationFactor = Math.max(0, scrollTop - elementTop),
perspectiveFactor = Math.max(0, scrollTop - elementTop),
rotation = (rotationFactor / (documentHeight - windowHeight) * 90),
perspective = (perspectiveFactor / (documentHeight - windowHeight) * 2000),
transform = 'perspective(' + perspective + ') rotateX(' + rotation + 'deg)';
// Elements off the top edge.
if(scrollTop > elementTop) {
item.classList.add('scrolling');
item.style.webkitTransform = transform;
} else {
item.classList.remove('scrolling');
item.style.webkitTransform = null; // Reset the transform
}
});
};
I updated your fiddle: https://jsfiddle.net/0zpc2a76/1/
If I understand your question correctly, I think you are trying to get the blue boxes to "fold over" as if they are being pushed down by the top of the viewport. For that, your calculations seem to be wrong, so I updated some of the variable assignments:
rotation = (rotationFactor / (item.offsetHeight) * 90),
perspective = 2000 - (perspectiveFactor / (item.offsetHeight) * 2000),
I created a sprite which moves in a circular motion. I want to change the direction if the mouse button (touch) is clicked, but when the mouse is clicked, the direction does not change.
This is my code:
create: function() {
this.stage.backgroundColor = '#FFFFFF';
x = this.world.centerX;
y = this.world.centerY;
this.direction = 1;
this.speedDelta = 0.002;
this.radius = 114;
this.physics.startSystem(Phaser.Physics.ARCADE);
//adding player
this.player = this.add.sprite(x, y, 'player');
this.player.anchor.setTo(0.5, 0.5);
this.game.physics.arcade.enable(this.player);
this.input.onDown.add(this.changeDirection, this);
},
update: function() {
if (this.direction == 1) {
this.speedDelta = 0.002;
} else if (this.direction == 1) {
this.speedDelta = -0.002;
}
var period = this.time.now * this.speedDelta;
this.player.x = Math.cos(period) * this.radius;
this.player.y = d + Math.sin(period) * this.radius;
},
changeDirection: function() {
this.direction = -this.direction;
}
}
Your basic assumptions about the behavior of cos and sin are incorrect. You can't simply change the sign of the input and get a different answer.
Notice:
cos(pi/4) = 0.707
cos(-pi/4) = 0.707
sin(pi/4) = -0.707
sin(-pi/4) = -0.707
Also I think your code would benefit by using a slightly different approach in general.
Currently you're recalculating the position from scratch on every update cycle. To get the behavior you want, I think it would be simpler to instead calculate a location delta based off of the speed and direction, then simply add the delta to the current location.
That would also allow you to eliminate your conditional statement, which will make the code cleaner.
i have a simple jQ script:
a set width/height container
a landscape img (can be bigger or
smaller than container)
when a user mouses over the image, it pans
(no click/drag) until it reaches the end
The equation to move the img to the left is this:
-1(relative mouse-position)*(img width)/(container width)
This works fine, but it leaves a space one the mouse reaches the end of the img.
Fiddle
$("figure img").mousemove( function (e) {
var a = $(this).closest("figure"),
b = $(this).width(),
c = a.width(),
d = (e.clientX - a.offset().left);
$(this).css({
left: -1*(d*b/c)
}, 100);
});
can someone help? I want the img to be completely aligned to the right of the container once the mouse reaches the end.
The correct formula is: -1 * (d/c) * (b - c)
Or, more clearly: -1 * (mouseX / figureWidth) * (imgWidth - figureWidth)
(mouseX / figureWidth) represents the percent of the width of the figure that the mouse is positioned at. It will be a number between 0 and 1.
(imgWidth - figureWidth) represents the biggest X value you want to use to position the image at the opposite side.
Multiplying the percent by the total range of movement gives you the movement amount for the current mouse position!
Updated Fiddle
I suggest using more descriptive variable names such as figureWidth, imgWidth, mouseX etc. Not only will it be easier for you to understand, but it will be easier for people to answer.
This should work: http://jsfiddle.net/0zd5t1wf/4/
i just get the limit value for the left propriety of image (the image width - the figure box)
$("figure img").each( function () {
if($(this).width() >= ($(this).height() * 2.5)) {
$(this)
.attr("class", "panorama")
.mousemove( function (e) {
var a = $(this).closest("figure"),
b = $(this).width(),
c = a.width(),
d = (e.clientX - a.offset().left),
newLeft = -1*(d*b/c),
limitValue = parseInt($(this).width()) - parseInt($("figure").width());
if ( newLeft < 0 && (newLeft *-1) < limitValue ){
$(this).css({
left: newLeft
}, 100);
}
$("#hello").html('why');
});
}
});
I am trying to animate shape continue from from X to Y distance, again return shape from Y to X using kinetic js animate function. eg. move shape from 0px to 200px and again return shape 200px to 0px.
thanks.
You are probably looking for a Tween here rather then an Animation. Check out the kinetic documentation for more information on Tweens, however what you are looking to do will probably look something like this:
var tween = new Kinetic.Tween({
node: myShape,
x: moveToX,
y: moveToY,
duration: 1
});
Now that you have a tween, you can play it, rewind it, pause it, reverse it (again, check out the documentation for all up to date information on Tweens).
So you can now do:
tween.play()
or
tween.reverse()
to accomplish what you are looking for.
Reference: http://www.html5canvastutorials.com/kineticjs/html5-canvas-stop-and-resume-transitions-with-kineticjs/
Update (as per comment below): If you want a looping affect, in an X direction, Y direction, or both. You can do something like:
var yPos = myShape.getAttr('y'),
xPos = myShape.getAttr('x'),
maxX = 1000,
maxY = 1000,
yIncreasing = true,
xIncreasing = true; //lets assume myShape resides somewhere below the max
var anim = new Kinetic.Animation(function(frame) {
/* move the shape back and fourth in a y direction */
if (yPos < maxY && yIncreasing) {
hexagon.setY(yPos++);
} else {
if (yPos < 1) {
yIncreasing = true;
hexagon.setY(yPos++);
} else {
hexagon.setY(yPos--);
yIncreasing = false;
}
}
/* move the shape back and fourth in a x direction */
if (xPos < maxX && xIncreasing) {
hexagon.setX(xPos++);
} else {
if (xPos < 1) {
xIncreasing = true;
hexagon.setX(xPos++);
} else {
hexagon.setX(xPos--);
xIncreasing = false;
}
}
}, layer);
Note: I haven't ran this code, it should work. Using both will cause the shape to move diagonally, but hopefully this snipplet shows a solution to your problem.