By using HTML5 canvas, how to create infinite loop with time interval - javascript

I want to keep updating my image position with HTML5 canvas. I tried the following javascript code to do the work
window.onload = function start() {
update();
}
function update() {
document.getElementById('scoreband').innerHTML = score;
var style = document.getElementById('bug').style;
timmer = window.setInterval(function () {
style.left = ((Math.random() * 100) + 1) + "%";
style.top = ((Math.random() * 100) + 19) + "%";
}, num);
}
But this is not working when it comes to HTML5 canvas. Is there similar way to do the same job in HTML5 canvas?

To change any visual DOM content you should use requestAmimationFrame
Eg
function update(time){
// time is in ms and has a 1/1000000 second accuracy
// code that changes some content, like the canvas
requestAnimationFrame(update); // requests the next frame in 1/60th second
}
And to start it
requestAnimationFrame(update);
As requested
indow.onload = function start() {
requestAnimationFrame(update);
}
function update() {
document.getElementById('scoreband').innerHTML = score;
var style = document.getElementById('bug').style;
style.left = ((Math.random() * 100) + 1) + "%";
style.top = ((Math.random() * 100) + 19) + "%";
requestAnimationFrame(update);
}

Though it’s not as good as requestAnimationFrame, setInterval’s frame rate can be dynamic.
//supposing num is defined lol
var timer = setInterval(update, num);
function update() {
document.getElementById('scoreband').innerHTML = score;
var style = document.getElementById('bug').style;
style.left = ((Math.random() * 100) + 1) + "%";
style.top = ((Math.random() * 100) + 19) + "%";
}

Related

Javascript conflicting with eachover

I have two pieces of java script, one for showing the result percentage in a progress bar, one to show the speed in a different bar.
at the moment only one bar is reviving data the other is not.
**Javascript*
// Progress bar javascript reults
{
var elem = document.getElementById("myBar");
var width = 0;
var id = setInterval(frame, 50);
function frame() {
if (width >= document.getElementById("results-percentile-2").innerHTML) {
clearInterval(id);
} else {
width++;
elem.style.width = width + '%';
document.getElementById("demo").innerHTML = width * 1 + '%';
}
}
}
// End javascript progress bar results
// Progress bar javascript speed
{
var elem = document.getElementById("myBarspeed");
var width = 0;
var id = setInterval(frame, 50);
function frame() {
if (width >= document.getElementById("results-speed").innerHTML) {
clearInterval(id);
} else {
width++;
elem.style.width = width + '%';
document.getElementById("speed").innerHTML = width * 1 + '%';
}
}
}
// End javascript progress bar speed
HTML
<div class="scale-container-main ">
<div id="percentile-scale" class="scale">
results bar: Your results
<div id="demo">0%</div>
<div class="myProgress">
<div id="myBar" style="width:0"></div>
</div>
speed bar: Your speed
<div id="speed">0%</div>
<div class="myProgress">
<div id="myBarspeed" style="width:0"></div>
</div>
</div>
</div>
You could use let instead of var inside each block, and
let frame = function() { .... }
but frame would have to be moved above setInterval line
Also, the above only works on recent decent broswers, which means it wont work in IE
An alternative, equally valid method is to use IIFE's - this works in IE!
(function() {
var elem = document.getElementById("myBar");
var width = 0;
var id = setInterval(frame, 50);
function frame() {
if (width >= document.getElementById("results-percentile-2").innerHTML) {
clearInterval(id);
} else {
width++;
elem.style.width = width + '%';
document.getElementById("demo").innerHTML = width * 1 + '%';
}
}
}());
// End javascript progress bar results
// Progress bar javascrip speed
(function() {
var elem = document.getElementById("myBarspeed");
var width = 0;
var id = setInterval(frame, 50);
function frame() {
if (width >= document.getElementById("results-speed").innerHTML) {
clearInterval(id);
} else {
width++;
elem.style.width = width + '%';
document.getElementById("speed").innerHTML = width * 1 + '%';
}
}
}());
The only advantage to the above is that variable names can be useful and meaningful and guaranteed not to clash with anything else (sort of)
You can't have two functions with the same name. Rename one 'frame' function to something else and change it in your setInterval. Also use different variables to store the interval in.

Multiple timers on a single HTML page

I have the following JavaScript code to update tiles on a page:
var delayMinimum = 1000;
var delayMaximum = 5000;
function UpdateTiles()
{
var width = 0;
var delay = 0;
var percent = 0;
var divNameLabel = "";
var divNameValue = "";
var divNameProgress = "";
if (Math.floor((Math.random() * 100) + 1) > 30)
{
percent = Math.floor((Math.random() * 100) + 1);
width = Math.floor(80 * percent / 100);
divNameLabel = "DivDashboardTileTemplatesLabel";
divNameValue = "DivDashboardTileTemplatesValue";
divNameProgress = "DivDashboardTileTemplatesProgress";
document.getElementById(divNameValue).innerText = percent.toString() + "%";
$("div#" + divNameProgress).animate({ width: (width.toString() + "px"), }, delayMinimum);
}
if (Math.floor((Math.random() * 100) + 1) > 30)
{
percent = Math.floor((Math.random() * 100) + 1);
width = Math.floor(80 * percent / 100);
divNameLabel = "DivDashboardTileDocumentsLabel";
divNameValue = "DivDashboardTileDocumentsValue";
divNameProgress = "DivDashboardTileDocumentsProgress";
document.getElementById(divNameValue).innerText = percent.toString() + "%";
$("div#" + divNameProgress).animate({ width: (width.toString() + "px"), }, delayMinimum);
}
if (Math.floor((Math.random() * 100) + 1) > 30)
{
percent = Math.floor((Math.random() * 100) + 1);
width = Math.floor(80 * percent / 100);
divNameLabel = "DivDashboardTileFormsLabel";
divNameValue = "DivDashboardTileFormsValue";
divNameProgress = "DivDashboardTileFormsProgress";
document.getElementById(divNameValue).innerText = percent.toString() + "%";
$("div#" + divNameProgress).animate({ width: (width.toString() + "px"), }, delayMinimum);
}
delay = Math.floor((Math.random() * (delayMaximum - delayMinimum)) + delayMinimum);
window.setTimeout(UpdateTiles, delay);
}
$(document).ready(UpdateTiles);
This works but any tiles updated in every iteration are updated all at once. How could I have independent timers with different intervals for each update?
Consider the following JSFiddle as a solution.
I have simplified it by using 1 function for all 3 calls and they now update at different (random) times. The key to recalling the update is the following line.
setTimeout(function () {updateTileSet(label,value,progress)}, delay);
You only have one timer: window.setTimeout(UpdateTiles, delay), add more timers as you need i order to have multiple timers.
Why did you duplicate the code 3 times?
Use functions instead and set the timeout in each one of them.

JavaScript Css Animation

I have a Javascript animation at http://dev17.edreamz3.com/css/
All code works, however, there are performance problems. on Desktop, its good, On mobile things are so slow that it's unusable. I want to optimize the animation so that it runs smoothly on mobile. It can take 20 seconds or more for the animation to render.
Right now the way the code is designed is in js/anim.js there is a render() function that gets executed every time a scroll event happens. The problem is that this routine is not efficient, that's what I think of. Each time render() executes it loops through all the paths and sections of the maze and redraws them, is there any alternative way or a strategy to get it working both on mobile as well as desktop.
var offPathTime = 1000;
window.offSection = -1;
function render() {
// var top = ($window.scrollTop() + (0.4 * $window.height())) / window.scale;
var top = ($('.parent-div').scrollTop() + (0.4 * $('.parent-div').height())) / window.scale;
top -= 660;
top /= mazeSize.h;
if (window.offSection != -1) {
$body.addClass("blockScroll");
$('.parent-div').addClass("blockScroll");
// var wtop = $window.scrollTop() / window.scale;
var wtop = $('.parent-div').scrollTop() / window.scale;
wtop -= 660;
wtop /= mazeSize.h;
var $offSection = $("#offSection" + window.offSection);
var $section = $("#section" + window.offSection);
$(".section").removeClass("sectionActive");
$offSection.addClass("sectionActive");
$section.addClass("sectionActive");
var sTop = 200 -(mazeSize.h * (window.offSections[window.offSection].cy - wtop));
$container.animate({
left: 290 -(mazeSize.w * window.offSections[window.offSection].cx) + "px",
top: sTop + "px"
}, offPathTime);
// Path
var lr = offPaths[window.offSection].x1 > offPaths[window.offSection].x0;
var dx = Math.abs(offPaths[window.offSection].x1 - offPaths[window.offSection].x0);
var dashw = (dx * mazeSize.w) | 0;
$offPaths[window.offSection].css("width", "0px");
$offPaths[window.offSection].show();
if (lr) {
$offPaths[window.offSection].animate({
width: dashw + "px"
}, offPathTime);
} else {
var x0 = offPaths[window.offSection].x0 * mazeSize.w;
var x1 = offPaths[window.offSection].x1 * mazeSize.w;
$offPaths[window.offSection].css("left", x0 + "px");
$offPaths[window.offSection].animate({
width: dashw + "px",
left: x1 + "px"
}, offPathTime);
}
return;
}
$body.removeClass("blockScroll");
$('.parent-div').removeClass("blockScroll");
$(".offPath").hide();
if ($container.css("top") != "0px") {
$container.animate({
left: "-1550px",
top: "0px"
}, 500);
}
var pathIdx = -1;
var path0 = paths[0];
var path1;
var inPath = 0;
var i;
var curTop = 0;
var found = false;
for (i=0; i<paths.length; i++) {
var top0 = (i == 0) ? 0 : paths[i-1].y;
var top1 = paths[i].y;
if (top >= top0 && top < top1) {
pathIdx = i;
path1 = paths[i];
inPath = (top - top0) / (top1 - top0);
found = true;
if (i > 0) {
var dy = paths[i].y - paths[i-1].y;
var dx = paths[i].x - paths[i-1].x;
var vert = dx == 0;
if (vert)
$paths[i-1].css("height", (dy * mazeSize.h * inPath) + "px");
$paths[i-1].show();
}
} else if (top >= top0) {
path0 = paths[i];
var dy = paths[i].y - top0;
var vert = dy != 0;
if (i > 0) {
if (vert)
$paths[i-1].css("height", (dy * mazeSize.h) + "px");
$paths[i-1].show();
}
} else {
if (i > 0) {
$paths[i-1].hide();
}
}
curTop = top1;
}
// Check for an active section
$(".section").removeClass("sectionActive");
var section;
for (i=0; i<sections.length; i++) {
var d = Math.abs(sections[i].cy - (top - 0.05));
if (d < 0.07) {
var $section = $("#section" + i);
$section.addClass("sectionActive");
}
}
}
1) At the very least - assign all DOM objects to variables outside of the function scope. Like this:
var $parentDiv = $('.parent-div');
var $sections = $(".section");
...
function render() {
...
2) Also you should probably stop animation before executing it again, like this:
$container.stop(true).animate({
...
If you are running render() function on scroll - it will run many times per second. stop() helps to prevent it somewhat.
3) If it will not be sufficient - you can switch from jQuery to Zepto(jQuery-like api, but much faster and uses css transitions for animations) or to Velocity(basically drop-in replacement for jQuery $.animate and much faster than original) or even to GSAP - much more work obviously, but it is very fast and featured animation library.

Moving div elements stored in array

var move = function() {
Xpos = Math.round(Math.random() * 95);
food[num].css('left', Xpos + '%');
interval = setInterval(function() {
console.log(i);
var posTop = food[num].offset().top / $(window).height() * 100;
while(posTop < 80) {
if(posTop === 80) {
num++;
break;
}
posTop += 1;
food[num].css('top', posTop + '%');
break;
}
}, speed);
}
//Color the circle
circleColor();
move();
}
OK so this is my code. It creates a circle(a <div> element) on top of the screen and gives it a random x coordinate. Than it puts it in food[] array. The entire code starts by clicking the button, but every time I press the button again the circle that was last moving stops, function creates a new one and the new one moves. Is there a way I can make all elements in the array move without depending on each other?
http://jsfiddle.net/yqwjqx31/
I understand why this happens but I have no idea how to fix it.
First you're using a global variable num in setInterval function handler, so its value get modified while using it in new cercle create, secondly you're clearing interval of the last cercle you created before creating a new cercle. It means you're sharing the same interval between all cercles. Use instead an array of intervals just like var food =[] and use a temporary variable to prevent the index value modification inside your setInterval handler. Here's a working fiddle
//Interval
var interval =[];
var tempNum = num;
interval[num] = setInterval(function() {
var posTop = food[tempNum].offset().top / $(window).height() * 100;
while(posTop < 80) {
if(posTop === 80) {
break;
}
posTop += 1;
food[tempNum].css('top', posTop + '%');
break;
}
}, speed);
Increment your num variable
//Color the circle
circleColor();
move();
num++;
Your move function is only responsible for moving the last generated div via createCircle. If you want to move them all till collision, you need to loop through them all and move them accordingly. Or, you can animate them via CSS.
Here is the working version :
http://jsfiddle.net/yqwjqx31/3/
Notice how the setInterval callback loops through all the div and pushes them down until their height is 80.
var move = function () {
interval = setInterval(function () {
for (var i = 0; i < food.length; ++i) {
var posTop = food[i].offset().top / $(window).height() * 100;
if (posTop < 80) posTop += 1;
food[i].css('top', posTop + '%');
}
}, speed);
}

rotate object onclick

So i have the code that is supposed to add when clicked "+10" button 10degree rotation to object, when clicked "+30" button 30degree rotation to the object, the 90degree position to be max available. Now it ads only by one and i dont know how to make it to move as much degree as i want it to move.
http://jsfiddle.net/9Xghf/
var rotateObject = document.getElementById("object");
var objectRotation = 0;
var add10 = document.getElementById("add10");
var add30 = document.getElementById("add30");
add10.onclick = function(){
rotate(0, 10);
}
add30.onclick = function(){
rotate(0, 30);
}
function rotate(index, limit){
if(objectRotation < 90 && index <= limit){
index++;
objectRotation++;
rotateObject.style.transform="rotate(" + objectRotation + "deg)";
rotateObject.style.WebkitTransform="rotate(" + objectRotation + "deg)";
rotateObject.style.msTransform="rotate(" + objectRotation + "deg)";
setTimeout(rotate, 50);
}else{
// 90 degree is the max limit for this object
}
}
Replace the timer by this :
setTimeout(function(){
rotate(index,limit);
}, 50);
nb : this won't work for all browsers

Categories