Rya*_*hel 2 javascript bezier canvas spline html5-canvas
假设我有一条由以下代码生成的贝塞尔曲线:
const ctx = document.querySelector('canvas').getContext('2d');
ctx.beginPath();
ctx.moveTo(50, 20);
ctx.quadraticCurveTo(230, 30, 50, 100);
ctx.stroke();Run Code Online (Sandbox Code Playgroud)
<canvas></canvas>Run Code Online (Sandbox Code Playgroud)
有没有办法只绘制最后 90% 的内容?
对于我的应用程序,我想“消耗”曲线,并创建一个动画,其中圆沿着直线路径移动,沿途吃掉曲线。
我唯一能想到的就是不使用该quadraticCurveTo函数绘制曲线,而是通过以下函数手动计算大量点:
t = 0.5; // given example value
x = (1 - t) * (1 - t) * p[0].x + 2 * (1 - t) * t * p[1].x + t * t * p[2].x;
y = (1 - t) * (1 - t) * p[0].y + 2 * (1 - t) * t * p[1].y + t * t * p[2].y;
Run Code Online (Sandbox Code Playgroud)
然后对 300 左右的点中的每一个点进行moveTo和操作。lineTo
但这存在三个问题:
有没有更好的办法?
您可以使用ctx.setLineDash([])with ctx.lineDashOffset,这是模拟部分路径绘制的常用方法。
const ctx = document.querySelector('canvas').getContext('2d');
animate();
function animate(){
let i = 0;
drawCurve(i);
function drawCurve(start){
ctx.clearRect(0,0,300,150); // initial width and height of canvas
const line_len = 204; // to let the last part of curve stay
ctx.setLineDash([1000]); // bigger than curve length
ctx.lineDashOffset = -start; // changing parameter
ctx.beginPath();
ctx.moveTo(50, 20);
ctx.quadraticCurveTo(230, 30, 50, 100);
ctx.stroke();
const anim_id = requestAnimationFrame(() => drawCurve(++start));
if(start > line_len) cancelAnimationFrame(anim_id);
}
}Run Code Online (Sandbox Code Playgroud)
<canvas></canvas>Run Code Online (Sandbox Code Playgroud)
获取画布中路径的长度可能很棘手。所以我更喜欢使用隐藏来计算它SVG。它<path>的 具有空d属性。所以我可以将我们的路径字符串分配给它和getTotalLength()它的。现在我们有了路径的长度,我们可以使用这些数据来setLineDash正确定义数组,所以path_len(在哪里停止)。
我们还可以使用 path.getPointAtLength() 方法获取路径起点的当前位置。
animate();
function animate(){
const path = document.querySelector('svg > path');
const path_string = 'M 50 20 Q 230 30 50 100';
path.setAttribute('d', path_string);
const path_len = path.getTotalLength();
const ctx = document.querySelector('canvas').getContext('2d');
drawCurve(0);
function drawCurve(start){
ctx.clearRect(0,0,300,150); // initial width and height of canvas
ctx.save();
ctx.setLineDash([path_len + 1]); // bigger than curve length
ctx.lineDashOffset = -start; // changing parameter
ctx.stroke(new Path2D(path_string));
ctx.restore();
const cur_pos = path.getPointAtLength(start - 7); // current position - (radius + 2)
ctx.beginPath();
ctx.arc(cur_pos.x, cur_pos.y, 5, 0, 2*Math.PI, false); // radius = 5 (should be a constant)
ctx.fill();
const anim_id = requestAnimationFrame(() => drawCurve(++start));
if(start > path_len) cancelAnimationFrame(anim_id);
}
}Run Code Online (Sandbox Code Playgroud)
<svg style="display:none">
<path d=""></path>
</svg>
<canvas></canvas>Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
349 次 |
| 最近记录: |