【问题标题】:Seamless drawing in multiple canvas在多个画布中无缝绘图
【发布时间】:2010-10-28 23:11:53
【问题描述】:

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

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

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

【问题讨论】:

  • 这非常非常奇怪。我在我的 jsfiddle 上遇到了更不可能的问题。我会及时通知您我取得的任何进展。

标签: javascript jquery html canvas


【解决方案1】:

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

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

固定版本在这里:

http://jsfiddle.net/CVFv5/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();

现在它可以工作了。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-10-26
    • 2018-07-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多