2013-02-28 21 views
0

我试图在Canvas中用Canvas作为渲染器在Dojo的gfx中实现橡皮筋选择框。我的意图是在鼠标点击并拖动时绘制选择框,然后在释放鼠标后消失。不幸的是我遇到了一个问题。Dojo gfx:onmousemove连接到一个形状clobbering onmouseup?

的jsfiddle例如:http://jsfiddle.net/7F9fy/

的主要问题是在某处的OnMouseMove(或与其相关的):

whiteRect.connect("onmousemove",function(e) { 
    if(isMouseDown) { 
     if(whiteRect.groupSelector_) { 
      pStat.innerHTML = "dragging..."; 
      console.debug("dragging..."); 
      e.stopImmediatePropagation(); 
      e.preventDefault(); 
      var ex = (e.x ? e.x : e.clientX); 
      var ey = (e.y ? e.y : e.clientY);     

      if(groupSelector) { 
       // Also tried getShape, editing that shape, and setShape on groupSelector--same 
       // behavior, though.      
       var rectX = (ex - cnvDiv.offsetLeft < whiteRect.groupSelector_.x ? ex - cnvDiv.offsetLeft : whiteRect.groupSelector_.x); 
       var rectY = (ey - cnvDiv.offsetTop < whiteRect.groupSelector_.y ? ey - cnvDiv.offsetTop : whiteRect.groupSelector_.y); 

       surface.remove(groupSelector); 
       groupSelector = surface.createRect({ 
        x: rectX, 
        y: rectY, 
        width: Math.abs(ex - cnvDiv.offsetLeft - whiteRect.groupSelector_.x), 
        height: Math.abs(ey - cnvDiv.offsetTop - whiteRect.groupSelector_.y) 
       }).setStroke({color: "blue", width: 3}); 

      } else { 
       groupSelector = surface.createRect({ 
        x: whiteRect.groupSelector_.x, 
        y: whiteRect.groupSelector_.y, 
        width: Math.abs(ex - cnvDiv.offsetLeft - whiteRect.groupSelector_.x), 
        height: Math.abs(ey - cnvDiv.offsetTop - whiteRect.groupSelector_.y) 
       }).setStroke({color: "blue", width: 3}); 
      } 
      e.stopPropagation(); 
     } 
    } 
}); 

如果我按住形状/组中的鼠标左键(白色正方形在上面的例子中),我的鼠标事件连接到并开始拖动,框开始绘制,跟随我的拖动。当我释放鼠标时,有时候框会消失,有时它不会。如果没有,盒子会不断被绘制,并按照鼠标移动的方式进行拖动。

在jsFiddle中,如果您在画布下观看console.debug或段落记者,您会发现有时,当您释放鼠标时,onmouseup不会触发(我也检查过mouseup,但那有同样的问题)。在onmouseup从不发射的情况下,onmousemove继续发射。如果再次点击,有时会点击一个完整的鼠标点击(向下,向上,点击和移动),然后使绘制的矩形消失。但有时候这并不会发生,而且onmousemove一直在开火。如果在拖动/ onmousemove变为'卡住'并且没有任何事情发生后单击,则没有调试行或针对这些事件对记录进行更改,因此就像除了onmousemove之外的所有鼠标事件都被压制一样。我尝试添加stopPropagation,stopImmediatePropagation和preventDefault,但这没有帮助。我也尝试使用Dojo事件的停止,但这并没有改变行为。

为了重新绘制onmousemove中的框,我尝试了'getShape - >编辑属性 - > setShape'以及删除形状并制作一个全新的形状;这些方法都不能阻止这个问题,它们之间没有任何明显的区别。

我使用的是Dojo 1.8.3,这种情况发生在Chrome(v25)和Firefox(v19)中,Canvas或SVG作为渲染器。

想法?我在这里错过了很明显的东西吗

回答

0

排序出来。问题是onmouseup事件,当你决定停止拖出形状时,可能触发底层/连接形状,或拖动形状。它是随机的,取决于光标的位置,但如果拖动没有偏移或延迟,则偏好绘制的形状。 (dojox/gfx中的Moveable.js和Mover.js指向正确的方向。)

我在尝试使它工作的过程中将我的盒子更改为路径,而且这似乎表现更好,但isn没有必要。

关键是制作一个'onMouseUp'函数,然后从原始形状的onmouseup以及拖动形状的onmouseup中调用该函数。我的例子很sl,,但我希望它能得到重点。

的jsfiddle:http://jsfiddle.net/n3KGY/1/

关键代码:

// General method to clear out a selector if 
// one was being drawn. 
var selectorMouseUp = function(e) { 
    reporter.innerHTML = "onmouseup"; 
    isMouseDown = false; 
    whiteRect.groupSelector_ = null; 
    if(groupSelector) { 
     if(selectorUp) { 
      groupSelector.disconnect(selectorUp); 
     }    
     surface.remove(groupSelector); 
     groupSelector = null; 
    } 
    e.stopImmediatePropagation(); 
    e.stopPropagation(); 
    e.preventDefault(); 
}; 

// Mouseup event for the background/workspace 
whiteRect.connect("onmouseup",function(e){ 
    selectorMouseUp(e); 
}); 

// Make a selector as a path on the surface 
// and attach a mouseup to it 
var makeSelector = function(x,y,w,h) { 
    groupSelector = surface.createPath() 
     .moveTo(x,y) 
     .hLineTo(x+w).vLineTo(y+h).hLineTo(x).vLineTo(y) 
     .setStroke({color: "blue", width: 3}) 
     .closePath(); 
    // Attach the same mouseup method as the workspace/background 
    selectorUp = groupSelector.connect("onmouseup",function(e){ 
     reporter.innerHTML = "onmouseup (selector)"; 
     selectorMouseUp(e); 
    });   
}; 

bigRect.connect("onmousemove",function(e){ 
    if(isMouseDown) { 
     if(bigRect.groupSelector_) { 
      var ex = e.clientX; 
      var ey = e.clientY; 

      reporter.innerHTML = "dragging at " + ex+","+ey; 

      var downX = bigRect.groupSelector_.x; 
      var downY = bigRect.groupSelector_.y; 
      var leadingX = (ex - grn.offsetLeft < downX ? ex - grn.offsetLeft : downX); 
      var leadingY = (ey - grn.offsetTop < downY ? ey - grn.offsetTop : downY); 
      var selWidth = Math.abs(ex - grn.offsetLeft - downX); 
      var selHeight = Math.abs(ey - grn.offsetTop - downY); 

      if(groupSelector) { 
       // If there's already a selector being drawn, get rid of it. 
       groupSelector.disconnect(selectorUp); 
       surface.remove(groupSelector); 
      } 
      // Draw the current selector 
      makeSelector(leadingX,leadingY,selWidth,selHeight); 
      e.stopImmediatePropagation(); 
      e.stopPropagation(); 
      e.preventDefault(); 
     } 
    } 
});