Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Muliple div creation, jquery/javascript, performance/best practice

Im trying to figure out best practices in regard to performance when creating multiple DIV's at an insane rate. For example, on every .mousemove event...

$('head').append("<style>.draw {width: 20px; height: 20px; position:fixed;</style>");

$(document).mousemove(function(mouseMOVE) {
//current mouse position
    var mouseXcurrent = mouseMOVE.pageX;
    var mouseYcurrent = mouseMOVE.pageY;

//function to create div
   function mouseTRAIL(mouseX, mouseY, COLOR) {
        $('body').append("<div class='draw' style='top:" + mouseY + "px; left:" + mouseX + "px; background: " + COLOR + ";'></div>");
    }

// function call to create <div> at current mouse positiion
   mouseTRAIL(mouseXcurrent, mouseYcurrent, '#00F');

// Remove <div>
    setTimeout(function() {
        $('.draw:first-child').remove();
    }, 250);
});

So, this works all nice and dandy but it's mega inefficient (especially so when I try filling in the space between each mouse move position). Here's an example...

$('head').append("<style>.draw {width: 20px; height: 20px; position:fixed;</style>");

$(document).mousemove(function(mouseMOVE) {
//current mouse position
    var mouseXcurrent = mouseMOVE.pageX;
    var mouseYcurrent = mouseMOVE.pageY;

// function to create div
    function mouseTRAIL(mouseX, mouseY, COLOR) {
        $('body').append("<div class='draw' style='top:" + mouseY + "px; left:" + mouseX + "px; background: " + COLOR + ";'></div>");
    }

// function call to create <div> at current mouse positiion
    mouseTRAIL(mouseXcurrent, mouseYcurrent, '#00F');

// variabls to calculate position between current and last mouse position
    var num = ($('.draw').length) - 3;
    var mouseXold = parseInt($('.draw:eq(' + num + ')').css('left'), 10);
    var mouseYold = parseInt($('.draw:eq(' + num + ')').css('top'), 10);
    var mouseXfill = (mouseXcurrent + mouseXold) / 2;
    var mouseYfill = (mouseYcurrent + mouseYold) / 2;

// if first and last mouse postion exist, function call to create a div between them
    if ($('.draw').length > 2) {
    mouseTRAIL(mouseXfill, mouseYfill, '#F80');
    }

// Remove <div>
    setTimeout(function() {
        $('.draw:first-child').remove();
        $('.draw:nth-child(2)').remove();
    }, 250);
});


I really cant figure out how to improve things. Believe me, Ive tried researching but it hasn't done much good... What I'm looking for is some suggestions, examples, or links to better practices...

Please note that I'm teaching myself to code. I'm a Graphic Design student and this is how I'm spending my summer out of class... Making little projects to teach myself JavasSript, fun stuff :)


Ive set up some jsfiddles to show what Im working on...

Mouse Trail, More Elements - Very Very Slow
Mouse Trail, Less Elements - Very Slow
Mouse Trail, Bare Bones - Slow

like image 554
Terry Avatar asked May 19 '12 09:05

Terry


2 Answers

There are multiple bad practices going on here:

  • Using elements instead of Canvas
  • Using those elements via jQuery
  • Abusing that jQuery as if you were trying to make it slow on purpose
  • Stuffing all of the above inside a mousemove handler

The root issue here really is using elements instead of canvas. After fixing that, the interaction with DOM should become minimal and thus fix the other points as well.

Also, those who claim that this works fine didn't check their CPU usage. On my Core I5-2500K one core is instantly maxed up which is ridiculous and unacceptable for something trivial like rendering a mouse trail on screen. I can very well imagine this being very very slow on an older computer. So yes, it's smooth but at the cost of using amount of resources enough for 10-20+ tabs to do the same properly.

This takes 7-14% cpu for me when moving mouse around fast, this takes full 25%.

like image 100
Esailija Avatar answered Nov 11 '22 10:11

Esailija


You should be careful not to cause a reflow and stick only to a repaint. -> When does reflow happen in a DOM environment?

So creating <div>s is no option. - But you don't need to :)

Just create as many <div>s as you will need in future and then reposition them. If you have them in an array you'd only need an integer that points to the current most one and on each mouse movement you'd increase that value (set it to 0 once it reaches the array lenght) and reposition the <div> that's pointed to by that number.

like image 41
Chris Avatar answered Nov 11 '22 12:11

Chris