所以我正在编写一种绘图脚本,现在它运行良好(尽管代码仍然需要清理并且需要更多功能),但是当绘制太多时,mousemove
令人难以置信地滞后。这是主要的 Javascript:
$('#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
上 append 足够的内容,从而导致(我认为)DOM 被淹没。
问题:
在不产生延迟的情况下向 DOM 添加许多 div 的有效方法是什么?这可能吗?
注意:
这是一个个人项目,我对使用以前创建的绘图 API 不感兴趣
最佳答案
您可以采取很多措施来提高性能。
下面的代码是对问题中代码的大量重构。乍一看,它的效率似乎较低,因为它的行数大约是原始的两倍。然而,行数不是这里的问题。适用两个基本原则:
- 在 mousemove 处理程序中尽可能少地进行 DOM 交互,并在 mousedown 上尽可能多地进行 DOM 交互。
- 包含一个“除法器电路”来限制调用 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 上的固定数据。这些假设可能是不正确的,因此您很可能仍然需要做一些工作,但只要您在上面的整体框架内工作,您的性能问题很可能就会消失。
关于javascript - 防止 DOM 中的滞后,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17266000/