CSS transform: translateX( to the right );

Covy :

I want to make a particle system for my home page. Blue little circular dots should go from left to right and then reapear in the left so that it makes a loop. Image of particles

The code below will generate 150 dots that all have different properties as speed color and size and will apear at random positions when loading the page. Either by looping the animation or by adding new dots I want to continue the animation infinitely.

// ========== JAVASCRIPT ==========
function Dot(){
    var colors = [
        "#313146",
        "#36364f",
        "#3d3d5c",
        "#404066"
    ];
    var speed = Math.floor(Math.random() * 20) + 2;

    this.obj = document.createElement("div");
    this.obj.classList.add("dot");
    this.obj.style.top = (window.innerHeight * Math.random()) + 'px'; // random Y-position after page load
    this.obj.style.left = (window.innerWidth * Math.random()) + 'px'; // random X-position after page load
    this.size = Math.floor(Math.random() * 5) + 4; // random size
    this.obj.style.height =  this.size + 'px';
    this.obj.style.width = this.size + 'px';
    this.obj.style.backgroundColor = colors[Math.floor(Math.random()*colors.length)]; // random color
    this.obj.style.animation = `move ${speed}s linear`; // start animation
    document.body.appendChild(this.obj);

    setTimeout(del, speed*1000, this.obj); // THIS FUNCTION SHOULD BE REMOVED IF ANIMATION GETS A LOOP
    function del(element) {
        element.parentNode.removeChild(element);
    };
};

for(var i = 0 ; i < 151 ; i++ ){ // creating 150 dots
    new Dot();
};

// ========== CSS ==========

.dot {
    border-radius: 50%;
    z-index: -1;
}

@keyframes move {
    0% {
        transform: translateX(0vw);
    }
    100% {
        transform: translateX(100vw);
    }
}

My problem is that as the dots apear with random positions, and all of them get a transform: translateX(100vw);, they will move out of the screen for a while before being deleted or reapeared at the beginning. My second image shows in red where the dot is moving to, and where it should move to.

image

What I tried allready:

1. JS: this.obj.style.animation = `move ${speed}s linear infinite`; added infinite and deleted the code that deletes the dots.

CSS:

@keyframes move {
    0% {
        transform: translateX(0vw);
    }
    100% {
        transform: translateX(right); 
    }
}

<= Does not exist, and couldn't find working code equal to this idea. This would have been a solution.

2. Adding a second animation with dots coming from the left when otherones where deleted. Ended in a gap between the 150 dots of the first animtion and the incomming dots of the second animation.

Is there any other possibility of moving the dots from left to right with different properties?

best regards

Temani Afif :

Since you are setting the position with JS so you can know exactly where each element will appear and use this information to adjust the animation.

Here is a basic example to illustrate:

.dot {
  background: blue;
  position:fixed;
  width: 50px;
  height: 50px;
  border-radius: 50%;
  z-index: -1;
  left:var(--x,0px);
  animation:move 2s linear infinite;
}

@keyframes move {
  0% {
    transform: translateX(0vw);
  }
  100% {
    transform: translateX(calc(100vw - var(--x,0px)));
  }
}
<div class="dot" style="top:10px;--x:80px;"></div>

<div class="dot" style="top:20px;--x:150px;"></div>

<div class="dot" style="top:100px;--x:350px;"></div>

The variable --x will define left and will get substracted from the 100vw


For better support and since you are using JS, you can get rid of calc() and CSS variables. Simply do a small calculation to find the value of transform.

Here is an example where I am using jQuery for simplicity but you can easily make it a JS-only code:

$('.dot').each(function() {
  $(this).css('transform','translateX('+ ($(window).width() - parseInt($(this).css('left')))+'px)');
});
.dot {
  background: blue;
  position:fixed;
  width: 50px;
  height: 50px;
  border-radius: 50%;
  z-index: -1;
  animation:move 2s linear infinite;
}

@keyframes move {
  0% {
    transform: translateX(0px);
  }
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="dot" style="top:10px;left:80px;"></div>

<div class="dot" style="top:20px;left:150px;"></div>

<div class="dot" style="top:100px;left:350px;"></div>

Worth to note that you need to update the value on window resize


Another idea to keep the loop effect is to have the same position and the same animation for all and you adjust the delay to simulate the different position:

.dot {
  background: blue;
  position:fixed;
  width: 50px;
  height: 50px;
  border-radius: 50%;
  z-index: -1;
  left:0;
  animation:move 2s linear infinite;
}

@keyframes move {
  0% {
    transform: translateX(0px);
  }
  100% {
    transform: translateX(100vw);
  }
}
<div class="dot" style="top:10px;animation-delay:-1s;"></div>

<div class="dot" style="top:20px;animation-delay:-0.1s;animation-duration:1s"></div>

<div class="dot" style="top:100px;animation-delay:-0.5s;animation-duration:4s"></div>

The calculation is easy. If the animation duration is D then a delay of -D/2 will place the element in the center intially. -D*0.1 will place the image at 10% and so on.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=301923&siteId=1