Javascript 帆布“;“随机”;曲线形状
我想在画布上画一个看起来随机的曲线斑点,但我似乎无法想出一个算法来做到这一点。我尝试过创建如下随机贝塞尔曲线:Javascript 帆布“;“随机”;曲线形状,javascript,algorithm,drawing,html5-canvas,Javascript,Algorithm,Drawing,Html5 Canvas,我想在画布上画一个看起来随机的曲线斑点,但我似乎无法想出一个算法来做到这一点。我尝试过创建如下随机贝塞尔曲线: context.beginPath(); // Each shape should be made up of between three and six curves var i = random(3, 6); var startPos = { x : random(0, canvas.width), y : random(0, canvas.height) }; c
context.beginPath();
// Each shape should be made up of between three and six curves
var i = random(3, 6);
var startPos = {
x : random(0, canvas.width),
y : random(0, canvas.height)
};
context.moveTo(startPos.x, startPos.y);
while (i--) {
angle = random(0, 360);
// each line shouldn't be too long
length = random(0, canvas.width / 5);
endPos = getLineEndPoint(startPos, length, angle);
bezier1Angle = random(angle - 90, angle + 90) % 360;
bezier2Angle = (180 + random(angle - 90, angle + 90)) % 360;
bezier1Length = random(0, length / 2);
bezier2Length = random(0, length / 2);
bezier1Pos = getLineEndPoint(startPos, bezier1Length, bezier1Angle);
bezier2Pos = getLineEndPoint(endPos, bezier2Length, bezier2Angle);
context.bezierCurveTo(
bezier1Pos.x, bezier1Pos.y
bezier2Pos.x, bezier2Pos.y
endPos.x, endPos.y
);
startPos = endPos;
}
(这是一种简化……我添加了一些限制行在画布内的位,等等)
这样做的问题是让它回到起点,而且不仅仅是制造大量尴尬的弯道。有人知道更好的算法吗,或者能想出一个更好的算法吗
编辑:我取得了一些进展。我又开始了,用直线工作(我想我知道一旦我完成了这一点,该怎么做才能把它们变成平滑的贝塞尔曲线)。我将其设置为在绘制每个点之前,计算出从上一点到起点的距离和角度。如果距离小于一定量,则闭合曲线。否则,可能的角度会根据迭代次数而变窄,最大线长度是到起点的距离。这里有一些代码
start = {
// start somewhere within the canvas element
x: random(canvas.width),
y: random(canvas.height)
};
context.moveTo(start.x, start.y);
prev = {};
prev.length = random(minLineLength, maxLineLength);
prev.angle = random(360);
prev.x = start.x + prev.length * Math.cos(prev.angle);
prev.y = start.y + prev.length * Math.sin(prev.angle);
j = 1;
keepGoing = true;
while (keepGoing) {
j++;
distanceBackToStart = Math.round(
Math.sqrt(Math.pow(prev.x - start.x, 2) + Math.pow(prev.y - start.y, 2)));
angleBackToStart = (Math.atan((prev.y - start.y) / (prev.x - start.x)) * 180 / Math.pi) % 360;
if (isNaN(angleBackToStart)) {
angleBackToStart = random(360);
}
current = {};
if (distanceBackToStart > minLineLength) {
current.length = random(minLineLength, distanceBackToStart);
current.angle = random(angleBackToStart - 90 / j, angleBackToStart + 90 / j) % 360;
current.x = prev.x + current.length * Math.cos(current.angle);
current.y = prev.y + current.length * Math.sin(current.angle);
prev = current;
} else {
// if there's only a short distance back to the start, join up the curve
current.length = distanceBackToStart;
current.angle = angleBackToStart;
current.x = start.x;
current.y = start.y;
keepGoing = false;
}
context.lineTo(current.x, current.y);
}
console.log('Shape complexity: ' + j);
context.closePath();
context.fillStyle = 'black';
context.shadowColor = 'black';
context.shadowOffsetX = -xOffset;
context.shadowOffsetY = -yOffset;
context.shadowBlur = 50;
context.fill();
我现在遇到的问题是,形状的轮廓经常与自身交叉,这看起来是错误的。我能想到的解决这个问题的唯一方法是跟踪一个边界框,并且每个新点都应该始终指向边界框之外。这很棘手,因为计算可用角度会增加整个复杂程度。一种可能是使用极坐标,并将半径作为角度的函数。对于平滑斑点,您希望半径平滑,并且在0和2*pi处具有相同的值,这可以使用三角多项式完成:
radius(theta) = a_0 + a_1*sin(theta) + a_2*sin(2*theta) + ... + b_1*cos(theta) + ...
其中系数为“随机”。要控制半径的大小,可以搜索半径函数的最大值和最小值,然后适当地移动和缩放系数(也就是说,如果你愿意,你应该发布一个完整的HTML页面,内嵌JavaScript。这是一个JSFIDLE,其中包含他的代码:谢谢@Fantius。查看我的编辑以获得进度更新。谢谢@JamesClark,我已经用我的更新更新了链接:这是一个了不起的主意!我将玩一玩,然后看看我是否能找到工作。