在多个画布中无缝绘图 [英] Seamless drawing in multiple canvas

查看:103
本文介绍了在多个画布中无缝绘图的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用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:

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

固定版本在这里:

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

基本上,问题在于您没有正确计算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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆