Reputation: 135
I'm trying to use a typing effect using 'setInterval', it works fine but lagging on mobile devices. I've slowed it down but still it lags, below I've attached the representation of what happening, also my code.
code:
function animate() {
var a = "We DESIGN,";
var b = "We DEVELOP";
var c = "and";
var d = "We CARE";
var e = 0;
var one = setInterval(function () {
document.getElementById('one').insertAdjacentHTML('beforeend',a[e]);
e = e + 1;
if (e == 10) {
clearInterval(one);
var f = 0;
var two = setInterval(function () {
document.getElementById('two').insertAdjacentHTML('beforeend',b[f]);
f = f + 1;
if (f == 10) {
clearInterval(two);
var g = 0;
var three = setInterval(function () {
document.getElementById('three').insertAdjacentHTML('beforeend',c[g]);
g = g + 1;
if (g == 3) {
clearInterval(three);
var h = 0;
var four = setInterval(function () {
document.getElementById('four').insertAdjacentHTML('beforeend',d[h]);
h = h + 1;
if (h == 7) {
clearInterval(four);
}
},200);
}
},150);
}
},200);
}
},200);
}
at first i used jquery's .append() but then tried pure js to see if it is doing anything, but no luck, and i'm calling this function onload() on body. Anyway, I've not really looked into the code to make it much smaller, so unless it isn't the reason please don't judge it.
on desktop: https://drive.google.com/open?id=1Rv4bNu1X0wcHgbehYUb5WqzcVlA2gHTV
on mobile: https://drive.google.com/open?id=1z8hCT71Xr_X9n3StDGRdn4TpLbx5TeQk
Upvotes: 2
Views: 309
Reputation: 57344
document.getElementById
is expensive. It traverses the DOM to find your element again and again for every character in the string. It makes more sense to store these elements in variables (better yet, use one container for the entire text block).
I'm not sure if setting and clearing intervals is more or less performant than the one-shot setTimeout
, but I don't think there's any harm in making the switch, if only for cleanliness. I'm also using a promise for the same reason, but you can use a callback as easily if there's any trouble with making it async.
Beyond that, the code is difficult to maintain. If you want to add more text, the pyramid of doom grows and the code generally needs to be re-written. Use a loop.
I'd approach it as follows:
const text = `We DESIGN,
We DEVELOP
and
We CARE`;
const typeElem = document.querySelector("#typewriter");
(async () => {
for (const line of text.split("\n")) {
const div = document.createElement("div");
typeElem.appendChild(div);
for (const char of [...line]) {
div.insertAdjacentHTML("beforeend", char);
await new Promise(resolve => setTimeout(resolve, 200));
}
}
})();
<div id="typewriter"></div>
Adjust timeouts to your specification (you could pause after a line, keep pauses per line/character in a separate data structure, etc).
Upvotes: 2