【问题标题】:How to create a circular "brush tip" in HTML5 canvas drawing application?如何在 HTML5 画布绘图应用程序中创建圆形“画笔笔尖”?
【发布时间】:2011-10-26 04:01:30
【问题描述】:

我正在使用 HTML5 lineTo,但任何大于 1 的笔划都会在线条上创建方形的角(笔划垂直于您绘制的线条的路径延伸)。我想创建一个圆形画笔笔尖,类似于http://muro.deviantart.com

有什么想法吗?

【问题讨论】:

  • 你看过ctx.lineCap - 也许这就是你所追求的。

标签: html canvas drawing


【解决方案1】:

可以通过设置线帽来圆角。

ctx.lineCap = "round"

您还可以将贝塞尔曲线应用于整体线条以创建更平滑的整体线条,对于线条中的每个点 P'0, ..., P'n + 1 ,应用等式 P'k = (k/(n+1))Pk-1+(1-(k/(n+1 )))Pk[注意:您最好通过设置阈值来选择应用贝塞尔曲线平滑的点,可能是 P 之间的角度n 和 Pn+1]

将这两种技术与线条本身的标准框模糊相结合,将使您的线条看起来更加平滑。

编辑

据我所知,实际上有很多方法可以做到这一点——您使用哪种方法完全取决于您。我给你一个例子,让你决定:假设你有一条从起点 pm (mousedown) 到终点 (mouseup) pn 的路径.该路径由子路径(由斜接连接的点)组成。我们可以像往常一样使用 lineTo() 和 stroke() 绘制从 p0 到 p1 的上下文路径。仅从控制台输出来看,子路径连接的点就是 mousemove 事件触发。将这些点按顺序记录在一个数组中。

当然,如果我们将它绘制到主上下文中,我们会遇到删除它的问题,因此应该对缓冲区上下文(例如,附加的画布元素)执行此操作。缓冲区被清除,我们使用斜接点来计算曲线。 bezierCurveTo 打印三次函数 (B(t) = (1-t)3P0+3(1-t)2P1+3(1-t)t2P2+t3P3, t ∈ [0,1]. 遍历你的数组(想想循环)用这些点重新计算线,将曲线从 P0 更新到 Pn-3.(快速进行头脑计算。您可能需要考虑这个端点。所有这些都取决于您使用的弧形方程)。

所以让我看看我能不能用这个做点什么......我没有测试它,所以我保证有错误。

// Assume:
// bfr = buffer context.
// ctx = main context.
// md = boolean value for mousedown
// pts = []; <-- already contains lp (below) at pts[0];
// We've also recorded Pm in associative array lp [last point]
// Draw is fired on mousemove. Mousemove records a current point in associative array cp
draw = function() {
  if(md) {
      bfr.beginPath();
      bfr.moveTo(lp.x-.5, lp.y-.5);
      bfr.lineTo(cp.x-.5, cp.y-.5);
      pts.push({cp.x, cp.y});
      bfr.stroke();
  }
}

// Optionally, you could make this function recursive.
// This assumes that you want to estimate the curve based on the whole line.
bezier = function(pts) {
  ctx.beginPath();
  ctx.moveTo(pts[0].x, pts[0].y);
  for( var i = 0; i < pts.length - 3; i++ ) {
    ctx.bezierCurveTo( pts[i+1].x, pts[i+1].y, pts[i+2].x, pts[i+2].y, pts[i+3].x, pts[i+3].y);
  }
  ctx.stroke();
}

再一次,这就是我所看到的——其他人可能有完全不同的看法,我相信会有更好的解释。我正在尝试将我所做的大量事情撕掉,并快速将它们与一些新代码组合在一起,以便为您提供一些想法。

【讨论】:

  • 关于 lineCap 工作的提示。谢谢。关于贝塞尔曲线......我该如何“应用”方程?在计算每个点 P 之后我是否只使用 lineTo ?我找到了 quadraticCurveTo 函数和贝塞尔版本,但它们只需要 3 或 4 个输入点。如何将贝塞尔曲线应用到整个笔触?
  • 我会写一个自定义函数。选择记录到数组的样本点,应用曲线。您可以对mousemove 触发的点进行采样,确定三个点之间的角度以检查采样点是否存在显着差异,如果存在则标记它,然后使用它来应用曲线。我会将标记点数组传递给函数以执行评估。始终以 mousedownmouseup 开头,分别为 0 和 n+1。
  • 假设用户画了一个快速的圆,但样本点的分布更像八角形的角。您建议使用某种自定义函数 bezierLine(sample_points) 来“弯曲”这条线,对吗?我不明白该功能会发生什么?该函数是否通过计算每个像素坐标来绘制每个像素?或者该函数是否为 Bezier(t) 遍历采用 t 步参数,在这种情况下,该函数最终仍使用 lineTo 绘制一条线,对吗?
  • 实际上,您确实有一个很好的观点 - 您可以将其应用为 quadraticCurveTo、bezierCurveTo 或 arcTo... 我想我可能偶然发现了一些东西,所以让我检查一下并返回你很快。
  • 谢谢。我最终找到了一个解决方案来制作更流畅的线条,我在这里发布了:stackoverflow.com/questions/7054272/… 到目前为止我对它感到满意。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-02-19
  • 2014-08-30
  • 1970-01-01
相关资源
最近更新 更多