填充复杂形状(绘制线条)

时间:2013-01-02 23:31:04

标签: canvas html5-canvas

我们在这里看到的填充效果http://hakim.se/experiments/html5/coil/非常惊人。我甚至无法猜测任何类似填充的方式(在绘制你的时候关闭形状会看到你正在创建填充的封闭形状)可能会起作用。

请问任何想法?

3 个答案:

答案 0 :(得分:6)

听起来你正在寻找整体的高级流程。如果不对该站点使用的方法进行逆向工程,我可以考虑这样做。

从鼠标当前位置的一个点开始。经常这样,

  1. 从鼠标的上一个位置绘制一个线段到鼠标的当前位置。
  2. 删除太旧的线段。
  3. 如果新线段与任何现有线段相交(Google“检测线段交叉点”或类似物),请将它们分开到它们相交的点(搜索“算法”在十字路口的分割线段“可能会让你到那里”

    假设您从

    开始
       o----o
        \
         \     o
          \   /
           \ /
            o
    

    并从右侧的点添加一个段,向左延伸:

       o----o
        \
    o----------o
          \   /
           \ /
            o
    

    请注意,新细分与现有细分细分相交。在交叉点拆分它们:

       o----o
        \
    o----o-----o
          \   /
           \ /
            o
    

    请注意,o表示线段的结尾。我们已经从四个片段(其中两个片段相交)变为六个片段,其中四个片段具有共同点。

    这些步骤将为您提供连续的线段跟踪。现在让我们弄清楚它们是否形成一个多边形:

  4. 通过每个线段端到端地进行步骤。标识在多个不相邻的段之间共享的线段的第一个 end 。找到结束后,将所有线段绘制到该点:

       ●----●
        \
         ●
    
  5. 从另一端开始,做同样的事情。

       o----o
        \
    ●----●
    
  6. 所有剩余的线段都是多边形的一部分。现在,画布上的draw the enclosed polygon

       o----o
        \
    o----●-----●
          \.../
           \./
            ●
    
  7. 最后是时候弄清楚多边形中包含哪些圆圈了。使用上面实际形成多边形的段列表,使用“算法点在多边形内”等搜索点击网页。

答案 1 :(得分:1)

您基本上是在绘制折线(OpenGL术语中的线条)。有三个关键问题:

  • 如何测试您是否已关闭折线。
  • 一旦确定有闭合折线,如何获得闭合折线。
  • 如何光栅化闭合折线以获得填充的形状。

对于第一个问题,你可以(粗略地说,虽然它在实践中会有点繁琐)存储你在绘制折线时所点击的像素序列,然后当你绘制的线的当前位点击某些东西时停止你提前画了。 (在游戏中,线条的旧位会在一段时间后过期 - 这可以通过存储像素的时间值来建模,并在它们的年龄大于某个阈值时将其移除。)

对于第二个问题,您只需将像素序列的一部分保留在起点和终点之间。

如果你想要做得很好(第三个问题有点困难)(有许多“令人愉快的”特殊情况) - 搜索“多边形光栅化”并做好相当多的阅读准备。我曾经写过一些代码来实现它,这就是它的价值所在:

https://github.com/sgolodetz/millipede/blob/master/trunk/source/common/graphics/PolylineRasterizer.cpp

请注意,在实践中,所有这些都可能比我在这里描述的更加繁琐 - 但是这些方面的内容大致与你如何去做。

答案 2 :(得分:0)

使用开始路径http://www.html5canvastutorials.com/tutorials/html5-canvas-shape-fill/

<!DOCTYPE HTML>
<html>
<head>
<style>
  body {
    margin: 0px;
    padding: 0px;
  }
</style>
</head>
<body>
<canvas id="myCanvas" width="578" height="200"></canvas>
<script>
  var canvas = document.getElementById('myCanvas');
  var context = canvas.getContext('2d');

  // begin custom shape
  context.beginPath();
  context.moveTo(170, 80);
  context.bezierCurveTo(130, 100, 130, 150, 230, 150);
  context.bezierCurveTo(250, 180, 320, 180, 340, 150);
  context.bezierCurveTo(420, 150, 420, 120, 390, 100);
  context.bezierCurveTo(430, 40, 370, 30, 340, 50);
  context.bezierCurveTo(320, 5, 250, 20, 250, 50);
  context.bezierCurveTo(200, 5, 150, 20, 170, 80);

  // complete custom shape
  context.closePath();
  context.lineWidth = 5;
  context.fillStyle = '#8ED6FF';
  context.fill();
  context.strokeStyle = 'blue';
  context.stroke();
</script>
</body>
</html>