Force Feeding not working in Velocity JS - javascript

I am trying to use VelocityJS in one of my React projects. The use case where I am facing the problem is:
There is pointer created in SVG, initially at the center of the screen. I want to move the pointer with the keyboard arrow keys. I have maintained a state variable for updating the X and Y values of the pointer on keydown event. On the callback of setState, I am calling a translate function which animates the translation. But the problem I faced is that The animation always happened from the initial position of the pointer i.e. center of the screen. So as a workaround I tried was that I maintained the previous position of the pointer in state too, using forcefeeding in velocityJS. Someone go through my code and see if I am doing something wrong.
$(".Aim").velocity(
{
translateX: [this.state.aimX, this.state.aimXOld],
translateY: [this.state.aimY, this.state.aimYOld]
},
{
duration: 500,
easing: [0.46, 0.46, 0.46, 0.46],
complete: () => {
console.log("completed");
}
}
);

Related

Rotating cirle anime js

I'm trying to let a cricle spin and on mouseenter I want the circle to stop spinning and rotate "x" degree, on mouseleave the circle should spin back to its origin and continue the spinning animation.
function rotatingCircle(degree) {
var test =
anime({
targets: [document.getElementsByTagName("svg")[0]],
rotate: degree,
duration: 800,
loop: true,
elasticity: 0,
easing: "linear"
});
};
rotatingCircle(360);
var buttonEl = document.querySelector('.trigger');
var circleOne = document.getElementsByTagName("svg");
buttonEl.addEventListener('mouseenter', rotatingCircle(20));
buttonEl.addEventListener('mouseleave', rotatingCircle(0));
Add the moment my svg is not rotating at all. When I remove the 'mouseenter' and 'mouseleave' event, then my svg is rotating as wanted. How do I keep a rotating loop animation AND can add a 'mouseenter' / 'mouseleave' event, which triggers the rotating SVG to rotate to a specifig angle?
One problem I see with your code is that
buttonEl.addEventListener('mouseenter', rotatingCircle(20));
buttonEl.addEventListener('mouseleave', rotatingCircle(0));
are actually calling the function rotatingCircle where as you want to send a function name or anonymous function here instead.
Function name example if these were parameterless functions
buttonEl.addEventListener('mouseenter', rotatingCircle);
buttonEl.addEventListener('mouseleave', rotatingCircle);
Anonymous function example when you need to send parameters (use this one)
buttonEl.addEventListener('mouseenter', () => rotatingCircle(20));
buttonEl.addEventListener('mouseleave', () => rotatingCircle(20));
How to think about it with an example:
listeners just need the reference to what to call when they are triggered, they don't need what the function returns from calling
I made a code sandbox of what I think you are talking about. Check it out here: https://codesandbox.io/s/aninejs-different-animations-for-different-hover-states-ld76r

Velocity.js - Buggy looping animation?

I have been testing a theory design for an animated mouse to indicate that the user of a website can scroll downwards. It's not complicated, and I've come up with a design which should be re-usable...
However for some reason if I try to clone the element and append it, it no longer get animated visually? However if I $.click() with jQuery, it fixes after one iteration.
Perhaps this is just a browser render issue? Please let me know if you cannot replicate the problem! Cheers
jsfiddle: https://jsfiddle.net/xw39e0bs/4/
Turns out that velocity calculates the start point based on current CSS values. So if you clone a moving element mid-motion, that will become the new start point. Therefore, one way to fix this is to provide forcefeeding.
Working example:
function mouse(){
$(".mouse .ball").velocity({
top: ["45%","25%"] //[TARGET_VAL,START_VAL]
},{
duration: 800,
easing: "swing",
}).velocity("reverse",{
delay: 2000,
complete: function(){
mouse();
}
});
}
mouse();
$("#clone").click(function(){
$(".mouse").last().clone().appendTo("#mice");
});
https://jsfiddle.net/xw39e0bs/5/
In this version we're reassigning the selector to bring in the cloned items. All of the clones then animate as expected.
complete: function(){
sel = $(".mouse .ball");
mouse();
}

Mouse:over event fires twice in Fabric.js

I'm trying to write a simple card game on canvas + Fabricjs. Need to make bigger player's card when mouse is on it and return to normal size if mouse is out.
Here is my js code:
canvas.on('mouse:over', function(e) {
if(e.target.mytype && e.target.mytype=='card'){
e.target.animate({
top:352,
left: e.target.left - (max_width - min_width)/2,
scaleX:0.4,
scaleY:0.4
} , {
duration: 500,
onChange: function(value) {
canvas.renderAll.bind(canvas);
},
easing: fabric.util.ease.easeInOut
});
canvas.renderAll();
}
});
canvas.on('mouse:out', function(e) {
if(e.target.mytype && e.target.mytype=='card'){
e.target.animate({
top:385,
left: e.target.left + (max_width - min_width)/2,
scaleX:0.3,
scaleY:0.3
} , {
duration: 500,
onChange: function(value) {
canvas.renderAll.bind(canvas);
},
easing: fabric.util.ease.easeInOut
});
canvas.renderAll();
}
});
if player hover the card for 200ms (animation duration is 500ms) and move out, the animation freeze and the card remains at a new position. Hovering again wil start animation from this new position.
Here is a fiddle
Just try to move mouse in/out on the object and you'll see the bug. Please, help me to fix this.
The problem is the way that your code has relative positioning changes within the animation action - in the jsFiddle, the "top" value, in your code above, in the "left" value.
What each of these do is move the element +X or -X from the position the event starts at. If the animation finishes before the mouseout event is fired, it's fine, because the amount it moves back is equal (but opposite) to the amount it moved in the mouseover event.
However, if the animation for mouseout starts Before the first is finished, it takes it's current position, not the position it will be at when it finishes the animation. This leads to a situation where the element drifts away from its original position. This is certainly what the issue is in the JSFiddle, I understand from your comments that this is the same issue in your own code.
How to resolve it? As long as you are using a fixed relative position value in the mouseout event you probably can't. You could try logging the initial positioning (i.e., the value of "left/top" you started at) in the mouseover function and returning specifically to that point in the mouseout event.

Dragging elements

Im just wondering whether its possible to drag images/elements (whether inside a div or not) where the image/element is dragged to the far left and comes in from the right side of the screen - therefore dragging the image/element left to get the same result, or vice versa.
Similar to the google maps (on zoom level 1) the user can continuously drag the image left or right, and those images are on a continuous loop.
If so, what languages would you recommend using? javascript?
I hope this makes sense.
Many thanks
This is certainly possible using Javascript. Just have two copies of the image, and as you slide the images left, move the second copy to the right side. (Or vice versa if sliding right).
You can add event handlers to any element, including your images, that execute code while dragging. I apologize for not providing a complete working solution, I am pressed for time, I hope this helps as a starting point
var myGlobals = {
state: {
dragging: false;
}
};
$('.carouselImg').on('mousedown', function(e){
myGlobals.state.dragging = true;
});
$(window).on('mouseup', function(e){
// stop movement even if mouseup happens somewhere outside the carousel
myGlobals.state.dragging = false;
});
$(window).on('mousemove', function(e){
// allow user to drag beyond confines of the carousel
if(myGlobals.state.dragging == true){
recalculateCarouselPosition(e);
}
});
function recalculateCarouselPosition(e){
// These fun bits are left as an exercise for the reader
// the event variable `e` gives you the pixel coordinates where the mouse is
// You will have to do some math to determine what you need to do after this drag.
// You may want to store the coordinates of the initial click in
// `myGlobals.dragStart.x, .y` or similar so you can easily compare them
// You will probably set a negative CSS margin-left property on some element
// of your carousel.
// The carousel will probably have overflow:hidden.
// You will also have to manipulate the DOM, by adding a duplicate image to the
// opposite end and deleting the duplicates once they have scrolled out of view
};

Raphael JS - Start/Continue animating during mouseover. Pause animation on mouseout

Using Raphael JS, is there a way to make a circle move to the right (or any direction) during mouseover, and then pause/stop the movement when the cursor is no longer on the circle.
I've tried few different methods, but they have bugs. One of the main issues is: if the mouse cursor doesn't move after entering the circle, "mouseout" will not be triggered once the circle moves to a location where the mouse cursor is no longer over top of the circle.
You'll see what I mean in these different attempts:
1) Animate with pause / resume:
jsfiddle.net/fKKNt/
But the animation is jerky and unreliable. If you hover over the object, as the object moves outside of where the mouse cursor is, it doesn't trigger the "mouseout" listener.
2) Repositioning with mouseover & .attr("cx"):
jsfiddle.net/c4BFt/
But we want the animation to continue while the cursor is in the circle too.
3) Using setInterval (as suggested in:
An "if mouseover" or a "do while mouseover" in JavaScript/jQuery):
jsfiddle.net/9bBcm/
But "mouseout" is not called as the circle moves outside of where the cursor lies. I.e. the circle move to a location where "mouseout" should be called, but it is not called.
The same thing happens with "hover":
jsfiddle.net/STruB/
I'm sure there's a much more elegant way to do this, but off the top of my head, you could try something like this: http://jsfiddle.net/D6Ps4/2/
In case that disappears for some reason, I've included the code below. The solution simply initiates the animation, then checks to see if the mouse cursor (note the e.offsetX/e.offsetY) is within the bounding box of your Raphael Object (Element.getBBox()) at some set interval. If it is, do nothing and use setTimeout to check again in some time, if it's not, pause the animation.
var paper = Raphael("holder");
var animObject = Raphael.animation({cx: 400}, 5000);
circle = paper.circle(90, 90, 45).attr({fill: "#0E4"});
var timer;
circle.mouseover(function(e) {
var anim = function(shouldAnim) {
if (shouldAnim) {
circle.animate(animObject);
}
if (!mouseInsideCircle(e, circle)) {
circle.pause();
return;
} else {
timer = setTimeout(function() {anim(false)}, 20);
}
}
anim(true);
});
circle.mouseout(function() {
this.pause();
clearTimeout(timer);
});
var mouseInsideCircle = function(e, c) {
var bb = c.getBBox();
if (e.offsetX > bb.x && e.offsetY > bb.y) {
return true;
}
return false;
}
I'm sure the solution is flawed (it's checking the boundBox, not the circle itself; it also assumes the circle is moving right) and perhaps not ideal, but it seems to work reasonably smoothly and hopefully gets you on the right path.

Categories