Hi there,
I haven’t been here since a looong time ! Glad to see it’s still a vibrant community, congrats !
For a project i’m working on, i’m trying to build a filterable system of randomly moving div. I must say that my javascript skills are quite basic, i mostly use common jQuery stuff.
Anyway, I managed to build up something using jQuery and the animate function but it seems quite heavy on CPU and memory consumption over the time : http://www.artefakt.be/dev/RandomDivMove_update.html
As i was looking for a lighter approach, i found this post on kirupa that correspond to what i did (https://www.kirupa.com/html5/animating_many_elements_using_transitions.htm ).
However, i can’t find a way to pause/stop the animation when hovering or clicking an element (as in my first example) (I’ve tried adding/removing a class to cancel the transition on the transform but it’s not working properly).
Is there an easy (?) way to achieve this ?
It has been a long time indeed! The forums have a banner above your post that said it was 11 years ago when you last posted
The CSS approach you linked to is tricky, for there isn’t a great way to stop a transition mid-way as you have already found out. There are some hacky solutions to pick on, but I wouldn’t recommend them.
The best solution here would be to stick with a pure JS solution that doesn’t use jQuery. Just requestAnimationFrame. I could have sworn I had a tutorial around how to animate many elements in the DOM using JS, but I seem to never have created it in a way that doesn’t use the native animate method: https://www.kirupa.com/html5/animating_multiple_elements_animate_method.htm
With the holidays, I may not be able to get to this until next week. One approach you can try would be to modify the Falling Snow Effect a bit to have the elements move between random points instead: https://www.kirupa.com/html5/the_falling_snow_effect.htm
Wow, 11 years… That dates me,I guess
Thank you Kirupa for the quick answer, i’ll look into this.
In the meantime, i followed the tutorial and replace my jQuery code (http://www.artefakt.be/dev/RandomDivMove_kirupa.html), the animation is much smoother indeed.
With this code, wouldn’t it be possible to use keyframes animation instead of transitions ?
I had an idea, and found a sort of hack. Instead of trying to pause the transition, i’m adding a class with a very long transition time on hover, not very clean but that does the trick for the moment.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Randomly Moving Elements DOM</title>
<style>
.container {
width: 600px;
height: 500px;
background-color: #EEE;
position: relative;
overflow: hidden;
}
.circle {
position: absolute;
}
.circleChild {
width: 50px;
height: 50px;
background-color: orange;
opacity: .5;
border-radius: 50%;
transition: all .2s cubic-bezier(17, .67, .65, 1.31);
}
.circleChild:hover {
background-color: #333;
cursor: pointer;
transform: scale3d(1.2, 1.2, 1);
}
</style>
</head>
<body>
<div class="container">
<div class="circle">
<div class="circleChild"></div>
</div>
<div class="circle">
<div class="circleChild"></div>
</div>
<div class="circle">
<div class="circleChild"></div>
</div>
<div class="circle">
<div class="circleChild"></div>
</div>
<div class="circle">
<div class="circleChild"></div>
</div>
<div class="circle">
<div class="circleChild"></div>
</div>
<div class="circle">
<div class="circleChild"></div>
</div>
<div class="circle">
<div class="circleChild"></div>
</div>
</div>
<script>
var circles = document.querySelectorAll(".circle");
var circleObjects = [];
var containerWidth = 600;
var containerHeight = 500;
class Circle {
constructor(xPos, yPos, el) {
this.xPos = xPos;
this.yPos = yPos;
this.speed = Math.floor(100 + Math.random() * 100);
this.el = el;
this.incX = 0;
this.incY = 0;
this.signal = 1;
this.setNewPosition();
}
setNewPosition() {
this.newX = -100 + Math.floor(Math.random() * (containerWidth + 100));
this.newY = -100 + Math.floor(Math.random() * (containerHeight + 100));
var diffX = this.xPos - this.newX;
var diffY = this.yPos - this.newY;
this.incX = diffX / this.speed;
this.incY = diffY / this.speed;
}
stopMovement() {
this.signal = 0;
}
resumeMovement() {
this.signal = 1;
}
updatePosition() {
this.xPos -= (this.incX * this.signal);
this.yPos -= (this.incY * this.signal);
this.el.style.transform = "translate3d(" + this.xPos + "px, " + this.yPos + "px, 0)";
// update position for the next draw
if (Math.round(this.xPos) == Math.round(this.newX)) {
this.setNewPosition();
}
}
}
function update() {
for (var i = 0; i < circles.length; i++) {
var circle = circles[i];
var circleObject = circle.associatedObject;
circleObject.updatePosition();
}
requestAnimationFrame(update);
}
function stopMovement(e) {
var circle = e.currentTarget;
circle.associatedObject.stopMovement();
}
function resumeMovement(e) {
var circle = e.currentTarget;
circle.associatedObject.resumeMovement();
}
function setupCircles() {
for (var i = 0; i < circles.length; i++) {
var circle = circles[i];
circle.addEventListener("mouseenter", stopMovement, false);
circle.addEventListener("mouseleave", resumeMovement, false);
var x = -100 + Math.floor(Math.random() * (containerWidth + 100));
var y = -100 + Math.floor(Math.random() * (containerHeight + 100));
var circleObject = new Circle(x, y, circle);
circle.associatedObject = circleObject;
}
update();
}
setupCircles();
</script>
</body>
</html>
There is some additional cleanup that you can do to make the naming of variables and functions more clear. I am also not happy with having an eventlistener for each circle as opposed to following the advice in Handling Events for Multiple Elements. I will try to revisit some of this tomorrow
Thank you very much Kirupa, this certainly helps a lot !
I managed to add random rotation but I’m still trying to understand how it works and how i can tweak it to my needs (stop all movement or slow down elements on hovering one element, managing click events)
I’ve made some progress and managed to get close to what i’m trying to achieve using jquery and css classes in addition. However i’m still facing an unwanted behavior when i’m adding a transition duration to .circle (to add smoothness to the movement and transition on hover). Sometimes, it’s not constant, i cannot hover or click elements except for one or two. I’m not sure that is very clear, you can see it in action here : http://www.artefakt.be/dev/Random_div_click.html
For the hover transition, you need to be careful to not set any properties that are already being modified by JavaScript. One way I tried to avoid that is by wrapping my circle elements inside a parent element. For any hover related CSS changes, I only set (in my case) a transform on the parent circle element. The JavaScript affects the .circle element itself, so there is no conflict there.
Indeed, when adding a transition on .circle, the element had to finish the transition to be able to hover it. I’ve reduced the transition time to a short value to avoid this and still be able to transition the elements when clicking on it. It seems to work so far although it’s quite heavy on the cpu… (safari and chrome seems to deal with it better than firefox tough) : http://www.artefakt.be/dev/Random_div_click_filter.html