1

我们可以在这里看到的填充效果http://hakim.se/experiments/html5/coil/是相当惊人的。我什至无法猜测这样的填充(在绘制时关闭形状,您会看到您正在创建闭合形状的填充)如何工作..

有什么想法吗?

4

3 回答 3

6

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

从鼠标当前位置的一个点开始。每隔一段时间,

  1. 从鼠标的先前位置到鼠标的当前位置绘制一条线段。
  2. 删除太旧的线段。
  3. 如果新线段与任何现有线段相交(谷歌“检测线段相交”或类似的),在它们相交的点分割它们(搜索“算法在相交处分割线段”可能会让你到达那里)

    假设您从

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

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

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

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

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

    注意o表示线段的结束。我们已经从四个线段(其中两个相交)到六个线段,其中四个共享一个公共点。

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

  4. 端到端地遍历每个线段。识别在多个非相邻线段之间共享的线段的第一端。找到终点后,将所有线段绘制到该点:

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

       o----o
        \
    ●----●
    
  6. 所有剩余的线段都是多边形的一部分。现在,在画布上绘制封闭的多边形。

       o----o
        \
    o----●-----●
          \.../
           \./
            ●
    
  7. 最后,是时候确定多边形中包含哪些圆了。借助上面实际形成多边形的线段列表,在网上搜索“算法点在多边形内”之类的搜索。

于 2013-01-03T00:28:26.867 回答
1

你基本上是在画一条折线(一条线,在 OpenGL 术语中)。存在三个关键问题:

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

对于第一个问题,您可以(粗略地说,尽管在实践中会有点繁琐)存储您在绘制多段线时遇到的像素序列,然后在您正在绘制的当前位遇到您之前绘制的东西时停止. (在游戏中,线的旧位会在一段时间后过期 - 这可以通过存储像素的时间值并在它们的年龄大于某个阈值时移除它们来建模。)

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

如果你想稳健地完成第三个问题(有很多“令人愉快”的特殊情况),第三个问题会有些困难 - 搜索“多边形光栅化”并准备好阅读大量内容。我曾经写了一些代码来做到这一点,这是在这里,它的价值:

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

请注意,在实践中,所有这些都可能比我在这里描述的要复杂得多——但沿着这些思路大致就是你可能会如何去做。

于 2013-01-02T23:53:21.643 回答
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>
于 2013-09-27T15:17:15.397 回答