我要假定,贾瓦尼亚正在利用一种一般技术来绘制任何 da的曲线,而且恰如其分地利用它。
The hard part is figuring out where to start and stop each dash, which requires knowing the arc length of your bezier curve at various points along it.
There is an analytic approach, but I would suggest the following:
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();
};
这种做法的主要问题是它不明智的贪 gr。 如果对你(小)的 da或(大)的 cur子来说,步骤规模不会奏效,干.的边界不会完全落到你想要的地处。 当步骤太小时,您可以最终完成<条码>To(<>>>>> > /条码> ,其位置是距离另一条次的距离,有时是AAA工艺品。 脱硫线距离坐标不是硬的,但产生比你真正需要的更高的vert却效率不高。 规模越大,实际上我更想从分析的角度加以攻击。
There is one bonus to using this approach: if you replace bezier(controlPoints, t)
with anything else that evaluates to a curve, you ll be drawing dashed whatevers!-- again with the same potential problems listed in the previous paragraph. But a really good solution to the granularity problem could work for all well-behaved curves.