2013-06-23 3 views
1

Итак, я пишу сценарий рисования, и сейчас он отлично работает (хотя код еще нужно очистить, и там должно быть больше возможностей), но при рисовании слишком много, mousemove лагов невероятно. Вот основные Javascript:Предотвращение отставания в DOM

$('#canvas').on('mousedown', function(){ 
     going = !going; 
     $(this).on('mousemove', function(e){ 
      if(cursor == 'paint' && going == true){ 
     $('.fall').each(function(){ 
      if ($(this).css("opacity") == 0){ 
       $(this).remove(); 
      }; 
     }); 
     var ps = $('#canvas').offset().top; 
     var t = (e.pageY - ps - $('.fall').height()).toString() + 'px'; 
     var l = (e.pageX - $('.fall').width()).toString() + 'px'; 
     $('.fall').css("margin_left",l); 
     $('.fall').css("margin_top",t); 
       var doit = '<div class="fall" style="position:absolute;margin-left:' + l + ';margin-top:' + t + ';background-color:'+ color +';box-shadow: 0px 0px 5px ' + color + ';"></div>' 
     $('#canvas').prepend(doit); 
      } 
      else if(cursor == 'erase'){ 
      $('.fall').mouseenter(function(){ 
       $(this).fadeOut('fast',function(){ 
        $(this).remove() 
       }); 
      }); 
     }; 
    }); 

По существу, при нажатии кнопки в секции для рисования, если кнопка нажата краски, вы можете сделать: jsfiddle.

Мой вопрос:

Если вы рисуете слишком много, особенно с запуском и остановки, он не добавляет достаточно на mousemove сделать, чтобы (я предполагаю) DOM-перегружают.

Вопрос:

Что бы быть эффективным способом, чтобы добавить много много дивов в DOM без создания лаг? Это возможно?

Примечание:

это личный проект, и я не заинтересован в использовании ранее созданное рисование API,

+0

Вы добавляете ** еще один обработчик «mousemove» на каждом «mousedown». Вызов '.on()' не удаляет никаких предыдущих обработчиков! – Pointy

+0

hmmmm Я думаю, это правда! Как удалить обработчик? –

+1

Нет необходимости удалять старые обработчики; просто добавьте этот код в другой обработчик mousemove. Кроме того, код, который обновляет «курсор», чрезвычайно дорог. Вы должны попытаться получить координаты мыши из объекта события вместо опроса DOM. – Pointy

ответ

1

Там много вы можете сделать, чтобы улучшить производительность.

Код ниже представляет собой тяжелый рефакторинг кода в вопросе. На первый взгляд это может показаться менее эффективным, поскольку оно имеет удвоенное количество строк оригинала. Однако количество строк здесь не является проблемой. Применяются два основных принципа:

  • Выполняйте как можно больше взаимодействия с DOM в обработчике mousemove и как можно больше на mousedown.
  • включают в себя «разделительную цепь», чтобы ограничить количество выходов обработчика mousemove. Это достигается путем отсоединения обработчика события mousemove при каждом вызове и повторной фиксации после короткой задержки, обусловленной тем, что мышь все еще опускается.

Также см. Комментарии в коде.

jQuery(function($) { 
    ... 
    var $canvas = $("#canvas"); 
    var data = { 
     name: 'fall'//a unique string for namespacing the muousemove event. 
    }; 
    $canvas.on('mousedown', function() { 
     going = !going; 
     data.$fall = $('.fall');//this collection is created once per mousedown then managed inside mm to avoid unnecessary DOM interaction 
     data.mousedown = true; 
     data.colorCSS = { 
      'background-color': color, 
      'box-shadow': '0px 0px 5px ' + color 
     }; 
     data.fallWidth = data.$fall.width(); 
     data.fallHeight = data.$fall.height(); 
     attachMouseMoveHandler(); 
    }).on('mouseup', function() { 
     data.mousedown = false; 
    }).trigger('mouseup'); 

    function attachMouseMoveHandler() { 
     if(data.mousedown); 
      $canvas.on('mousemove.' + data.name, mm);//the event is namespaced so its handler can be removed without affecting other canvas functionality 
    } 

    //The mousemove handler 
    function mm(e) { 
     if(going && cursor == 'paint') { 
      data.$fall.each(function() { 
       data.$fall = data.$fall.not(this);//manage data.$fall rather than re-form at every call of mm() 
       var $this = $(this); 
       if ($this.css("opacity") == 0) { 
        $this.remove(); 
       }; 
      }); 
      data.$fall = data.$fall.add($('<div class="fall" />').css(data.colorCSS).prependTo($canvas)).css({ 
       'margin-left': (e.pageX - data.fallWidth) + 'px', 
       'margin-top': (e.pageY - $canvas.offset().top - data.fallHeight) + 'px' 
      }); 
     } 
     else if(cursor == 'erase') { 
      data.$fall.mouseenter(function() { 
       data.$fall = data.$fall.not(this);//manage data.$fall rather than re-form at every call of mm() 
       var $this = $(this).fadeOut('fast', function() { 
        $this.remove(); 
       }); 
      }); 
     }; 
     $canvas.off('mousemove.' + data.name); 
     setTimeout(attachMouseMoveHandler, 50);//adjust delay up/down to optimise performance 
    } 
}); 

Испытано только синтаксис

мне пришлось сделать ряд предположений, главным образом относительно того, что становится фиксированных данных на MouseDown. Эти допущения могут быть неверными, поэтому вам, вероятно, еще предстоит сделать какую-то работу, но пока вы работаете в общей структуре выше, есть хорошие шансы, что ваши проблемы с производительностью исчезнут.

+0

+1, отличное объяснение и код кажутся очень многообещающими, но когда я попытался реализовать его в своем jsfiddle, он сломал скрипку ... может быть, я ошибаюсь? –

+0

Я только что сделал небольшой, но потенциально значительный мод для кода в ответе. 'data. $ fall.add' теперь считывает' данные. $ fall = data. $ fall.add (... '. Если это не исправляет скрипку, тогда мне нужно будет увидеть, как это судить о том, что –

+0

Я связал jsfiddle, показывая все в вопросе ... вот jsfiddle, используя ваш код, который работает: http://jsfiddle.net/xyuBJ/1/ ... когда вы их сравниваете, ваш ходит меньше, но намного хуже при рисовании, если вы не удалите задержку ... но тогда это добавляет лаг ... это возможно? –

Смежные вопросы