及时绘制HTML5 / Javascript画布路径 [英] Draw HTML5/Javascript Canvas Path in Time

查看:254
本文介绍了及时绘制HTML5 / Javascript画布路径的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我有一个路径:

  var context = canvas.getContext('2d'); 
context.beginPath();
context.moveTo(100,20);
context.lineTo(200,160);
context.quadraticCurveTo(230,200,250,120);
context.bezierCurveTo(290,-40,300,200,400,150);
context.lineTo(500,90);
context.lineWidth = 5;
context.strokeStyle ='blue';
context.stroke();

这会一次输出所有路径:





如何分割路径到给定长度的子路径?例如: context.splitCurrentPathIntoSubPath(0,0.75)应该只返回路径的前3/4。



我想用这个来实现动画。

解决方案

当使用D3动画SVG弧时,我遇到了类似的问题。 js。我的解决方案借鉴了。它不是最直观的,但是常用于D3动画。它需要仔细设置虚线偏移和线长度。 CSS技巧提供了一个很好的解释这里的技术,我强烈建议在查看我的代码之前阅读



我已使用此技术修改了上述JSFiddle 在此处为您的行实施



有关行长的注意事项

b $ b

这个实现需要你知道你的行的大致长度,以便你可以设置长度var大于它。对于贝塞尔曲线和二次曲线,这是棘手的,但仍可以完成(这个SO问题看起来很有前途)。对于我的演示,我用反复试验,发现你的大约608px。设置长度为10000可能会确保您的线总是正确绘制,但是代价是每毫秒调用大量不必要的间隔回调。底线是:如果你关心性能,找出贝塞尔公式的东西;



HTML

 < body> 
< canvas id =canvaswidth =500height =500>
webgl无法启动
< / canvas>
< / body>

JavaScript

  canvasHolder = document.getElementById('canvas'); 
context = canvasHolder.getContext('2d');

context.fillStyle ='white';
var w = canvasHolder.width,h = canvasHolder.height;
context.fillRect(0,0,w,h);

//设置线条绘制的方向
// 1-> ltr | -1> rtl
var dir = -1;
//重要信息:这必须设置为大于行的长度
//
var length = 608;
//线的绘制速度
var speed = 1;

var progress = 0;
var lineInterval;

// Go!
context.globalCompositeOperation ='copy';
drawLine();

function drawLine(){
//一旦绘制线就会自动清除
lineInterval = setInterval(updateLine,1);
}

function updateLine(){
//定义行
defineLine();

if(progress< length)
{
progress + = speed;
moveDash(progress,dir);
} else {
clearInterval(lineInterval);
}

}

function defineLine(){
context.beginPath();
context.moveTo(100,20);
context.lineTo(200,160);
context.quadraticCurveTo(230,200,250,120);
context.bezierCurveTo(290,-40,300,200,400,150);
context.lineTo(500,90);
context.lineWidth = 5;
context.strokeStyle ='blue';
}

function moveDash(frac,dir){
//默认方向右 - >左
var dir = dir || -1
context.setLineDash([length]);
context.lineDashOffset = dir *(frac + length);
context.stroke();
}


Let's say I have a path:

var context = canvas.getContext('2d');
context.beginPath();
context.moveTo(100, 20);
context.lineTo(200, 160);
context.quadraticCurveTo(230, 200, 250, 120);
context.bezierCurveTo(290, -40, 300, 200, 400, 150);
context.lineTo(500, 90);
context.lineWidth = 5;
context.strokeStyle = 'blue';
context.stroke();

This prints the path all at once:

How can I split the path into subpaths of given length? For example: context.splitCurrentPathIntoSubPath(0, 0.75) should return only the first 3/4 of the path.

I would like to use this to realise an animation. If there is an easier method, it is also welcome.

解决方案

I came across a similar problem when animating SVG arcs using D3.js. My solution borrows from that. It isn't the most intuitive, but is commonly used in D3 animations. It requires careful setting of the dash offset and line length. CSS Tricks gives a good explanation of the technique here which I strongly recommend reading before viewing my code.

I have modified the above JSFiddle with this technique implemented for your line here. Note this will work even if the line loops back on itself.

A note on line length:

This implementation requires you to know the approx length of your line so that you can set the length var to be greater than it. For bezier and quadratic curves this is tricky but can nevertheless be done (this SO question looks promising). For my demo I used trial and error to find that yours was about 608px. Setting length to 10000 will probably ensure your lines always draw correctly, but at the cost of having lots of needless interval callbacks called every millisecond. The bottom line is: if you care about performance, figure out the bezier formula stuff; if you don't, set that variable high.

Code:

HTML

<body>
    <canvas id="canvas" width="500" height="500">
        webgl couldn't be started
    </canvas>
</body>

JavaScript

canvasHolder = document.getElementById( 'canvas' );
context = canvasHolder.getContext('2d');

context.fillStyle = 'white';
var w = canvasHolder.width, h = canvasHolder.height;
context.fillRect( 0, 0, w, h);

//set the direction the line draws in
//1->ltr | -1->rtl
var dir = -1;
//IMPORTANT: this must be set to greater than the length
//of the line
var length = 608;
//the speed of the line draw
var speed = 1;

var progress = 0;
var lineInterval;

//Go!
context.globalCompositeOperation='copy';
drawLine();

function drawLine() {
    //this clears itself once the line is drawn
    lineInterval = setInterval(updateLine, 1);
}

function updateLine() {
    //define the line
    defineLine();

    if(progress<length)
    {
      progress+=speed;
      moveDash(progress, dir);
    } else {
      clearInterval(lineInterval);
    }

}

function defineLine() {
    context.beginPath();
    context.moveTo(100, 20);
    context.lineTo(200, 160);
    context.quadraticCurveTo(230, 200, 250, 120);
    context.bezierCurveTo(290, -40, 300, 200, 400, 150);
    context.lineTo(500, 90);
    context.lineWidth = 5;
    context.strokeStyle = 'blue';
}

function moveDash(frac, dir) {
    //default direction right->left
    var dir = dir || -1 
    context.setLineDash([length]);
    context.lineDashOffset = dir*(frac+length);
    context.stroke();
}

这篇关于及时绘制HTML5 / Javascript画布路径的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆