I want to achieve a conveyor belt animation on an SVG element i.e. the blocks on the conveyor belt need to move along with the belt in a particular direction.
A better view of what i want to achieve:
GIF
The SVG image has separate groups for separate blocks that need to be moved along a line (belt). The svg can be found here
I tried using jquery animate to move them at an angle like so:
$(function() {
var dist = 130;
var angle = -48;
var x = Math.cos(angle*Math.PI/180) * dist;
var y = Math.sin(angle*Math.PI/180) * dist;
// $(".st93").animate({'left': '+='+x+'px', 'top': '+='+y+'px'}, 1000);
$(".st93").animate({"transform": "translateX(+=" +x+ "px)"}, {"transform": "translateY(+=" +y+ "px)"}, 1000);
})
which didn't work.
and then i tried using CSS only transforms like so:
#Square_1 {
position: relative;
animation-name: move;
animation-duration: 2s;
animation-timing-function: linear;
animation-iteration-count: infinite;
}
#keyframes move {
0% {
opacity:0;
//transform: translateX( -400px, 10px);
}
10% {
opacity:1;
}
90% {
opacity:1;
transform: translate( 100px, -60px);
}
100% {
opacity:0;
}
}
which took me closer to what I wanted but still isn't showing the desired effect. the blocks start abruptly forming at their respective starting position instead of a continuously flowing from the start of the belt which seems far from natural.
Any help will be appreciated. Thanks.
Related
I would like to animate element on the screen by arrows. It should change the direction immediately while translation. So if element go to right and I press down arrow in half of the animation it should go straight down and stop to go right. But how can I catch current x position of the element. offsetLeft does not work. It is still the same origin position. Is it possible to catch current position of animated element? Thanks.
I think you need to call element.getBoundingClientRect()
let circle = document.querySelector(".animate");
let style = window.getComputedStyle(circle);
setInterval(() => {
let rect = circle.getBoundingClientRect();
console.log(rect.left)
}, 1000)
div {
height: 100px;
width: 100px;
border-radius: 100px;
background: blue;
}
.animate {
animation: animate;
animation-duration: 3s;
animation-direction: alternate;
animation-iteration-count: infinite;
animation-timing-function: linear;
}
#keyframes animate {
from {
transform: translate(0)
}
to {
transform: translate(calc(100vw - 120px))
}
}
<div class="animate"> </div>
Not sure why code snippet renders the entire element in console.log, but in an actual script it would return only the value.
I have css detailing what I want the picture to do (I want it to basically fall down when it gets created)
.pimg{
width: 100px;
height: 100px;
position: absolute;
animation-name: fall;
animation-duration: 4s;
animation-delay: 0s;
animation-iteration-count: infinite;
}
#keyframes fall {
0% {top:0px; transform: rotate(0deg)}
100% {top:800px; transform: rotate(360deg)}
}
I also have javascript/jquery that creates the image
function PIMG()
{
var img = $('<img id="img">');
img.attr('src', "Doggos/puppy.png");
img.attr('class', 'pimg');
img.appendTo('#PIC');
}
I was wondering how I could make it so it takes all of the x value points inside of the div and then spawn the picture randomly inside that div along that value? If possible I'd love for it to be in css but I don't know if that's even possible.
Reworded: Right now my image just gets created in the same spot. I was wondering how to make it in a random spot along the left-right axis but still be inside a specific div.
Thank you.
To move it randomly along the x-axis inside the div elememt, you can be ramdomly changing the margin. just add this line to your PIMG function
img.css("margin-left", Math.random() * 100 + "%");
so your function should now look like this:
function PIMG()
{
var img = $('<img id="img">');
img.attr('src', "Doggos/puppy.png");
img.attr('class', 'pimg');
img.appendTo('#PIC');
img.css("margin-left", Math.random() * 100 + "%");
}
JS Fiddle demo: https://jsfiddle.net/a7rk9vx4/1/
The Idea is to randomly set the left css property of the img to a random number between 0 to the box's width.
I have an introductory portion of a site where 4 letters (SVGS) pop onto the screen. Most of the time, it plays just fine. On occasion however, sometimes one or two or all the images won't animate in at all. I'm not sure what could be causing this (it's not the cache), and a page refresh usually fixes it. Am I missing something? Should I wait for the images to load AND for the entire DOM to be ready?
Here is the relevant CSS (Sass).
Animation:
#keyframes bobble {
0% {
transform: translateY(124px) scale(0.8, 1.6);
}
25% {
transform: translateY(-64px) scale(1.6, 0.8);
}
55% {
transform: translateY(16px) scale(0.9, 1.1);
}
100% {
transform: translateY(0) scale(1);
opacity: 1;
}
}
Styling
.hello-header-img {
height: 100%;
width: 100%;
opacity: 0;
animation: bobble $animation-duration cubic-bezier(0.64, 0.57, 0.67, 1.53);
animation-fill-mode: forwards;
animation-play-state: paused;
will-change: transform, opacity;
// Plays animations when images have loaded (JS)
.is-ready & {
animation-play-state: running;
}
}
Each letter also has an animation delay which starts at 0.4s and increases by 0.3s for each letter (so letter 1 = 0.4s delay, letter 2 = 0.7s delay, letter 3 = 1s delay, etc).
Javascript
const imgs = document.querySelectorAll('.hello-header img');
let counter = 0;
let hasScrolled = false;
// Animate after hello section images have loaded
[].forEach.call( imgs, function( img ) {
img.addEventListener( 'load', ()=> {
counter++;
if ( counter === imgs.length ) {
document.querySelectorAll('.js-hello-header')[0].classList.add('is-ready');
}
}, false );
});
Try replacing translate and scale with translate3d and scale3d (with the appropriate parameters).
translate and scale in general are very CPU expensive while their 3d counterparts utilize hardware acceleration from the graphics card and therefore play animations much smoother.
I have an idea in mind, and want some perspectives on what would make sense for the best implementation. The premise is basically slow moving objects ricocheting around inside an enclosure. Think like the game 'asteroids' but without a spaceship (and colliding with the walls instead of passing through).
Because this is to be in the background and purely aesthetic, I figure it's got to be pretty lightweight. I would use all CSS, but my question is can multiple animations be applied to an object? Say if I have a square bouncing around in a box using
---------
.square {
animation: moveX 2.05s linear 0s infinite alternate, moveY 2.4s linear 0s infinite
#keyframes moveX {
from { left: 0; } to { left: 480px; }
}
#keyframes moveY {
from { top: 0; } to { top: 280px; }
}
}
How can I get it to rotate continuously as well? Or at least create some effect that does so? If I need to put something together with javascript then that's fine, just curious whether I'm overlooking something with the CSS.
You can add rotation to the element in CSS:
.square {
position: relative; /* Ensure it's movable with non static position */
animation:
moveX 2.05s linear 0s infinite alternate,
moveY 2.4s linear 0s infinite,
rotate 2s linear infinite;
}
#keyframes moveX {
from { left: 0; } to { left: 480px; }
}
#keyframes moveY {
from { top: 0; } to { top: 280px; }
}
#keyframes rotate {
0% {transform: rotate(0deg);} 100% {transform: rotate(359deg);}
}
Use -359deg to rotate counterclockwise.
I have searched through a lot of questions related to my question in stackoverflow but i haven't found one yet that answers my question with plain JavaScript (not using libraries of any kind).
My problem is that I have an infinite animation with CSS3 i.e.:
.clockwiseAnimation {
top: 270px;
left: 200px;
position: absolute;
-webkit-animation: clockwise 4s linear infinite; /* Chrome, Safari 5 */
-moz-animation: clockwise 4s linear infinite; /* Firefox 5-15 */
-o-animation: clockwise 4s linear infinite; /* Opera 12+ */
animation: clockwise 4s linear infinite; /* Chrome, Firefox 16+, IE 10+, Safari 5 */
}
#-webkit-keyframes clockwise {
from { -webkit-transform: rotate(0deg) translateX(150px) rotate(0deg); }
to { -webkit-transform: rotate(360deg) translateX(150px) rotate(-360deg); }
}
#-moz-keyframes clockwise {
from { -moz-transform: rotate(0deg) translateX(150px) rotate(0deg); }
to { -moz-transform: rotate(360deg) translateX(150px) rotate(-360deg); }
}
#-o-keyframes clockwise {
from { -o-transform: rotate(0deg) translateX(150px) rotate(0deg); }
to { -o-transform: rotate(360deg) translateX(150px) rotate(-360deg); }
}
#keyframes clockwise {
from { transform: rotate(0deg) translateX(150px) rotate(0deg); }
to { transform: rotate(360deg) translateX(150px) rotate(-360deg); }
}
This animation allows me to spin (clockwise) whatever tag that has the class "clockwiseAnimation".
What I want to do is to change the time of execution (I'll call it speed) of the animation with javascript like:
HTML:
<span id="someID" class="clockwiseAnimation">sometext</span>
JavaScript:
var style = document.getElementById("someID").style,
speed = 6;
//obviously the speed is dynamic within my site (through an `<input type="range">`)
//for the purposes of this example I set the speed to a different value(6seconds) than the original value(4seconds).
style.webkitAnimationDuration = style.mozAnimationDuration = style.oAnimationDuration = style.animationDuration = speed + "s";
It works when I pause and then play(by play I mean UNPAUSE not restart) the animation, i.e.:
var style = document.getElementById("someID").style;
some = 6; //it is dynamic (as I pointed out before)
//pause
style.webkitAnimationPlayState = style.mozAnimationPlayState = style.oAnimationPlayState = style.animationPlayState = "paused";
//change speed
style.webkitAnimationDuration = style.mozAnimationDuration = style.oAnimationDuration = style.animationDuration = speed + "s";
//play (== UNPAUSE) //UPDATE: Added the timeout because I can't get it to work any other way.
setTimeout(function(){
style.webkitAnimationPlayState = style.mozAnimationPlayState = style.oAnimationPlayState = style.animationPlayState = "running";
},1);
UPDATED:
And it works! BUT, it has a big RANDOM jump in the animation, meaning that when I change the "speed" with the "<input type="range"> slider" the element jumps to a random location (not the beginning nor the end of the animation just a random location).
NOTE: Pause and play works very smooth without changing the "speed" of the animation.
My question(s): Can I change the "speed" of the animation smoothly WITH JavaScript? (WITHOUT the jumping)
If the answer is: "There is not a way to do it smoothly throughout the animation execution", then:
Is there a way to change it in the next iteration of the infinite animation?
If so:
Then how can I tell it to start in the next iteration and how to know which is the next iteration if I set the animation to infinite (animation-iteration-count property of the element that is doing the animation always returns "infinite").
Here is an example. I hope it helps.
What may be occurring is that the animation-duration "change" could be "jumping" to the point in the animation corresponding to the "changed" #keyframes - based on the total "changed" animation duration..
If the animation-duration began from (or 0%) proceeded to to (or 100%), the corresponding #keyframes "position" may be changed as well.
For example if the original animation-duration was 4s (or, 4000ms) at approximately 2s (or, 2000ms), the corresponding keyframes may be at approximately 50%, or
at 2 seconds into 4 second animation
50% { -webkit-transform: rotate(180deg) translateX(150px) rotate(-180deg); }
when the animation-duration is dynamically changed, the corresponding keyframes may be "changed" to the matching % point, or, a larger duration span for the same effect. The animated element may appear to go forwards or backwards, or hve a "jumping" due to it re-positioning itself within the "changed" corresponding keyframes and animations.
There is also 1s setTimeout function, that may or may not actually have a 1s duration.
It may be possible to "smoothly" "jump" to the newly "changed" position within the lengthier animation-duration the suggested transition effect or requestAnimationFrame (http://www.w3.org/TR/animation-timing/).
..
Try this:
html
<input type="range" id="speedSlider" min="2000" max="6000" value="4000">
css
input {
-webkit-transform: rotate(180deg);
top : 50px;
position : absolute;
}
.clockwiseAnimation {
/* top: 270px;
left: 200px; */
left : 50%;
top : 50%;
position:absolute;
/* css animation (no change) */
}
js
var speedSlider = document.getElementById("speedSlider");
speedSlider.addEventListener("change", changeSpeed, false);
function changeSpeed(e){
var speed = Math.floor(speedSlider.value);
var element = document.getElementById("span");
var style = element.style;
style.webkitAnimationPlayState = style.mozAnimationPlayState = style.oAnimationPlayState = style.animationPlayState = "paused";
style.webkitAnimationDuration = style.mozAnimationDuration = style.oAnimationDuration = style.animationDuration = String(speed) + "ms";
style.webkitAnimationPlayState = style.mozAnimationPlayState = style.oAnimationPlayState = style.animationPlayState = "running";
}
With CSS: http://jsbin.com/UsunIMa/1/
CSS properties transition and animation allow you to pick the easing function.
div {
transition: all 600ms cubic-bezier(0.77, 0, 0.175, 1);
/* or */
animation: clockwise 4s cubic-bezier(0.77, 0, 0.175, 1) infinite;
}
use setTimeout to add animation class to your required element with the removal of animation class as a callback.
Maybe jQuery queue could help you.
Here it is