gpt4 book ai didi

javascript - Html5 Canvas Bezier 上的虚线曲线

转载 作者:数据小太阳 更新时间:2023-10-29 04:12:00 60 4
gpt4 key购买 nike

对于我的一个应用程序,我需要在 Html5 Canvas 中的贝塞尔曲线路径上绘制虚线曲线...破折号的长度和中间的间隙应该是可变的...它可以在 JavaFx 中实现,see this link ...我想使用 Html5 Canvas 实现相同的效果。我知道如何绘制直线虚线,但不知道如何沿着贝塞尔曲线绘制曲线...

虽然我不是专家,但我知道bezier drawing algorithm ,我看到这个算法的问题是,它允许您使用范围从 0 到 1 的时间参数来识别贝塞尔曲线上的坐标...

这还不够,因为要绘制虚线贝塞尔曲线,我需要在主要贝塞尔曲线路径上绘制许多具有指定长度参数和给定间隙距离的小贝塞尔曲线。 JavaFx 必须使用某种算法。如果有人能帮助我,那就太好了。

最佳答案

我假设 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(),有时会产生 AA 伪像。过滤掉亚像素距离坐标并不难,但生成比实际需要更多的“顶点”效率低下。想出一个更好的步长实际上是我考虑进行更多分析性攻击的事情。

使用这种方法有一个好处:如果您将 bezier(controlPoints, t) 替换为任何其他计算为曲线的东西,您将绘制任何虚线!-- 再次使用上一段中列出的相同潜在问题。但是对于粒度问题的真正好的解决方案可能适用于所有“行为良好”的曲线。

关于javascript - Html5 Canvas Bezier 上的虚线曲线,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7352769/

60 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com