user7739271
user7739271

Reputation:

Customizing loading animation using pure javascript

I'm making a plugin for loading animation. Here is my example:

let loading = document.getElementsByClassName('loading')[0];

let width = +loading.style.width.split('px')[0], x = width / 50;

let O = {};
for (let i = 0; i <= 50; i++) {
    O[i] = {
        left: `0`,
        width: `${i * x}px`
    }
}

for (let i = 50, m = 1; i > 0; i-- , m++) {
    O[m + 50] = {
        left: `${m * x}px`,
        width: `${(i - 1) * x}px`
    }
}

let style = document.createElement('style');

let css = '';

for (let o in O) {
    let c = O[o];
    
    css += `${o}% { margin-left: ${c.left}; width: ${c.width} }`;
}

style.innerHTML = `@keyframes loading{ ${css} }`;

document.head.appendChild(style);

loading.style.animation = 'loading 2s infinite';
.container {
    width: 200px;
    height: 3px;
    background-color: rgba(0,0,0,.12);
}

.loading {
    height: 3px;
    background-color: #f00;
}
<div class="container">
    <div class="loading" style="width: 200px;"></div>
</div>

It's working. I want to upgrade this plugin by expanding the container width and keeping the loading width (still 200px).

let loading = document.getElementsByClassName('loading')[0];

let width = +loading.style.width.split('px')[0], x = width / 50;

let O = {};
for (let i = 0; i <= 50; i++) {
    O[i] = {
        left: `0`,
        width: `${i * x}px`
    }
}

for (let i = 50, m = 1; i > 0; i--, m++) {
    O[m + 50] = {
        left: `${m * x}px`,
        width: `${(i - 1) * x}px`
    }
}

let style = document.createElement('style');

let css = '';

for (let o in O) {
    let c = O[o];
    
    css += `${o}% { margin-left: ${c.left}; width: ${c.width} }`;
}

style.innerHTML = `@keyframes loading{ ${css} }`;

document.head.appendChild(style);

loading.style.animation = 'loading 2s infinite';
.container {
    width: 300px;
    height: 3px;
    background-color: rgba(0,0,0,.12);
}

.loading {
    height: 3px;
    background-color: #f00;
}
<div class="container">
    <div class="loading" style="width: 200px;"></div>
</div>

How to let it run to the end of the container?

My default example is easier because the loading width equals to the container width. So, spliting the width to multiple block (mini-widths) by width / 50 (twice).

Now, if the container width is 300, and the loading width is still 200. How to split it?

Thank you!

Upvotes: 0

Views: 84

Answers (1)

user7739271
user7739271

Reputation:

My idea: Split the container width to 3 parts:

                50%
|----------|-----|-----|----------|
{ loading1 }{ 1 }{  2  }{ loading2 }

The m variable is enabled and increased after getting full the loading width (1).

Inside the part 2, if m * z + loading_width < max_left (the loading2 is larger than the loading width (200 by default)), keep the width. Otherwise, decreased the width.

Also, because the second loop doesn't stop at 100%, I have added that field to the css alone:

100% { margin-left: 0; width: 0; }

let container = document.getElementsByClassName('container')[0];

let loading = document.getElementsByClassName('loading')[0];

let container_width = +container.style.width.split('px')[0];

let loading_width = +loading.style.width.split('px')[0];

let max_left = container_width - (container_width - loading_width);

let z = container_width / 50;

let O = {};

let m = 1;

for (let i = 0; i <= 50; i++) {
    if (i * z <= loading_width) {
        O[i] = {
            left: `0`,
            width: `${i * z}px`
        }
    } else {
        O[i] = {
            left: `${m++ * z}px`,
            width: `${loading_width}px`
        }
    }    
}

for (let i = 50, k = 51, n = 1; i > 0; i-- , k++ , n++) {
    if (m * z + loading_width <= max_left) {
        O[n + 50] = {
            left: `${m++ * z}px`,
            width: `${loading_width}px`
        }
        
    } else {
        O[n + 50] = {
            left: `${m * z}px`,
            width: `${container_width - (m * z)}px`
        }

        if (!(container_width - m * z)) {
            break;
        }

        m++
    }
}

let style = document.createElement('style');

let css = '';

for (let o in O) {
    let c = O[o];
    
    css += `${o}% { margin-left: ${c.left}; width: ${c.width} }`;
}

style.innerHTML = `@keyframes loading{ ${css} 100% { margin-left: 0; width: 0; } }`;

document.head.appendChild(style);

loading.style.animation = 'loading 2s infinite';
.container {
    height: 3px;
    background-color: rgba(0,0,0,.12);
}

.loading {
    height: 3px;
    background-color: #f00;
}
<div class="container" style="width: 300px;">
    <div class="loading" style="width: 200px;"></div>
</div>

Upvotes: 1

Related Questions