在多个canvas的无缝绘图

我正在尝试使用JS和Canvas元素制作一个简单的绘图工具。 我的问题是我希望有几个canvas,用户应该能够通过所有canvas画一条线。 这是我做的一个小页面:

     var act = null; var context = null; var draw = false; var c = false; function boot() { $('.can') .mouseenter(function(){ act = this; context = act.getContext('2d'); // console.log(this); }) .mouseleave(function(){ act = null; context = null; // console.log('out'); }) .mousedown(function(){ draw = true; }) .mouseup(function(){ draw = false; }) .mousemove(function(ev){ // console.log(act); if (ev.layerX || ev.layerX == 0) { // Firefox x = ev.layerX; y = ev.layerY; } else if (ev.offsetX || ev.offsetX == 0) { // Opera x = ev.offsetX; y = ev.offsetY; } if(draw && context != null) if (!c) { context.beginPath(); context.moveTo(x, y); c = true; } else { context.lineTo(x, y); context.stroke(); } }); } $(document).ready(boot);   .can {border: 1px solid blue; display:block; float:left; margin:0;}         

它部分起作用:我只能在第一个canvas上绘制。 我调试它,我真的很困惑,因为上下文按预期更改,并且仅在第一个canvas中启用绘图。

任何想法是什么导致这种行为?

好的,我找到了问题的根源。 原文在这里:

http://jsfiddle.net/CVFv5/4/

固定版本在这里:

http://jsfiddle.net/CVFv5/3/

基本上,问题是你没有正确计算你的X和Y变量。 .offsetX.offsetY计算相对于元素的直接祖先的x和y位置(在本例中是页面的主体)。 你可以通过在mouseover上警告x和y值来看到这一点。 无论如何,你需要做的是:

 var o = $(this).offset(), x = (ev.pageX - o.left), y = (ev.pageY - o.top); 

我的代码还有一些其他问题我已经改变了。 首先,你没有为每个canvas开始新的路径,所以当你重新进入canvas时,它会从行离开的地方开始行lineTo(x, y) 。 为了解决这个问题,我让你的mouseout事件看起来像这样:

 .mouseout(function() { c=false; }) 

现在,只要它进入新canvas,它就会开始一条新路径。

我改变的第三件事是使它只在文档就绪时创建一次上下文。 我想这可以节省一些处理。 所以我在全球范围内添加了这一行:

 var contexts = []; 

这个方法在你的$('.can')方法链中:

 .each(function(el) { id = this.id; contexts[id] = this.getContext('2d'); }) 

所以在你的代码中的其他地方,你可以像这样引用它:

 contexts[this.id].beginPath(); 

现在它有效。