html 直线变曲线,javascript – Html5 Canvas Bezier上的虚线曲线

我认为JavaFX正在使用一般技术绘制任何虚线曲线,恰好在该示例中恰好在贝塞尔曲线上使用它.

困难的部分是确定从哪里开始和停止每个破折号,这需要在沿着它的各个点知道你的贝塞尔曲线的arc length.

有一种分析方法,但我建议如下:

var bezier = function(controlPoints, t) {

/* your code here, I'll presume it returns a 2-element array of x and y. */

};

//just figure out the coordinates of all the points in each dash, don't draw.

//returns an array of arrays, each sub-array will have an even number of nu-

//merical elements, to wit, x and y pairs.

//Argument dashPattern should be an array of alternating dash and space

//lengths, e.g., [10, 10] would be dots, [30, 10] would be dashes,

//[30, 10, 10, 10] would be 30-length dash, 10-length spaces, 10-length dash

// and 10-length space.

var calculateDashedBezier = function(controlPoints, dashPattern) {

var step = 0.001; //this really should be set by an intelligent method,

//rather than using a constant, but it serves as an

//example.

//possibly gratuitous helper functions

var delta = function(p0, p1) {

return [p1[0] - p0[0], p1[1] - p0[1]];

};

var arcLength = function(p0, p1) {

var d = delta(p0, p1);

return Math.sqrt(d[0]*d[0] + d[1] * d[1]);

};

var subPaths = [];

var loc = bezier(controlPoints, 0);

var lastLoc = loc;

var dashIndex = 0;

var length = 0;

var thisPath = [];

for(var t = step; t <= 1; t += step) {

loc = bezier(controlPoints, t);

length += arcLength(lastLoc, loc);

lastLoc = loc;

//detect when we come to the end of a dash or space

if(length >= dashPattern[dashIndex]) {

//if we are on a dash, we need to record the path.

if(dashIndex % 2 == 0)

subPaths.push(thisPath);

//go to the next dash or space in the pattern

dashIndex = (dashIndex + 1) % dashPattern.length;

//clear the arclength and path.

thisPath = [];

length = 0;

}

//if we are on a dash and not a space, add a point to the path.

if(dashIndex % 2 == 0) {

thisPath.push(loc[0], loc[1]);

}

}

if(thisPath.length > 0)

subPaths.push(thisPath);

return subPaths;

};

//take output of the previous function and build an appropriate path

var pathParts = function(ctx, pathParts) {

for(var i = 0; i < pathParts.length; i++) {

var part = pathParts[i];

if(part.length > 0)

ctx.moveTo(part[0], part[1]);

for(var j = 1; j < part.length / 2; j++) {

ctx.lineTo(part[2*j], part[2*j+1]);

}

}

};

//combine the above two functions to actually draw a dashed curve.

var drawDashedBezier = function(ctx, controlPoints, dashPattern) {

var dashes = calculateDashedBezier(controlPoints, dashPattern);

ctx.beginPath();

ctx.strokeStyle = /* ... */

ctx.lineWidth = /* ... */

pathParts(ctx, dashes);

ctx.stroke();

};

这种方法的主要问题是其非智能粒度.当步长对于您的(小)破折号或(大)曲线来说太大时,步长将无法正常工作,并且破折号边界将不会精确地落在您想要的位置.当步长太小时,您可能最终在彼此相距亚像素距离的点上执行lineTo()s,有时会产生AA伪像.过滤掉子像素距离坐标并不难,但生成比实际需要更多的“顶点”效率低下.提出更好的步长实际上是我认为更具分析性的攻击.

使用这种方法有一个好处:如果你将bezier(controlPoints,t)替换为评估曲线的任何其他东西,你将会绘制虚线的whatevers! – 再次出现与前一段中列出的相同的潜在问题.但是,粒度问题的一个非常好的解决方案可以适用于所有“表现良好”的曲线.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值