在CSS或画布中绘制一条曲线,并沿着它移动圆圈

zma*_*anc 3 html css canvas css3

今天我给了一个设计,就是一个沿着曲线移动的圆圈.我创建了一个JSBin,其中包含了迄今为止我用纯css取得的进展,但我觉得我的方向错了.我想也许用帆布会更好,但我不知道从哪里开始.这不只是沿着一条线绘制它也填充了条形.

小提琴

这是设计:

在此输入图像描述

这是我到目前为止与CSS有多接近:

在此输入图像描述

mar*_*rkE 9

这是如何沿着曲线(这是一个Cubic Bezier曲线)为您的圆圈设置动画.

  • 使用canvas的context.bezierCurveTo方法绘制曲线.

  • 使用一系列画布context.lineTo方法关闭彩虹路径.

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

  • 使用requestAnimationFrame创建一个动画循环,沿着你的曲线增加航点吸引你的球.

  • 使用曲线计算沿曲线的航点 De Casteljau's Algorithm

这是示例代码和演示:

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;
}
Run Code Online (Sandbox Code Playgroud)
body{ background-color: ivory; }
#canvas{border:1px solid red; margin:0 auto; }
Run Code Online (Sandbox Code Playgroud)
<canvas id="canvas" width=820 height=200></canvas>
Run Code Online (Sandbox Code Playgroud)

  • 经过测试和验证.但是我几天都不会接受它,因为我想加上赏金并交给你.这是我收到过的最好的答案.它不仅通过,而且得到了很好的解释.非常感谢你. (2认同)