围绕 javascript 中的路径制作正弦波曲线
Making a sine wave curve around a path in javascript
我正在尝试寻找一种使正弦波沿着 javascript 路径自然流动的好方法。我做了这样的事情:
它抓住了一些意图,但它非常强迫和不自然,尤其是在改变方向上。我也很想适应更高的坡度,但不确定这是否会产生更自然的效果。
有什么想法可以实现吗?
原意是:
1)取一组积分
2) 分成相等的段
3) 通过正弦坐标与实际直线坐标的差值来调整实际直线的位置
虽然这给出了一个非常弱的显示,但我想创建一些更自然和流畅的东西,就像捕捉沿路径传播的正弦波的流动一样。
var c = document.getElementById("c");
var ctx = c.getContext("2d");
var cw = c.width = window.innerWidth;
var ch = c.height = window.innerHeight;
var cx = cw / 2,
cy = ch / 2;
var rad = Math.PI / 180;
var w = cw;
var h = ch * 0.3;
var amplitude = h;
var frequency = 0.01;
var phi = 0;
var frames = 0;
var stopped = true;
ctx.lineWidth = .4;
var offset = 100;
var points = interpolateLineRange( [ [0, 0], [ 95, 58], [84, 158], [350, 300], [540, 190] ], 20);
points = interpolateLineRange(points, 100);
ctx.moveTo(0, 0);
var distance_traveled = 0;
var current_slope = 0;
for (var ii in points) {
if (ii == 0) {
continue;
}
distance_traveled += dist(points[ii - 1], points[ii]);
current_slope = slope(points[ii - 1], points[ii]);
var newY = Math.sin(distance_traveled * .07) * 45 + points[ii][1];
var diff = newY - points[ii][1];
if (points[ii][1] > points[ii - 1][1]) {
ctx.lineTo(points[ii][0] - diff, newY);
} else {
ctx.lineTo(points[ii][0] + diff, newY);
}
}
ctx.stroke();
ctx.moveTo(0, 0);
for (var ii in points) {
ctx.lineTo(points[ii][0], points[ii][1]);
}
ctx.strokeStyle = 'red';
ctx.stroke();
问题其实并不"drawing sine waves along a path":那部分实际上是微不足道的。取你的路径部分,用距离或时间变量表示,然后绘制正弦(或其他任何东西)作为偏移函数:
for t=0; t<distance; t+=fraction of distance:
point = path.get(t)
normal = path.normal(t)
strength = sin(t)
if t=0:
ctx.moveTo(point + strength * normal)
else:
ctx.lineTo(point + strength * normal)
很简单,让我们来实现它:http://jsbin.com/nefemazovo/edit?js,output
当然,这是一些代码,但它并不复杂:只是一个 class 模拟多边形路径,在我们向其添加点时跟踪其长度,以及一个绘制多边形的绘制函数,以及一些偏移函数,通过定期对多边形进行采样并计算每个点的法线。
真正的问题是:您将如何处理偏移数据中的重叠?例如,从上面的例子:
这里有一个非常明显的区域,我们将不得不做...一些事情:
那我们怎么办?事实证明:没有人知道,这完全取决于您。例如,您可以绘制 "uneven" 正弦曲线,以便始终在多边形截面的端点处有一个节点。可能有效,但如果连续段之间的角度足够小,您也可能仍然有重叠。再加上你的正弦会不均匀,那看起来不错吗?呃……随你。或者,您可以在多边形过渡处将偏移强度衰减到零,然后将其逐渐增加到 100%,但这看起来不错吗?不知道,那是你的电话。您还可以使用插值法,使过渡处的正弦波 "blend"。 那个好看吗?同样,不知道,仍然取决于你。您甚至可以用二次曲线或三次曲线之类的东西替换多边形的违规部分,这样您始终可以平滑过渡,正弦偏移将沿着该过渡 "just work",但这看起来不错吗? ...你明白了 =)
这个问题中我们可以回答的部分不是很有趣,很遗憾我们无法为您回答有趣的部分...
不过我们可以提供建议:我不知道你的多边形代表什么,但 "curves" 几乎总是作为脊柱工作得更好(几乎,因为曲线 可以 也有不连续性,这是你想要避免的事情),所以如果你可以构建曲线,那可能是值得的。但是,不会解决角度太小时奇怪的重叠问题:
您仍然面临着 "executive decisions" 比教科书 "in this situation, do this: ..." 解决方案更多的问题。
我正在尝试寻找一种使正弦波沿着 javascript 路径自然流动的好方法。我做了这样的事情:
它抓住了一些意图,但它非常强迫和不自然,尤其是在改变方向上。我也很想适应更高的坡度,但不确定这是否会产生更自然的效果。
有什么想法可以实现吗?
原意是:
1)取一组积分
2) 分成相等的段
3) 通过正弦坐标与实际直线坐标的差值来调整实际直线的位置
虽然这给出了一个非常弱的显示,但我想创建一些更自然和流畅的东西,就像捕捉沿路径传播的正弦波的流动一样。
var c = document.getElementById("c");
var ctx = c.getContext("2d");
var cw = c.width = window.innerWidth;
var ch = c.height = window.innerHeight;
var cx = cw / 2,
cy = ch / 2;
var rad = Math.PI / 180;
var w = cw;
var h = ch * 0.3;
var amplitude = h;
var frequency = 0.01;
var phi = 0;
var frames = 0;
var stopped = true;
ctx.lineWidth = .4;
var offset = 100;
var points = interpolateLineRange( [ [0, 0], [ 95, 58], [84, 158], [350, 300], [540, 190] ], 20);
points = interpolateLineRange(points, 100);
ctx.moveTo(0, 0);
var distance_traveled = 0;
var current_slope = 0;
for (var ii in points) {
if (ii == 0) {
continue;
}
distance_traveled += dist(points[ii - 1], points[ii]);
current_slope = slope(points[ii - 1], points[ii]);
var newY = Math.sin(distance_traveled * .07) * 45 + points[ii][1];
var diff = newY - points[ii][1];
if (points[ii][1] > points[ii - 1][1]) {
ctx.lineTo(points[ii][0] - diff, newY);
} else {
ctx.lineTo(points[ii][0] + diff, newY);
}
}
ctx.stroke();
ctx.moveTo(0, 0);
for (var ii in points) {
ctx.lineTo(points[ii][0], points[ii][1]);
}
ctx.strokeStyle = 'red';
ctx.stroke();
问题其实并不"drawing sine waves along a path":那部分实际上是微不足道的。取你的路径部分,用距离或时间变量表示,然后绘制正弦(或其他任何东西)作为偏移函数:
for t=0; t<distance; t+=fraction of distance:
point = path.get(t)
normal = path.normal(t)
strength = sin(t)
if t=0:
ctx.moveTo(point + strength * normal)
else:
ctx.lineTo(point + strength * normal)
很简单,让我们来实现它:http://jsbin.com/nefemazovo/edit?js,output
当然,这是一些代码,但它并不复杂:只是一个 class 模拟多边形路径,在我们向其添加点时跟踪其长度,以及一个绘制多边形的绘制函数,以及一些偏移函数,通过定期对多边形进行采样并计算每个点的法线。
真正的问题是:您将如何处理偏移数据中的重叠?例如,从上面的例子:
这里有一个非常明显的区域,我们将不得不做...一些事情:
那我们怎么办?事实证明:没有人知道,这完全取决于您。例如,您可以绘制 "uneven" 正弦曲线,以便始终在多边形截面的端点处有一个节点。可能有效,但如果连续段之间的角度足够小,您也可能仍然有重叠。再加上你的正弦会不均匀,那看起来不错吗?呃……随你。或者,您可以在多边形过渡处将偏移强度衰减到零,然后将其逐渐增加到 100%,但这看起来不错吗?不知道,那是你的电话。您还可以使用插值法,使过渡处的正弦波 "blend"。 那个好看吗?同样,不知道,仍然取决于你。您甚至可以用二次曲线或三次曲线之类的东西替换多边形的违规部分,这样您始终可以平滑过渡,正弦偏移将沿着该过渡 "just work",但这看起来不错吗? ...你明白了 =)
这个问题中我们可以回答的部分不是很有趣,很遗憾我们无法为您回答有趣的部分...
不过我们可以提供建议:我不知道你的多边形代表什么,但 "curves" 几乎总是作为脊柱工作得更好(几乎,因为曲线 可以 也有不连续性,这是你想要避免的事情),所以如果你可以构建曲线,那可能是值得的。但是,不会解决角度太小时奇怪的重叠问题:
您仍然面临着 "executive decisions" 比教科书 "in this situation, do this: ..." 解决方案更多的问题。