在CSS或画布中绘制曲线,沿着它移动圆 [英] Drawing a curved line in CSS or canvas, and moving circle along it

查看:291
本文介绍了在CSS或画布中绘制曲线,沿着它移动圆的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我今天被赋予了一个沿曲线移动的圆形。我创建了一个JSBin与我迄今为止与纯CSS的进步,但我觉得我的方向错误。我想也许这将是更好的画布,但我不知道从哪里开始。这不是沿着一条线绘制,也填充了酒吧。



Fiddle



以下是设计:





以下是我到目前为止使用CSS的距离:



这里是如何为您的圆形沿着曲线设置动画(这是一个 c。使用canvas的 context.bezierCurveTo 绘制曲线。 code>方法。


  • 使用一系列画布的 context.lineTo


  • 要用彩虹颜色填充曲线路径,可以使用 context.clip 以限制图形仅在路径内显示。然后您可以使用 context.fillRect 填充您的多色乐队。


  • 使用 requestAnimationFrame 创建一个动画循环,在曲线上沿途增加的路点绘制您的球。


  • 曲线使用 De Casteljau的算法




  • 代码和演示:



      var canvas = document.getElementById(canvas); var ctx = canvas.getContext 2d); var cw = canvas.width; var ch = canvas.height; var colors = [[229,133,50],[251,183,50],[133,206,63],[22,155,116],[26,160,219]]; var points = [35,120,317,511,709,792]; var p0 = {x:37, ; var p1 = {x:267,y:143}; var p2 = {x:651,y:129}; var p3 = {x:794,y:96}; var waypoints = cubicBezierPoints(p0,p1,p2 ,p3); var currentIndex = 0; var radius = 10; // requestAnimationFrame(animate); //绘制彩虹曲线的函数drawCurve(){ctx.save(); ctx.moveTo(37,144); ctx.bezierCurveTo(267,143,651,129,794,96); ctx.lineTo(794,158); ctx.lineTo(37,158); ctx.closePath(); ctx.fill(); ctx.globalCompositeOperation ='source-atop'; for(var i = 0; i< points.length-1; i ++){var c = colors [i]; ctx.fillStyle ='rgb('+ c [0] +','+ c [1] +','+ c [2] +')'; ctx.fillRect(points [i],0,points [i + 1],ch); } ctx.restore(); } // function drawBall(){var pt = waypoints [currentIndex]; ctx.beginPath(); ctx.arc(pt.x,pt.y,radius,0,Math.PI * 2); ctx.fillStyle ='white'; ctx.fill(); ctx.strokeStyle ='black'ctx.lineWidth = 3; ctx.stroke();} //动画循环函数animate(){ctx.clearRect(0,0,cw,ch); drawCurve(); drawBall(); ctx.beginPath(); currentIndex ++; if(currentIndex< waypoints.length){requestAnimationFrame(animate); }} //计算waypoints函数cubicBezierPoints(p0,p1,p2,p3){var ticksPerSecond = 60; var seconds = 4; var totalTicks = ticksPerSecond * seconds; var pts = []; for(var t = 0; t  

      body {background-color:ivory; } #canvas {border:1px solid red; margin:0 auto; }  

     < canvas id =canvaswidth = 820 height = 200>< / canvas>  


    I was given a design today that is a circle moving along a curved line. I created a JSBin with the progress I have made so far with pure css but I feel I'm on the wrong direction. I think maybe this would be better done with canvas but I'm not sure where to begin. This is not just drawing along a line its also filling the bars.

    Fiddle

    Here is the design:

    Here is how close I have got so far with CSS:

    解决方案

    Here's how to animate your circle along your curved line (which is a Cubic Bezier Curve).

    • Draw your curve using canvas's context.bezierCurveTo method.

    • Close your rainbow path using a series of canvas's context.lineTo method.

    • To fill only the curved path with your rainbow colors, you can use context.clip to restrict drawings to display only inside the path. Then you can use context.fillRect to fill with your multi-colored bands.

    • Use requestAnimationFrame to create an animation loop that draws your ball at increasing waypoints along your curve.

    • Calculate waypoints along your curve using De Casteljau's Algorithm

    Here's example code and a Demo:

    var canvas=document.getElementById("canvas");
    var ctx=canvas.getContext("2d");
    var cw=canvas.width;
    var ch=canvas.height;
       
    var colors=[[229,133,50],[251,183,50],[133,206,63],[22,155,116],[26,160,219]];
    var points=[35,120,317,511,709,792];
    var p0={x:37,y:144};
    var p1={x:267,y:143};
    var p2={x:651,y:129};
    var p3={x:794,y:96};
    var waypoints=cubicBezierPoints(p0,p1,p2,p3);
    var currentIndex=0;
    var radius=10;
    //
    requestAnimationFrame(animate);
    
    // draw the rainbow curve thing
    function drawCurve(){
        ctx.save();
        ctx.moveTo(37,144);
        ctx.bezierCurveTo(267,143,651,129,794,96);
        ctx.lineTo(794,158);
        ctx.lineTo(37,158);
        ctx.closePath();
        ctx.fill(); 
        ctx.globalCompositeOperation='source-atop';
        for(var i=0;i<points.length-1;i++){
            var c=colors[i];
            ctx.fillStyle='rgb('+c[0]+','+c[1]+','+c[2]+')';
            ctx.fillRect(points[i],0,points[i+1],ch);
        }
        ctx.restore();    
    }
    //
    function drawBall(){
        var pt=waypoints[currentIndex];
        ctx.beginPath();
        ctx.arc(pt.x,pt.y,radius,0,Math.PI*2);
        ctx.fillStyle='white';
        ctx.fill();
        ctx.strokeStyle='black'
        ctx.lineWidth=3;
        ctx.stroke();
    }
    
    // the animation loop
    function animate(){
        ctx.clearRect(0,0,cw,ch);
        drawCurve();
        drawBall();
        ctx.beginPath();
        currentIndex++;
        if(currentIndex<waypoints.length){
            requestAnimationFrame(animate);
        }
    }
    
    // calculate the waypoints
    function cubicBezierPoints(p0,p1,p2,p3){
        var ticksPerSecond=60;
        var seconds=4;
        var totalTicks=ticksPerSecond*seconds;
        var pts=[];
        for(var t=0;t<totalTicks;t++){
            pts.push(getCubicBezierXYatT(p0,p1,p2,p3,t/totalTicks));
        }
        return(pts);
    }
    
    // De Casteljau's algorithm which calculates points along a cubic Bezier curve
    // plot a point at interval T along a bezier curve
    // T==0.00 at beginning of curve. T==1.00 at ending of curve
    // Calculating 100 T's between 0-1 will usually define the curve sufficiently
    function getCubicBezierXYatT(startPt,controlPt1,controlPt2,endPt,T){
        var x=CubicN(T,startPt.x,controlPt1.x,controlPt2.x,endPt.x);
        var y=CubicN(T,startPt.y,controlPt1.y,controlPt2.y,endPt.y);
        return({x:x,y:y});
    }
    // cubic helper formula at T distance
    function CubicN(T, a,b,c,d) {
        var t2 = T * T;
        var t3 = t2 * T;
        return a + (-a * 3 + T * (3 * a - a * T)) * T
        + (3 * b + T * (-6 * b + b * 3 * T)) * T
        + (c * 3 - c * 3 * T) * t2
        + d * t3;
    }

    body{ background-color: ivory; }
    #canvas{border:1px solid red; margin:0 auto; }

    <canvas id="canvas" width=820 height=200></canvas>

    这篇关于在CSS或画布中绘制曲线,沿着它移动圆的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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