在多个画布中无缝绘图 [英] Seamless drawing in multiple canvas
问题描述
我正在尝试使用JS和Canvas元素制作一个简单的绘图工具.我的问题是我想拥有多个画布,并且用户应该能够通过所有画布画一条线.这是我做的一小页:
I'm trying to make a simple drawing tool using JS and Canvas element. My problem is that I would like to have several canvases and user should be able to draw one line through all of them. Here's a little page I did:
<!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>
部分起作用:我只能在第一个画布中绘制. 我对其进行了调试,并感到非常困惑,因为上下文按预期进行了更改,并且仅在第一个画布中启用了绘制.
And it partially works: I can draw only in the first canvas. I debugged it and i got really confused, because the context changes as expected and drawing is enabled only in the first canvas.
任何想法都是这种行为的原因吗?
Any ideas what's the cause of such behavior?
推荐答案
好的,我找到了问题的根源.原始文件在这里:
OK, I've found the source of the problem. The original is here:
固定版本在这里:
基本上,问题在于您没有正确计算X和Y变量. .offsetX
和.offsetY
计算相对于元素直接祖先的x和y位置(在本例中为页面的主体).您可以通过在鼠标悬停时提醒x和y值来查看此情况.无论如何,您要做的是:
Basically, the issue was that you weren't calculating your X and Y vars correctly. .offsetX
and .offsetY
calculate the x and y position relative to the element's direct ancestor (which in this case was the body of the page). You can see this by alerting the x and y values on mouseover. Anyway, what you have to do instead is this:
var o = $(this).offset(),
x = (ev.pageX - o.left),
y = (ev.pageY - o.top);
您的代码中还有其他一些我已更改的问题.首先,您并没有为每个画布开始新的路径,所以当您重新进入画布时,它将从行中断处开始lineTo(x, y)
.为了解决这个问题,我使您的mouseout事件看起来像这样:
There were also a few other problems with your code that I've changed. First of all, you weren't beginning new paths for each canvas, so when you re-entered the canvas, it would lineTo(x, y)
from where the line had left off. In order to solve this, I made your mouseout event look like this:
.mouseout(function() {
c=false;
})
现在,无论何时进入新画布,它将开始一个新路径.
Now it will begin a new path whenever it enters a new canvas.
我更改的第三件事是使其变为仅在准备好文档时一次创建上下文 .我想这可以节省一些处理.所以我在全局范围内添加了这一行:
The third thing I changed was to make it so that it only creates the contexts once on document ready. I imagine this saves a little bit of processing. So I added this line in the global scope:
var contexts = [];
$('.can')
方法链中的此方法:
.each(function(el) {
id = this.id;
contexts[id] = this.getContext('2d');
})
因此,在代码的其他任何地方,您都可以像这样引用它:
So everywhere else in your code, you can reference it like this:
contexts[this.id].beginPath();
现在可以使用了.
这篇关于在多个画布中无缝绘图的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!