【问题标题】:Save a reference to a html canvas path保存对 html 画布路径的引用
【发布时间】:2014-01-13 02:26:12
【问题描述】:

我正在处理一些绘制到画布上的代码。代码的一部分在画布上绘制了一些线条。这些线条的位置和颜色不会改变,但它们通常需要重新绘制,因为其他代码可能已经影响了它(例如:绘制在它的顶部)。

可能有几百条线要绘制,在这些情况下,分析显示它需要大约 200 毫秒来绘制,所以我希望对其进行一些优化。

我注意到的一件事是,在画布上绘制时,您基本上是在向路径添加点,然后一旦准备好,您就可以填充或描边该路径。虽然画布上的像素已经过时了,但如果我能够保留对路径的引用,那么更新就像重新绘制之前构建的路径一样简单。

我的问题是:到底如何获得 Path 对象?

填充和描边方法出现在accept a path object,规范定义了methods for Path,但我似乎无法在任何地方找到实际的Path 类...

所以,回顾一下:

我有这样的事情:

function update() {
  context.beginPath();
  // lots of lines added to the default path...
  context.moveTo(x1, y1); context.lineTo(somewhere, else);
  context.moveTo(x2, y2); context.lineTo(somewhere, else);

  context.stroke();
}

我想要的是这样的:

function update() {
  if (!this.path) {
    this.path = new Path(); // <-- here's the magic
    this.path.moveTo(x1, y2); this.path.lineTo(somewhere, else); // etc
  }
  this.path.stroke();
}

【问题讨论】:

    标签: javascript html canvas


    【解决方案1】:

    画布规范需要一个尚未在浏览器中实现的 Path 对象。

    顺便说一句,当实现时,Path 对象在与 context.isPointInPath(myPath) 结合使用时将在命中测试中很有用;总有一天……

    在浏览器赶上之前,您可以创建自己的 Path 对象:

    • 创建一个 JS 对象,其中包含绘制路径笔划的画布。
    • 当您想要执行 myPath.stroke() 时,请使用 myVisibleContext.drawImage(myPath.context,0,0) 将路径的画布“blit”到绘图画布上。

    演示:http://jsfiddle.net/m1erickson/QLJv8/

    代码:

    <!doctype html>
    <html>
    <head>
    <link rel="stylesheet" type="text/css" media="all" href="css/reset.css" /> <!-- reset css -->
    <script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script>
    
    <style>
        body{ background-color: ivory; }
        #canvas{border:1px solid red;}
    </style>
    
    <script>
    $(function(){
    
        var canvas=document.getElementById("canvas");
        var ctx=canvas.getContext("2d");
    
        function Path(maxWidth,maxHeight,color,linewidth,drawingContext){
            this.width=maxWidth;
            this.height=maxHeight;
            this.drawingCtx=drawingContext;
            this.points=[]
            this.canvas=document.createElement("canvas");
            this.canvas.width=maxWidth;
            this.canvas.height=maxHeight;
            this.ctx=this.canvas.getContext("2d");
            this.ctx.strokeStyle=color;
            this.ctx.lineWidth=linewidth;
            this.lastX;
            this.lastY;
        }
        Path.prototype.moveTo=function(x,y){
            this.lastX=x;
            this.lastY=y;
    
        }
        Path.prototype.lineTo=function(x,y){
            this.ctx.moveTo(this.lastX,this.lastY);
            this.ctx.lineTo(x,y);
            this.ctx.stroke();
            this.lastX=x;
            this.lastY=y;
        }
        Path.prototype.stroke=function(){
            this.drawingCtx.drawImage(this.canvas,0,0);
        }
    
        // create a new path object
    
        var p=new Path(300,300,"blue",2,ctx);
    
        // set the Path's drawing commands
    
        p.moveTo(69,91);
        p.lineTo(250,150);
        p.moveTo(69,208);
        p.lineTo(180,54);
        p.lineTo(180,245);
        p.lineTo(69,91);
        p.moveTo(69,208);
        p.lineTo(250,150);
    
        // draw the Path.canvas to the drawing canvas
        p.stroke();
    
        // tests...
    
        $("#stroke").click(function(){
            p.stroke();
        });
        $("#erase").click(function(){
            ctx.clearRect(0,0,canvas.width,canvas.height);
        });
    
    }); // end $(function(){});
    </script>
    
    </head>
    
    <body>
        <button id="stroke">Path.stroke</button><br>
        <button id="erase">Erase main canvas</button><br>
        <canvas id="canvas" width=300 height=300></canvas>
    </body>
    </html>
    

    【讨论】:

    • Path 对象现在在 Chrome Canary 中可用。很快就会出现在常规 Chrome 中。
    • @Ken 想到路径对象可以跨浏览器使用,我脸上露出灿烂的笑容!!!!
    【解决方案2】:

    事实证明,只是没有浏览器支持它,根据这篇博客(2013 年 1 月 24 日)http://www.rgraph.net/blog/2013/january/html5-canvas-path-objects.html

    【讨论】:

    • Chrome Canary 现在支持 Path,并且很快就会出现在常规 Chrome 中(除非他们改变主意)。
    【解决方案3】:

    它们在画布中没有路径支持,但为什么不使用 svg 线并将其 zIndex 设置为在其他之上。

    【讨论】:

      【解决方案4】:

      所有画布绘图 API 都不允许您保存对对象的引用。 Canvas 可让您在位图中绘制像素,而不是像 SVG 那样创建和操作对象。

      如果您希望优化性能并且希望反复重用相同的路径,您可能希望在单独的画布对象中绘制一次,然后使用 drawImage 将该画布绘制到您的另一个画布中(可以将画布作为参数)。

      【讨论】:

      猜你喜欢
      • 2017-08-04
      • 2013-02-08
      • 2021-10-05
      • 2016-07-29
      • 2012-09-23
      • 1970-01-01
      • 2014-02-13
      • 2013-12-12
      • 1970-01-01
      相关资源
      最近更新 更多