Calculating Paint Times of Elements In All Browsers - javascript

I am trying to calculate the elapsed time an element is painted onto the DOM from the start time of the script or if the specific element was even painted at all. I am inserting a background gradient to the HTML, and then using javascript to create random (clouds, which are just large periods with a text shadow) in multiple places across the screen (some negative, some positive, some within scope, some outside of scope).
Currently my code looks like this:
<html>
<head>
<style>
.container {
border: 1px solid #3b599e;
overflow: hidden;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#315d8c', endColorstr='#84aace'); /* for IE */
background: -webkit-gradient(linear, left top, left bottom, from(#315d8c), to(#84aace)); /* for webkit browsers */
background: -moz-linear-gradient(top, #315d8c, #84aace); /* for firefox 3.6+ */
}
.cloud {
color: #fff;
position: relative;
font: 100% "Times New Roman", Times, serif;
text-shadow: 0px 0px 10px #fff;
line-height: 0;
}
</style>
<script type="text/javascript">
function cloud(){
var b1 = "<div class=\"cloud\" style=\"font-size: ";
var b2 = "px; position: absolute; top: ";
document.write(b1+"300px; width: 300px; height: 300"+b2+"34px; left: 28px;\">.<\/div>");
document.write(b1+"300px; width: 300px; height: 300"+b2+"46px; left: 10px;\">.<\/div>");
document.write(b1+"300px; width: 300px; height: 300"+b2+"46px; left: 50px;\">.<\/div>");
document.write(b1+"400px; width: 400px; height: 400"+b2+"24px; left: 20px;\">.<\/div>");
}
function clouds(){
var top = ['-80','80','240','400'];
var left = -10;
var a1 = "<div style=\"position: relative; top: ";
var a2 = "px; left: ";
var a3 = "px;\"><script type=\"text/javascript\">cloud();<\/script><\/div>";
for(i=0; i<8; i++)
{
document.write(a1+top[0]+a2+left+a3);
document.write(a1+top[1]+a2+left+a3);
document.write(a1+top[2]+a2+left+a3);
document.write(a1+top[3]+a2+left+a3);
if(i==4)
{
left = -90;
top = ['0','160','320','480'];
}
else
left += 160;
}
}
</script>
</head>
<body style="margin:0;padding:0;">
<div class="container" style="width: 728px; height: 90px;">
<script>clouds();</script>
</div>
</body>
</html>
I then run this inside of an iframe, trying to detect if the visible elements are being painted first, or if they are being painted in display order (pretty much, is the ad currently being viewed, or is it out of view).
I have not found a solid technique yet that works crossbrowser to detect this. In chrome, I was able to see it work when pasting images, as the visible images got an onload event fired first (even though they were at the end of the DOM), but this wasn't the case for firefox or IE.

I'm really not sure what you're after here. You said: "(pretty much, is the ad currently being viewed, or is it out of view)." But that is a bit cryptic.. What "ad" are you talking about?
In trying to figure out what you were trying to accomplish I pretty much rewrote your script to do exactly the same as before and it does an alert of the elapsed time as well as logs the time for each cloud in the console. It's not a good way to calculate execution time (which is what it seemed to me like you were after..).
NOTE: The only reason I rewrote everything was so I myself could make better sense of it in preparation for a response from you. Once I know exactly what you want I will edit my answer.
<style>
.container {
width: 728px;
height: 90px;
border: 1px solid #3b599e;
overflow: hidden;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#315d8c', endColorstr='#84aace'); /* for IE */
background: -webkit-gradient(linear, left top, left bottom, from(#315d8c), to(#84aace)); /* for webkit browsers */
background: -moz-linear-gradient(top, #315d8c, #84aace); /* for firefox 3.6+ */
}
.cloud {
color: #fff;
position: absolute;
font: 100% "Times New Roman", Times, serif;
text-shadow: 0px 0px 10px #fff;
line-height: 0;
}
.cloud-container {
position: relative;
}
</style>
<div class="container"></div>
<script type="text/javascript">
// for IE
if (!window.console) window.console = {};
if (!window.console.log) window.console.log = function () { };
var pxTop = ['34px', '46px', '46px', '24px'],
pxLeft = ['28px', '10px', '50px', '20px'],
size = ['300px', '300px', '300px', '400px'];
function cloud(callback) {
var df = document.createDocumentFragment(),
node;
for (var i = 0; i < 4; i++) {
node = document.createElement('div');
node.className = 'cloud';
node.style.fontSize = size[i];
node.style.width = size[i];
node.style.height = size[i];
node.style.top = pxTop[i];
node.style.left = pxLeft[i];
node.innerHTML = '.';
df.appendChild(node);
}
callback && callback();
return df;
}
function clouds(containerId, callback) {
var top = ['-80','80','240','400'],
left = -10,
container = document.querySelector(containerId);
container.appendChild(document.createTextNode("\n"));
for (i = 0; i < 8; i++) {
var div = document.createElement('div');
div.className = 'cloud-container';
div.style.top = top[0] + 'px';
div.style.left = left + 'px';
console.log('About to start making a cloud', new Date().getMilliseconds());
div.appendChild(cloud(function() {
console.log('Finished making cloud', new Date().getMilliseconds());
}));
container.appendChild(div);
container.appendChild(document.createTextNode("\n")); // newline for view source
if (i == 4) {
left = -90;
top = ['0','160','320','480'];
} else {
left += 160;
}
}
callback && callback();
}
var start = new Date().getMilliseconds();
clouds('.container', (function() {
var end = new Date().getMilliseconds(),
time = end - this;
alert('Execution time: ' + time);
}).bind(start));
</script>

You should use console API for measuring timings more accurately (and avoid DIY spaghetti):
console.time("Doing stuff");
/*le code*/
console.timeEnd("Doing stuff");
This functionality is available natively in Chrome and Firefox; it can also be polyfilled on other browsers like IE but will not be as precise.
Note that using Date is not appropriate/intended for benchmarking:
Depending on the browser and OS, Date's resolution can be as low as 15 milliseconds.
Date based on system time, isn't ideal. Most systems run a daemon which regularly synchronizes the time... tweaked a few milliseconds every 15-20 minutes. At that rate about 1% of 10 second intervals measured would be inaccurate.
Update:
Hold on, are you trying to measure browser paints' timing and order? These can't be monitored through js (ok, it's possible to have a js API, but ultimately it has to be benchmarked in the browser engine, so no js polyfills).
Rule of thumb is elements will be painted in parse order, with re-paints/re-flows triggered by content styling - like backgrounds being loaded, additional css rules becoming available or content of different size being added into a table column.
Html5rocks on profiling long paint times might get you started in the right direction.

Related

Changing an HTML element's style in JavaScript with its CSS transition temporarily disabled isn't reliably functioning [duplicate]

This question already has answers here:
How can I force WebKit to redraw/repaint to propagate style changes?
(33 answers)
Closed 4 years ago.
Currently I am working on an animation for a website which involves two elements having their position changed over a period of time and usually reset to their initial position. Only one element will be visible at a time and everything ought to run as smoothly as possible.
Before you ask, a CSS-only solution is not possible as it is dynamically generated and must be synchronised. For the sake of this question, I will be using a very simplified version which simply consists of a box moving to the right. I shall be referring only to this latter example unless explicitly stated for the remainder of this question to keep things simple.
Anyway, the movement is handled by the CSS transition property being set so that the browser can do the heavy lifting for that. This transition must then be done away with in order to reset the element's position in an instant. The obvious way of doing so would be to do just that then reapply transition when it needs to get moving again, which is also right away. However, this isn't working. Not quite. I'll explain.
Take a look at the JavaScript at the end of this question or in the linked JSFiddle and you can see that is what I'm doing, but setTimeout is adding a delay of 25ms in between. The reason for this is (and it's probably best you try this yourself) if there is either no delay (which is what I want) or a very short delay, the element will either intermittently or continually stay in place, which isn't the desired effect. The higher the delay, the more likely it is to work, although in my actual animation this causes a minor jitter because the animation works in two parts and is not designed to have a delay.
This does seem like the sort of thing that could be a browser bug but I've tested this on Chrome, Firefox 52 and the current version of Firefox, all with similar results. I'm not sure where to go from here as I have been unable to find this issue reported anywhere or any solutions/workarounds. It would be much appreciated if someone could find a way to get this reliably working as intended. :)
Here is the JSFiddle page with an example of what I mean.
The markup and code is also pasted here:
var box = document.getElementById("box");
//Reduce this value or set it to 0 (I
//want rid of the timeout altogether)
//and it will only function correctly
//intermittently.
var delay = 25;
setInterval(function() {
box.style.transition = "none";
box.style.left = "1em";
setTimeout(function() {
box.style.transition = "1s linear";
box.style.left = "11em";
}, delay);
}, 1000);
#box {
width: 5em;
height: 5em;
background-color: cyan;
position: absolute;
top: 1em;
left: 1em;
}
<div id="box"></div>
Force the DOM to recalculate itself before setting a new transition after reset. This can be achieved for example by reading the offset of the box, something like this:
var box = document.getElementById("box");
setInterval(function(){
box.style.transition = "none";
box.style.left = "1em";
let x = box.offsetLeft; // Reading a positioning value forces DOM to recalculate all the positions after changes
box.style.transition = "1s linear";
box.style.left = "11em";
}, 1000);
body {
background-color: rgba(0,0,0,0);
}
#box {
width: 5em;
height: 5em;
background-color: cyan;
position: absolute;
top: 1em;
left: 1em;
}
<div id="box"></div>
See also a working demo at jsFiddle.
Normally the DOM is not updated when you set its properties until the script will be finished. Then the DOM is recalculated and rendered. However, if you read a DOM property after changing it, it forces a recalculation immediately.
What happens without the timeout (and property reading) is, that the style.left value is first changed to 1em, and then immediately to 11em. Transition takes place after the script will be fihished, and sees the last set value (11em). But if you read a position value between the changes, transition has a fresh value to go with.
Instead of making the transition behave as an animation, use animation, it will do a much better job, most importantly performance-wise and one don't need a timer to watch it.
With the animation events one can synchronize the animation any way suited, including fire of a timer to restart or alter it.
Either with some parts being setup with CSS
var box = document.getElementById("box");
box.style.left = "11em"; // start
box.addEventListener("animationend", animation_ended, false);
function animation_ended (e) {
if (e.type == 'animationend') {
this.style.left = "1em";
}
}
#box {
width: 5em;
height: 5em;
background-color: cyan;
position: absolute;
top: 1em;
left: 1em;
animation: move_me 1s linear 4;
}
#keyframes move_me {
0% { left: 1em; }
}
<div id="box"></div>
Or completely script based
var prop = 'left', value1 = '1em', value2 = '11em';
var s = document.createElement('style');
s.type = 'text/css';
s.innerHTML = '#keyframes move_me {0% { ' + prop + ':' + value1 +' }}';
document.getElementsByTagName('head')[0].appendChild(s);
var box = document.getElementById("box");
box.style.animation = 'move_me 1s linear 4';
box.style.left = value2; // start
box.addEventListener("animationend", animation_ended, false);
function animation_ended (e) {
if (e.type == 'animationend') {
this.style.left = value1;
}
}
#box {
width: 5em;
height: 5em;
background-color: cyan;
position: absolute;
top: 1em;
left: 1em;
}
<div id="box"></div>

Does a hidden/transparent element impact rendering performance?

So I have a Polymer app that I am writing. I have written a non-polymer web-component for a loading overlay that I can show whilst Polymer is loading and when the app Websocket is connecting/reconnecting.
Here is an exert of some of the CSS I have to give an indication of what I am doing:
.overlay {
background: #000;
bottom: 0;
height: 100%;
left: 0;
opacity: 0;
pointer-events: none;
position: fixed;
right: 0;
transition: opacity 0.2s;
top: 0;
width: 100%;
z-index: 9999999;
}
.overlay[opened] {
opacity: 0.8;
pointer-events: auto;
}
.loader {
display: none;
}
.overlay[opened] .loader {
display: block;
}
Now this overlay and the CSS based loader animation I have is only used when I load the application realistically, however if the WebSocket were to disconnect it would be shown too.
My question is, for performance reasons, should I be removing the element from the DOM entirely and add it back if its required? Does the fact that the overlay is completely transparent when not in use and the loader animation is hidden mean they have no impact on drawing performance?
Note: I am looking to avoid the "don't micro-optimise" answer if possible ;)
TL;DR:
In general, a rendered element affects page performance when changes to it trigger repaint on subsequent elements in DOM or when it triggers resize on its parent(s), as resize can get expensive from being fired up to 100 times/second, depending on device.
As long as changes to your element do not trigger repaint on subsequent elements in DOM tree, the difference between having it rendered, hidden behind some opaque element (or above the content, with opacity:0 and pointer-events:none) and having it not displayed at all is insignificant.
Changes to your element will not trigger repaint on anything but itself, because it has position:fixed. The same would be true if it had position:absolute or if the changes to it would be made through properties that do not trigger repaint on subsequent siblings, like transform and opacity.
Unless the loader is really heavy on the rendering engine (which is rarely the case — think WebGL loaders with 3d scenes, materials and lights mapping — in which case it would be better to not display it when not shown to the user), the difference would be so small that the real challenge is to measure this difference, performance wise.
In fact, I would not be surprised if having it rendered and only changing its opacity and pointer-events properties is not, overall, less expensive than toggling its display property, because the browser doesn't have to add/remove it from DOM each time you turn it on/off. But, again, the real question is: how do we measure it?
Edit: Actually, I made a small testing tool, with 10k modals. I got the following results, in Chrome, on Linux:
`opacity` average: 110.71340000000076ms | count: 100
`display` average: 155.47145000000017ms | count: 100
... so my assumption was correct: display is more expensive overall.
The opacity changes are mostly around 110ms with few exceptions, while the display changes are faster when nodes are removed but slower when added.
Feel free to test it yourself, in different browsers, on different systems:
$(window).on('load', function () {
let displayAvg = 0, displayCount = 0,
opacityAvg = 0, opacityCount = 0;
for (let i = 0; i < 10000; i++) {
$('body').append($('<div />', {
class: 'modal',
html:'10k × modal instances'
}))
}
$(document)
.on('click', '#display', function () {
$('.modal').removeClass('opacity');
let t0 = performance.now();
$('.modal').toggleClass('display');
setTimeout(function () {
let t1 = performance.now();
displayAvg += (t1 - t0);
console.log(
'`display` toggle took ' +
(t1 - t0) +
'ms \n`display` average: ' +
(displayAvg / ++displayCount) +
'ms | count: ' +
displayCount
);
})
})
.on('click', '#opacity', function () {
$('.modal').removeClass('display');
let t0 = performance.now();
$('.modal').toggleClass('opacity');
setTimeout(function () {
let t1 = performance.now();
opacityAvg += (t1 - t0);
console.log(
'`opacity` + `pointer-events` toggle took ' +
(t1 - t0) +
'ms \n`opacity` average: ' +
(opacityAvg / ++opacityCount) +
'ms | count: ' +
opacityCount
);
});
})
});
body {
margin: 0;
}
.buttons-wrapper {
position: relative;
z-index: 1;
margin-top: 3rem;
}
.modal {
height: 100vh;
width: 100vw;
position: fixed;
top: 0;
left: 0;
padding: 1rem;
}
.modal.display {
display: none;
}
.modal.opacity {
opacity: 0;
pointer-events: none;
}
.as-console-wrapper {
z-index: 2;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="buttons-wrapper">
<button id="display">Toggle `display`</button>
<button id="opacity">Toggle `opacity` + `pointer-events`</button>
</div>
But this average is for 10k elements. Divide it by 10k and it's virtually no difference at all: we're talking less than 0.45% of a millisecond.
If an element is animated with 'Animation' property and its duration is infinite browser will continuously repaint the site and that will affect the site performance and lower the FPS.
However hiding elements with properties such as Opacity:0; will not do the trick because element is still in CSSOM rendering tree queue.
Visibility:hidden; and display:none; should do the trick based on CSSOM construction browser doesn't render hidden elements such as display:none; & visibility:hidden

Why does the animated text 'stutter' occasionally as it transitions across the screen?

I've been trying to make a simple marquee using velocity.js that will scroll multiple messages across the screen one after the other.
I've put together a working example but I'm experiencing issues with the text sporadically 'stuttering' as it moves.
Using the developer tools in Chrome I can see that I get a drop in framerate when this occurs but I can't figure out why:
There doesn't seem to be anything unusual such as high memory usage and the computer is doing little else.
The issue also occurs in both Internet Explorer and Mozilla Firefox so it's not a browser issue.
How can I diagnose/resolve the issue with stuttering animations, or is this situation to be expected?
The sample below should recreate the issue although as the stuttering is random you'd need to watch it carefully to see what I mean.
$(document).ready(function() {
// WINDOW WIDTH
var width = $(window).width();
// MESSAGE QUEUE
var messages = [
"This is the first message",
"This is the second message",
"This is the last message"
];
// APPEND EACH MESSAGE TO CONTAINER AND HIDE OFF RIGHT OF SCREEN
$.each(messages, function(index, value) {
$("#container").append( "<div id=\"message" + index + "\" class=\"message\">" + value + "</div>" );
$("#message" + index).css({left: width});
});
// START ANIMATION WITH FIRST MESSAGE
AnimateNext(0, messages.length - 1);
});
function AnimateNext(current) {
// GET THE CURRENT MESSAGE
var message = $("#message" + current);
// MOVE MESSAGE TO THE RIGHT OFF SCREEN POSITION
message.css({left: $(window).width()});
// MOVE MESSAGE TO THE LEFT AND OFF SCREEN
message.velocity({left: -message.width()}, 10000, "linear", function() {
// INCREASE CURRENT INDEX
current >= 2 ? current = 0 : current = current + 1;
// ANIMATE NEXT ITEM
AnimateNext(current);
});
};
html, body {
font-family: Helvetica, Arial, "Times New Roman";
height: 100%;
width: 100%;
padding: 0;
margin: 0;
background-color: black;
overflow: hidden;
}
#container {
height: 200px;
width: 100%;
background-color: darkred;
}
.message {
position: absolute;
color: white;
font-size: 100px;
white-space: nowrap;
}
<script src="https://code.jquery.com/jquery-3.2.1.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/velocity/1.5.0/velocity.min.js"></script>
<div id="container">
</div>
JSFiddle in case anyone wants to fork it

Change width of element without reflow

I have a music player with an animated bar that displays the current position in the song. It is rendered with requestAnimationFrame and works by changing the width style of the div to X%, where X is the percentage of time through the current song.
This causes huge CPU use in Chrome I believe due to the constant reflow work being done each frame. What are other options I can use to eliminate reflows and reduce CPU?
Two other requirements: this web page is a web UI over a back end music server. It's not using any HTML5 media elements. As such, the page may be loaded when the song is already partially over, so the position will not always animate between 0 and 100.
The below fiddle shows up at about 30% CPU on my machine, which seems a bit high to animate a rectangle.
var pos = 0;
var s = document.getElementById('i');
f = function() {
window.requestAnimationFrame(f);
pos += .03;
s.style.width = pos + '%';
}
f();
#i {
background-color: red;
position: absolute;
}
<div id="i">
</div>
There are a number of ways you could make a pure CSS progress bar that won’t cause a relayout, here are a few examples:
animation - http://jsbin.com/yoqabe/edit?html,css,js,output
I think one of the most performant ways would be to use an animation to control the background position of a linear-gradient. The only downside is that you can only play/pause the animation.
background-position - http://jsbin.com/veyibe/edit?html,css,js,output
If you need the ability to update the position with JS, then I would suggest updating the background-position of a gradient and applying CSS transitions, debouncing to avoid updating too quickly.
translateX: http://jsbin.com/zolurun/edit?html,js,output
You could also use CSS transforms to slide the progress bar inside of a container, which should also avoid a repaint.
These links might also be useful:
List of CSS layout, paint, and composite triggers: http://csstriggers.com
Debounce info: https://davidwalsh.name/javascript-debounce-function
You can consider using other CSS properties which don't require layout opearations, such as background-size.
And use CSS animations instead of requestAnimationFrame.
var bar = document.getElementById('i');
function playSong(currentTime, duration) {
bar.style.animationDuration = duration + 's';
bar.style.animationDelay = - currentTime + 's';
}
playSong(3, 10);
#i {
height: 1em;
background-image: linear-gradient(red, red);
background-repeat: no-repeat;
animation: bar linear;
}
#keyframes bar {
from { background-size: 0% 100%; }
to { background-size: 100% 100%; }
}
<div id="i"></div>
If you use position: absolute or position: fixed on the progress bar itself, it should prevent large reflows on the page.
Use timeupdate, The time indicated by the element's currentTime attribute has changed.
Try this:
var audio = document.getElementById("audio");
function updateProgress() {
var progress = document.getElementById("progress");
var value = 0;
if (audio.currentTime > 0) {
value = Math.ceil((100 / audio.duration) * audio.currentTime);
}
progress.style.width = value + "%";
}
audio.addEventListener("timeupdate", updateProgress, false);
#progressBar {
border: 1px solid #aaa;
color: #fff;
width: 295px;
height: 20px;
}
#progress {
background-color: #ff0000; // red
height: 20px;
display: block;
height: 100%;
width: 0;
}
<div id="progressBar"><span id="progress"></span>
</div>
<audio id="audio" controls>
<source src="http://www.w3schools.com/tags/horse.ogg" type="audio/ogg" />
<source src="http://www.w3schools.com/tags/horse.mp3" type="audio/mpeg" />Your browser does not support the audio element.
</audio>
The script you present is not very relevant to the one you desire, you animate on requestAnimationFrame but in reality you will animate every time the "song percentage" changes.
Assuming that you have a function (e.g. getSongPer()) that returns the current percentage of played song:
var oldPos, pos = 0;
var s = document.getElementById('i');
f = function() {
oldPos = pos;
pos = getSongPer();
if(oldPos !== pos){
s.style.width = pos + '%';
}
if(pos<100){
window.requestAnimationFrame(f);
}
}
f();
I didn't test it, but I expect it to be lighter, also, the performance will be affected by the precision of the percentage, e.g. there will be about 100 animation changes if you have zero digit precision and around ten times more for every digit after.
CSS:
#progress-bar {
background-color: red;
height: 10px;
width: 100%;
transform-origin: 0 0;
}
JS:
'use strict'
var progressBar = document.getElementById('progress-bar')
function setProgress(percentage) {
requestAnimationFrame(function () {
progressBar.style.transform = 'scaleX(' + percentage + '%)'
})
}
setProgress(10)
When setting the width to 100% you get a full width colored bar.
Then we can apply the scale transform to set the width of the bar without reflowing.
But oh, it scales to the middle. We can fix that by setting the origin of the transform to the top left corner using transform-origin: x y, with x and y being 0.
Then we wrap the style change in requestAnimationFrame to let the browser optimize when to apply the change.
Bam! You have a performant zero reflow progress bar.

Strange behaviour of "position: relative" when zooming. What's happening?

The Fiddle: http://jsfiddle.net/4WFrJ/
My Problem:
I can't wrap my head around the behaviour of this setup.
When I zoom in, the images tend to move faster, but when I zoom out, they don't move at all. Sometimes they just stop at 9.xxxxxx, even though I told them to move only by one pixel. Can you explain this?
My browser is Chrome.
My Aim: achieve a fluid motion with the images disappearing when out of bounds of the parent element, whatever the magnification percentage.
I am in search of the basic rules, that govern these strange processes, from which I hope to learn new things.
The Code:
HTML:
<div id = "presentation">
<ul>
<li class = "pres-item"> <img class = "pres-image" src = "../img/presentation/image1.jpg"> </li>
<li class = "pres-item"> <img class = "pres-image" src = "../img/presentation/image2.jpg"> </li>
<li class = "pres-item"> <img class = "pres-image" src = "../img/presentation/image3.jpg"> </li>
<li class = "pres-item"> <img class = "pres-image" src = "../img/presentation/image4.jpg"> </li>
</ul>
</div>
CSS:
html, body {
margin: 0;
}
#presentation {
padding: 10px;
width: 900px;
margin: 50px auto;
overflow: hidden;
}
#presentation ul {
list-style-type: none;
margin: 0;
}
#presentation ul li {
display: inline-block;
}
.pres-item {
height: 150px;
width: auto;
position: relative;
left: 0;
}
.pres-image {
width: inherit;
height: inherit;
}
JS (with jQuery):
$(document).ready(function(){
var presentation = $('#presentation');
var interval = setInterval(function() {
console.log('intervaling');
$('.pres-item').css('left', '+=1');
}, 60);
});
The Image:
The Thanks:
THANKS PEOPLE (in advance)
<script>
// too much code, but it explains..
// do this in ur interval...
var getCurrent_left = $('.pres-item').css('left');
var newCurrent_left = getCurrent_left.split['px'];
var newCurrent_left = parseInt(newCurrent_left[0]) + 1;
var newCurrent_left = parseInt(newCurrent_left);
$('.pres-item').css({"left", newCurrent_left});
// you can use parseFloat(var, 2) for decimal
</script>
My Problem:
When I zoom in, the images tend to move faster, but when I zoom out, they don't move at all.
I'm not sure this is actually a problem. They appear to move slower when zoomed out because they travel fewer screen pixels for each viewport pixel.
Sometimes they just stop at 9.xxxxxx, even though I told them to move only by one pixel. Can you explain this?
Apparently Chrome does not always return that CSS property as an integer. You can see the same effect in this code:
var presentation = document.getElementById('presentation');
var items = presentation.getElementsByClassName('pres-item');
var interval = setInterval(function () {
[].forEach.call(items, function (x) {
var lastLeft = getComputedStyle(x, null).getPropertyValue('left');
console.log(lastLeft);
x.style.left = (parseFloat(lastLeft) + 1) + 'px';
})
}, 60);
I'm not sure if this is a problem or not. You could easily avoid it by keeping track of the offset in a separate variable and incrementing it during your loop instead of computing it from the element's current style.
var presentation = $('#presentation');
var left = 0;
var interval = setInterval(function() {
++left;
$('.pres-item').css('left', left + 'px');
}, 60);

Categories

Resources