我正在尝试使用JS和Canvas元素制作一个简单的绘图工具。我的问题是我希望有几个画布,用户应该能够在所有画布中画一条线。这是我做的一个小页面:
<!DOCTYPE html>
<html>
<head>
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.4.3/jquery.min.js"></script>
<script type="text/javascript">
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);
</script>
<style>
.can {border: 1px solid blue; display:block; float:left; margin:0;}
</style>
</head>
<body>
<canvas class="can" id="c2" width="200" height="200"></canvas>
<canvas class="can" id="c1" width="200" height="200"></canvas>
<canvas class="can" id="c3" width="200" height="200"></canvas>
</body>
</html>
它部分有效:我只能在第一个画布上画画。 我调试了它,我真的很困惑,因为上下文按预期更改,并且只在第一个画布中启用了绘图。
任何想法是什么原因造成这种行为?
答案 0 :(得分:3)
好的,我找到了问题的根源。原文在这里:
固定版本在这里:
基本上,问题在于您没有正确计算X和Y变量。 .offsetX
和.offsetY
计算相对于元素的直接祖先(在本例中是页面正文)的x和y位置。您可以通过在鼠标悬停时警告x和y值来查看此信息。无论如何,你需要做的是:
var o = $(this).offset(),
x = (ev.pageX - o.left),
y = (ev.pageY - o.top);
我的代码还有一些其他问题我已经改变了。首先,你没有为每个画布开始新的路径,所以当你重新进入画布时,它会从行停止的地方lineTo(x, y)
开始。为了解决这个问题,我让你的mouseout事件看起来像这样:
.mouseout(function() {
c=false;
})
现在,无论何时进入新画布,它都会开始一条新路径。
我改变的第三件事是使它只在文档就绪时创建一次的上下文。我想这可以节省一些处理。所以我在全球范围内添加了这一行:
var contexts = [];
此方法在您的$('.can')
方法链中:
.each(function(el) {
id = this.id;
contexts[id] = this.getContext('2d');
})
因此,代码中的其他任何地方都可以像这样引用它:
contexts[this.id].beginPath();
现在它有效。