I am building an animation with lots of effects and animation in a website. I am trying to optimize the efficiency of those animations since some of them are a little complex to low CPU/RAM devices. The animations are not smooth as I want as you can see here https://www.empresasite.com.br
So I realize in many parts of my code I do this:
var x = 38; //this value changes every 50ms
document.getElementById("a").style.left = document.getElementById("b").style.left = document.getElementById("c").style.left = document.getElementById("d").style.left = document.getElementById("e").style.left = x + "px";
Actually it's a simplification above, I run the code above with at least 13 elements a = b = c = d .... m = x; and at least with 4 properties (left, height, box-shadow and background-color).
So I was wondering if there is any better alternative to assign the same value to multiple elements/objects at once?
Maybe the code below would be faster? I used it but I didnt see a significant improvement in animation, maybe I should have seen it?
var x = 38;
x = x + "px";
document.getElementById("a").style.left = x;
document.getElementById("b").style.left = x;
document.getElementById("c").style.left = x;
document.getElementById("d").style.left = x;
document.getElementById("e").style.left = x;
I think the code above should be faster right? I say this cause every element updates its own property (left) retrieving the value from "x". In the first example I gave MAYBE javascript is assigning the value of the previous element in the chain of "=" sign so it has to assign "x" to the first element then assign the value of the first element to the second... go on.
Do you know exactly what jquery does when I use this:
$(".elements").css({left:x});
Does it use some optimization?
You could increase performance no-end by using translate instead of modifying position.
Using the jQuery variation you asked will not make any difference, as you are still modifying position left.
After playing around with most of the javascript benchmarking tools online I came up to this conclusion:
1) Jquery is the faster method of all native js solutions I used. Maybe Jquery uses some sort of optimization when you apply the same property to lots of elements at once! So you should rely on $(".class").css("left",x) to apply the x value to left property for hundreds of elements and it will be the faster solution;
2) The second solution is apply x individually TO EACH element. Example:
var x = 38;
document.getElementById("a").style.left = x;
document.getElementById("b").style.left = x;
3) The worst solution was actually the one I was using in the website that I was facing not smooth animations. So avoid this:
document.getElementById("a").style.left = document.getElementById("b").style.left = ... = ... = x;
The difference from the 1st solution to the 3rd is really noticeable. You can check it in the links below (pay special attention to the animation at the top):
1) https://www.empresasite.com.br/?q=principal&before -> this is using the 3rd solution
2) https://www.empresasite.com.br/?q=principal -> this is using the 1st solution
In a computer with lots of resources you may not see a difference but if you run this in a computer with 4GB of RAM or less you will see a big impact!
Hope this helps anyone that does not have smooth animations!
Related
I'm having problem with a project that I'm working on in matlab which i'm then going to implement using javascript. The purpose is to use matlab to get a better understanding of the physics before moving over to javascript. The goal is to create some sort of a Rollercoaster simulation in matlab using differential equations and euler aproximation. Then to animate a block(cart) following the path.
The problem is that I can't get the approximation working on a arbitary path (equation), and I don't understand what I'm doing wrong.
So this is what i'm trying to do:
for t=1:h:tf
%acceleration
ax(i) = (g*cos((-pi/4)))*sin(-pi/4)-((C*ro*A*vx(i)^2*sign(vx(i)))/(2*m))*sin(-pi/4);
ay(i) = (g*cos((-pi/4)))*cos(-pi/4)+((C*ro*A*vy(i)^2*sign(vy(i)))/(2*m))*cos(-pi/4);
%speed
vx(i+1) = vx(i)+h*ax(i);
vy(i+1) = vy(i)+h*ay(i);
%position
x(i+1) = x(i)+h*vx(i);
y(i+1) = y(i)+h*vy(i);
i = i+1;
speed = sqrt(vx(i)^2+vy(i)^2);
plot(x(i),y(i),'or')
pause(1/speed)
end
Where i'm following Newtons second law (F=ma => a = F/m) the only negative force component i'm using now is air resistance.
This is when i'm using a hardcoded path -> y=1-x, and it's working just fine!
But when i try to use an arbitary path, eg. 1/x, the angle is changed all the time, and i've tried things like putting each angle into an angle vector:
%% initial values
vx(1) = 0;
vy(1) = 0;
x(1) = 0;
y(1) = 6.7056;
%Track Geometry Constants
h_start = 6.7056;
l_end = 32;
b = .055;
w = .7;
p = .3;
%% Creating path
path_x = linspace(0, 23, 1000);
path_y = (exp(-b*path_x).*(cos(w*path_x - p)) + 2.2*(exp(-(b)*path_x)));
path_y = path_y*(h_start/max(path_y));
path_x = path_x*(l_end/max(path_x));
%%
alpha = zeros(size(path_y));
for k=1:1:size(path_y)-1
alpha(j) = atan(path_y(k+1)-path_y(k))/(path_x(k+1)-path_x(k));
j= j+1;
end
But this doesn't appear to work.
How can I make this work for an arbitrary path?
Thank you in advance!
There is a pretty simple error in your loop. Two errors, actually.
You are indexing alpha with a variable, j, that doesn't exist and increment it in the loop, instead of just using k, which increments automatically in the loop.
The reason this isn't giving an error is that your loop never runs. Because the size of path_y is not a single number, (the size is 1 x 1000), k=1:1:size(path_y)-1 tries to create a loop that goes from 1 to 0 in steps of positive 1. Since this isn't possible, the loop is skipped. One option is to use length, not size here.
But the most important error: you didn't check your code line by line when it stopped working to confirm that every part of your code was doing what you thought it was when you wrote it. If you'd checked what k=1:1:size(path_y)-1 was outputting, you should have been able to identify this problem very quickly.
Incidentally I think you can avoid the loop entirely (append a zero at the end if you really need this to have the same size as the path variables):
alpha = atan(diff(path_y)./diff(path_x));
I have written a javascript program which plots the Mandelbrot set with the normal pretty colours approaching the boundary. I was planning on adding a zoom function next but it is far far too slow for this to be sensible.
I have posted the most important portion of the code here:
while (x * x < 2 && y * y < 2 && iteration < max_iteration) {
xtemp = (x * x) - (y * y) + xcord;
y = (2 * x * y) + ycord;
x = xtemp;
iteration = iteration + 1;
}
and have linked to a jsfiddle with the whole page here: http://jsfiddle.net/728dn2m0/
I have a few global variables which I could take into the main loop but that would result in additional calculations for every single pixel. I read on another SO question that an alternative to the 1x1 rectangle was to use image data but the performance difference was disputed. Another possibility would be rewriting the while statement as some other conditional loop but I'm not convinced that would give me the gains I'm looking for.
I'd consider myself a newbie so I'm happy to hear comments on any aspect of the code but what I'm really after is something which will massively increase performance. I suspect I'm being unreasonable in my expectations of what javascript in the browser can manage but I hope that I'm missing something significant and there are big gains to be found.
Thanks in advance,
Andrew
Using setInterval as an external loop construct slows the calculation down. You set it to 5 ms for a single pixel, however the entire Mandelbrot map calculation can be done within 1 second. So a single call to your function draws a pixel very quickly and then waits about the 99.99% of that 5 milliseconds.
I replaced
if (m<=(width+1))
with
while (m<=(width+1))
and removed the setInterval.
This way the entire calculation is done in one step, without refresh to the screen and without using setInterval as an external loop construct. I forked your script and modified it: http://jsfiddle.net/karatedog/2o4gjrv2/6/
In the script I modified the bailout condition from (x*x < 2 && y*y < 2) to (x < 2 && y < 2) just as I suggested in a previous comment and revealed some hidden pixel, check the difference!
I had indeed missed something significant. The timer I had used in order to prevent the page hanging while the set was plotted was limiting the code to one pixel every 5 milliseconds, in other words 200 pixels per second. Not clever!
I am now plotting one line at a time and it runs a lot better. Not yet real time but it is a lot quicker.
Thanks for the ideas. I will look into the escape condition to see what it should be.
A new jsfiddle with the revised code is here: http://jsfiddle.net/da1qyh9y/
and the for statement I've added is here:
function main_loop() {
if (m<=(width+1)) {
var n;
for (n=0; n<height; n=n+1) {
I have an image of a bug. I want to make 5 copies of that image fly in from the side of the screen and bounce around the screen and bounce off the sides. I want them to all have different starting positions and different directions.
so I made some a global variables
var flyVar;
var flySpeed = 5;
var widthMax = 0;
var heightMax = 0;
var xPosition = 0;
var yPosition = 0;
var xDirection = "";
var yDirection = "";
var bugFly;
var count = 1;
var bug = "bug";
I have a function called setBugs() that I use to set the value of widthMax and heightMax depending on the size of the users screen.
I have a bugStartingPlace function to set the initial starting place for each bug. I won't post the whole function but it does the same for "bug1" through "bug5", giving them different values.
function bugStartingPlace(bugName) {
//Accepts string as argument and sets the starting position and starting direction of each bug.
if (bugName == "bug1") {
xPosition = 0;
yPosition = 100;
xDirection = "right";
yDirection = "up";
}
}
I have a function called flyBug() that does the animation and sets the position of the image. It consists of a bunch of statements like this. I know it works because I can make it work with 1 bug. The problem is doing it with 5 bugs.
function flyBug() {
if (xDirection == "right" && xPosition > (widthMax - document.getElementById("bugImage").width - flySpeed))
xDirection = "left";
<!--More flow control statements are here-->
document.getElementById("bug1").style.left = xPosition + "px";
document.getElementById("bug1").style.top = yPosition + "px";
<!-- More statements are here that set the position of the image -->
}
So, I need some way to get the animation going with the body onload() event. One problem is that setInterval does not allow functions that contain parameters. So I can't put multiple statements in the body onload event that pass "bug1" as a parameter to this function, "bug2" as a parameter to this function and so on. That's why I made the global count variable. That way, any time I need to change the name of the bug, I change the name of count and then do
bug = bug + count;
But that adds a lot of complexity. I need the name of the bug for the bugStartingPlace() function, so I need to change the value of count and also change the value of bug before I use that function. Once I use the bugStartingPlace() function, that changes the value of the global variables. Then I need to use flyBug() before I change the value of bug again.
I guess one of the problems is that I'm using global variables for direction and position even though I have multiple bugs. It works fine for one bug but not for multiple bugs.
Can anyone give me tips on how the logic of this program should work?
setInterval allows, like setTimeout, the use of parameters in the function BUT:
setInterval(funcName(param1,param2...), 100);
wont work. Youll get it to work like that:
var func = function () { funcName(param1,param2..); }
setInterval(func, 100);
To understand that part of javascript, read through dougles crockfords explanation of functions, he tells about this very clear and deep. Link to a video of him
EDIT: Sry i understood your question wrong...
The problem why it wont work is, like you figured out the global vars. You could just make bug an object. His actions will then be methods, which can contain a function and so on. If you then initialize a new bug (you can do this a thousand times then), all the vars stay in the object, without conflicting each other. This is a secure way to provide solidness of your code.
You could do it very simple, with nested functions.
Another way would be, to send the name of the bug vie parameter to the, for example, fly function. And the only work in that function with the parameter given to it.
I need help/advice for improving/commenting my current design please :)
This relates to collision detection in a simple game: Dynamic bodies (moving ones) might collide with static bodies (i.e. ground, walls). I'm porting my Obj-C model to Javascript and am facing memory/performance questions as to my way of implementing this.
I'm using a very basic approach: An array of arrays represents my level in terms of physic opacity.
bit set to 0: Transparent area, bodies can go through
bit set to 1: Opaque area, bodies collide
Testing the transparency/opacity of a pixel simply goes as follows:
if (grid[x][y]) {
// collide!
}
My knowledge of JS is pretty limited in termes of performance/memory and can't evaluate how good this approach is :) No idea of the efficiency of using arrays that being said.
Just imagine a 1000-pixel wide level that's 600px high. It's a small level but this already means an array containing 1000 arrays each containing up to 600 entries. Besides, I've not found a way to ensure I create a 1bit-sized element like low-level languages have.
Using the following, can I be sure an entry isn't something "else" than a bit?
grid[x][y] = true;
grid[x][y] = false;
Thanks for your time and comments/advices!
J.
If you have an 1000x600 grid, you can guarantee you have at least 601 arrays in memory (1001 if you do it the other way round).
Rather than doing this, I would consider using either 1 array, or (preferrably) one object with a mapping scheme.
var map = {};
map["1x1"] = 1;
map["1x3"] = 1;
// assume no-hits are empty and free to move through
function canGoIn(x, y) {
return map.hasOwnProperty(x + "x" + y);
};
Alternately;
var map = [];
var width = 600;
map.push(0);
map.push(1);
// etc
function canGoIn(x, y) {
return map[(x * width) + y] == 1;
}
a boolean value won't be stored as just one bit, and that is also true for any other language I know (C included).
If you are having memory issues, you should consider implementing a bitarray like this one: https://github.com/bramstein/bit-array/blob/master/lib/bit-array.js
You will have to make your 2d array into a simple vector and converting your x, y coordinates like this: offset = x + (y * width);
Browsing an array will still lead to a multiplication to evaluate the offset so using a vector is equivalent to arrays.
But I suspect that calling a function (in case your using a bit-array) and doing some evaluations inside will lead to poorer performances.
I don't think you can gain performances and save memory at the same time.
http://davzy.com/gameA/
I can't figure out a smart way to get gravity. Now with this it detects which block the character is over but it does't drop to that block!
Is there a better way to do gravity? I'd like to do this without a game library.
I don't know what you mean by "get gravity"; your question is unclear. I assume that if you can detect when the block is over, you can use the following formula:
s(t) = ut + 1/2at2
Where s is the distance at time t, u is the initial velocity (which in your case would be zero), and a is the acceleration (on Earth this is 9.8m/s2). Essentially you would be adjusting the top position of your object based on the value you get at time t (so original top position of object + s(t)). I would imagine you would use some sort of animation loop. Perhaps a setInterval. Maybe others with more experience in Javascript animation can chime in about the best way to implement this. However, this would be the formula that you would be using to figure out where the object is at time t, if it falls.
Basically gravity in a platformer goes like this:
var currentGrav = 0.0;
var gravAdd = 0.5; // add this every iteration of the game loop to currentGrav
var maxGrav = 4.0; // this caps currentGrav
var charPosY = getCharPosY(); // vertical position of the character, in this case the lower end
var colPosY = getColDow(); // some way to get the vertical position of the next "collision"
for(var i = 0; i < Math.abs(Math.ceil(currentGrav)); i++) { // make sure we have "full pixel" values
if (charPosY == colPosY) {
onGround = true;
break; // we hit the ground
}
onGround = false;
charPosY++;
}
Now to jump one could simply do this:
if (jumpKeyPressed && onGround) {
currentGrav = -5.0; //
}
You can, if you want(and understand C), check out my game for a basic platformer(with moving platforms) here:
http://github.com/BonsaiDen/Norum/blob/master/sources/character.c