canvas绘画流动贝塞尔渐变曲线,三点绘画一条线

 该效果结合多个前辈文章进行改良的,底线是固定颜色,流动线段是渐变的,使用的效果是canvas内置的一些方法,并通过一些算法进行计算的流动效果。希望有可以优化的建议可以帮忙提一下,提前感谢感谢!!

一下是代码,复制,直接可以运行

<!DOCTYPE html>
<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">

   <script type="text/javascript" src="js/jquery/jquery.min.js"></script>

</head>


</head>
<body >

<div class="main-container" style="width: 1920px;
    height: 1080px;background-color: black;">


    <div class="">

       <!-- <%--网络图--%>-->
        <div class="col-sm-8 box3" style="height: 100%; position: absolute;  top: -113px; left: -1000px;">
            <div class="beijingmap">

               <!-- <%--站点位置--%>
                    <%--大站--%>-->
                <div class="mapdata">

                    <div class="site" style="left:720px;top:184px;">
                        <div class="siteText" siteName="1" sSubNetId="B717C3D697346EC22E14A12DB3F73967"></div>
                        <div class="siteName">1</div>
                    </div>
                    <div class="site" style="left:720px;top:536px;">
                        <div class="siteText" siteName="2" sSubNetId="1E67073FF59420B8B3908C21D2EE2AA7"></div>
                        <div class="siteName">2</div>
                    </div>
                    <div class="site" style="left:1222px;top:380px;">
                        <div class="siteText" siteName="3" sSubNetId="6623113B49547D03677F324E45EE3706"></div>
                        <div class="siteName">3</div>
                    </div>
                    <div class="site" style=" left:1110px;top:858px;">
                        <div class="siteText" siteName="4" sSubNetId="B21A9EA2621392234BA874DD21E552EF"></div>
                        <div class="siteName">4</div>
                    </div>
                    <div class="site" style="left:1753px;top:925px;">
                        <div class="siteText" siteName="5" sSubNetId="38293CDE72E76CC1FD653A50EEA3FAEA"></div>
                        <div class="siteName">5</div>
                    </div>
                    <div class="site" style="left:529px;top:209px;">
                        <div class="siteText" siteName="6" sSubNetId="A58DF56B87930AE42427DD73019F48A0"></div>
                        <div class="siteName">6</div>
                    </div>

                   <!-- <%--用户站--%>-->
                    <div class="site" style="left:590px;top:76px;">
                        <div class="siteText" siteName="7" sSubNetId=""></div>
                        <div class="siteName">7</div>
                    </div>
                    <div class="site" style="left:354px;top:595px;">
                        <div class="siteText" siteName="8" sSubNetId="6546F59E3837AADC8F457F8D86EEBA37"></div>
                        <div class="siteName">8</div>
                    </div>
                    <div class="site" style="left:719px;top:352px;">
                        <div class="siteText" siteName="9" sSubNetId=""></div>
                        <div class="siteName">9</div>
                    </div>
                    <div class="site" style="left:863px;top:533px;">
                        <div class="siteText" siteName="10" sSubNetId=""></div>
                        <div class="siteName">10</div>
                    </div>
                    <div class="site" style="left:1306px;top:620px;">
                        <div class="siteText" siteName="11" sSubNetId="64861712A1E407985A72771F27F1D24F"></div>
                        <div class="siteName">11</div>
                    </div>
                    <div class="site" style="left:1306px;top:780px;">
                        <div class="siteText" siteName="12" sSubNetId="3F9FEE1575CCE9F165E82628CD030362"></div>
                        <div class="siteName">12</div>
                    </div>

                    <div class="site" style="left:855px;top:324px; ">
                        <div class="siteText" siteName="13" sSubNetId="C657ED7210FC13020D4768EEF0233DFA"></div>
                        <div class="siteName">13</div>
                    </div>
                    <div class="site" style="left:865px;top:972px;">
                        <div class="siteText" siteName="14(花乡)" sSubNetId="CD9AA019EA05AE18CF105FA23B940431"></div>
                        <div class="siteName">14(花乡)</div>
                    </div>


                    <div class="site" style="left:1627px;top:69px;">
                        <div class="siteText" siteName="15" sSubNetId="E0797B04069E53247B16E6B23CFB18AE"></div>
                        <div class="siteName">15</div>
                    </div>
                    <div class="site" style="left:1716px;top:186px;">
                        <div class="siteText" siteName="16" sSubNetId="C657ED7210FC13020D4768EEF0233DFA"></div>
                        <div class="siteName">16</div>
                    </div>

                    <div class="site" style="left:368px;top:230px; ">
                        <div class="siteText" siteName="17" sSubNetId="C9666ED377DD3A900237CD53037B09C5"></div>
                        <div class="siteName">17</div>
                    </div>
                    <div class="site" style=" left:532px;top:395px;">
                        <div class="siteText" siteName="18" sSubNetId="F5CCADDAF791711EF0B56800E6F6091E"></div>
                        <div class="siteName">18</div>
                    </div>

                </div>

                <!--<%--线条--%>-->
                <canvas id="mapcanvas" width="2370" height="1263" style="position: absolute; top: 0px; left: 28px;"></canvas>
            </div>

        </div>
   
        </div>

    </div>
</div>
</body>
</html>


<script>
    
    


// 重庆大屏js
$(document).ready(function(){

    drawCurveLine();

});

// 动画渐变线条
let cureLineMove = {
    arr: [{
        start:{x:745,y:216},point:{x:718,y:137},end:{x:676,y:107},
        ms:200, //速度
        percent: 10, //线条动画第一次执行的起始位置
        movelength: [-10, 0], //偏移长度,可为负值 [x,y]  渐变方向
    }, {
        start:{x:745,y:210},point:{x:118,y:65},end:{x:379,y:625},
        ms: 200, //速度
        percent: 20, //线条动画第一次执行的起始位置
        movelength: [-50, 50], //偏移长度,可为负值 [x,y] 渐变方向
    }, {
        start:{x:805,y:214},point:{x:830,y:317},end:{x:806,y:385},
        ms: 200, //速度
        percent: 50, //线条动画第一次执行的起始位置
        movelength: [10, 10], //偏移长度,可为负值 [x,y]//渐变方向
    },  {
        start:{x:805,y:214},point:{x:1109,y:388},end:{x:950,y:565},
        ms: 200, //速度
        percent: 50, //线条动画第一次执行的起始位置
        movelength: [20, 20], //偏移长度,可为负值 [x,y]//渐变方向
    },  {
        start:{x:805,y:214},point:{x:1227,y:359},end:{x:1334,y:643},
        ms: 200, //速度
        percent: 50, //线条动画第一次执行的起始位置
        movelength: [50, 50], //偏移长度,可为负值 [x,y]//渐变方向
    }, {
        start:{x:805,y:214},point:{x:1187,y:359},end:{x:1334,y:805},
        ms: 200, //速度
        percent: 50, //线条动画第一次执行的起始位置
        movelength: [50, 50], //偏移长度,可为负值 [x,y]//渐变方向

    }, {
        start:{x:807,y:565},point:{x:838,y:434},end:{x:880,y:352},
        ms: 200, //速度
        percent: 50, //线条动画第一次执行的起始位置
        movelength: [20, 0], //偏移长度,可为负值 [x,y]//渐变方向
    }, {
        start:{x:810,y:570},point:{x:701,y:900},end:{x:891,y:1001},
        ms: 200, //速度
        percent: 50, //线条动画第一次执行的起始位置
        movelength: [30, 30], //偏移长度,可为负值 [x,y]//渐变方向
    }, {
        start:{x:1308,y:412},point:{x:1407,y:203},end:{x:1652,y:97},
        ms: 200, //速度
        percent: 50, //线条动画第一次执行的起始位置
        movelength: [50, 0], //偏移长度,可为负值 [x,y]//渐变方向
    }, {
        start:{x:1308,y:412},point:{x:1502,y:263},end:{x:1743,y:212},
        ms: 200, //速度
        percent: 50, //线条动画第一次执行的起始位置
        movelength: [50, 0], //偏移长度,可为负值 [x,y]//渐变方向
    }, {
        start:{x:1134,y:890},point:{x:654,y:1002},end:{x:450,y:262},
        ms: 200, //速度
        percent: 50, //线条动画第一次执行的起始位置
        movelength: [-50, 0], //偏移长度,可为负值 [x,y]//渐变方向
    }, {
        start:{x:1134,y:890},point:{x:704,y:942},end:{x:619,y:427},
        ms: 200, //速度
        percent: 50, //线条动画第一次执行的起始位置
        movelength: [-50, 0], //偏移长度,可为负值 [x,y]//渐变方向
    }, {
        start:{x:1135,y:887},point:{x:1084,y:803},end:{x:1020,y:823},
        ms: 200, //速度
        percent: 50, //线条动画第一次执行的起始位置
        movelength: [-50, 0], //偏移长度,可为负值 [x,y]//渐变方向
    }, {
        start:{x:1135,y:887},point:{x:1150,y:731},end:{x:1087,y:674},
        ms: 200, //速度
        percent: 50, //线条动画第一次执行的起始位置
        movelength: [0, -50], //偏移长度,可为负值 [x,y]//渐变方向
    },  {
        start:{x:1780,y:954},point:{x:1500,y:1122},end:{x:1260,y:1113},
        ms: 200, //速度
        percent: 50, //线条动画第一次执行的起始位置
        movelength: [-30, 30], //偏移长度,可为负值 [x,y]//渐变方向
    }, {
        start:{x:888,y:996},point:{x:830,y:831},end:{x:929,y:714},
        ms: 200, //速度
        percent: 50, //线条动画第一次执行的起始位置
        movelength: [-30, -30], //偏移长度,可为负值 [x,y]//渐变方向
    }, {
        start:{x:953,y:1006},point:{x:1079,y:1251},end:{x:1319,y:1177},
        ms: 200, //速度
        percent: 50, //线条动画第一次执行的起始位置
        movelength: [50, 0], //偏移长度,可为负值 [x,y]//渐变方向
    },{
        start:{x:1377,y:1186},point:{x:2247,y:1081},end:{x:1905,y:322},
        ms: 200, //速度毫秒
        percent: 50, //线条动画第一次执行的起始位置
        movelength: [100, -100], //偏移长度,可为负值 [x,y] 渐变方向
    }, {
        start:{x:987,y:714},point:{x:1005,y:525},end:{x:1847,y:318},
        ms: 200, //速度
        percent: 50, //线条动画第一次执行的起始位置
        movelength: [80, -80], //偏移长度,可为负值 [x,y]//渐变方向
    }, ],
    ctx: null,
    style:{strokeStyle:'#1a5e56',},
    gradients:{addColorStop1:["0","#27fd03"]},
    fn: null,
}


// 绘画站点线及线上字体

function drawCurveLine(perfData){
    var canvas = document.getElementById("mapcanvas");
    var context = canvas.getContext("2d");

    // 绘画动态线
    cureLineMove.ctx =context;
    cureLineMove.fn = context.drawAnimateBezierCurve.bind(cureLineMove),
    cureLineMove.fn();

    // 鼠标定位画布位置
    canvas.addEventListener("click",function _handler_(evt){
        var x = evt.clientX;
        var y = evt.clientY;
        var rect = canvas.getBoundingClientRect();
        x-= (rect.left);//+40
        y-= (rect.top);//+40
        console.log("线:{x:"+parseInt(x)+",y:"+parseInt(y)+"}"+"    点: left:"+parseInt(x-20)+"px;top:"+parseInt(y-20)+"px;  ");
    })
}

/**
 * 绘画样式
 * @param context 容器
 * @param width 宽度
 * @param start 开始节点
 * @param point 拐点
 * @param end 结束节点
 * @param isGradient 是否渐变
 */
function drawBezierLineDash(context1,width,start,point,end,isGradient){

    const gradient = context1.createLinearGradient(start.x, start.y, end.x, end.y);
    //context1.setLineDash([15,5]);

    context1.moveTo(start.x,start.y);
    context1.quadraticCurveTo(point.x,point.y,end.x,end.y);
    if(isGradient){
        context1.lineWidth= 14;
        gradient.addColorStop(1,"#27fd03"); // 尾部颜色
    }else {
        /*context1.lineWidth= 2;
        /!*gradient.addColorStop(0,"#e5662c"); // 头部颜色
        gradient.addColorStop(0.2,"#cd802c"); // 中部颜色*!/
        gradient.addColorStop(1,"#5ddd3a58"); // 尾部颜色*/
    }
    context1.strokeStyle = gradient;
    return context1;
}


    /**
 * 拓展canvas属性或方法
 * 
 */


/**
 *
 * 静态绘画贝塞尔曲线及绘画流动曲线
 */
CanvasRenderingContext2D.prototype.drawAnimateBezierCurve = function () {
    let ctx = this.ctx;
    let style = this.style;
    let gradients = this.gradients;

    // ctx.clearRect(0, 0, 1500, 1500); //清除
    for (let i = 0; i < this.arr.length; i++) {
        const item = this.arr[i]
        let start = item.start;
        let point = item.point;
        let end = item.end;
        if (start == undefined){
            continue;
        }
        ctx.drawBezierCurvePath(
            ctx,
            start, // 开始点
            point,
            end, // 结束点
            this.arr[i].percent / this.arr[i].ms,
            this.arr[i].movelength,
            style,
            gradients,
        );

        ctx.stroke();

        this.arr[i].percent = (this.arr[i].percent + 1) % this.arr[i].ms
    }

    requestAnimationFrame(ctx.drawAnimateBezierCurve.bind(this)); //类似于setInterval 浏览器按照屏幕刷新率执行函数

}

/**
 * 绘画贝塞尔曲线,可虚线可实线
 * @param {Object} ctx
 * @param {Object} start
 * @param {Object} end
 * @param {Object} speed 速度/第一次执行位置= 每帧的移动距离
 * @param {Object} movelength 偏移长度,渐变动画大小
 * @param {Object} style 线条底色
 * @param {Object} gradients 流动点渐变色
 */
CanvasRenderingContext2D.prototype.drawBezierCurvePath = function (ctx, start,point, end, speed, movelength,style,gradients) {

    ctx.beginPath();
    ctx.lineWidth= 1;
    ctx.moveTo(start.x, start.y);
    if(style.strokeStyle){
        ctx.strokeStyle = style.strokeStyle;//'#1a5e56'
    }else{
        ctx.strokeStyle = "#fff";
    }
    if(style.setLineDash){
        ctx.setLineDash ([style.setLineDash[0],style.setLineDash[1]]);;//'#1a5e56'
    }else{
        ctx.setLineDash([1,0]);
    }
    ctx.quadraticCurveTo(point.x, point.y, end.x, end.y);
    ctx.stroke();
    ctx.beginPath();
    ctx = $.extend(ctx,style);

    let p0 = start;
    let p1 = point;
    let p2 = end;

    let v01 = {x:(p1.x - p0.x), y:(p1.y - p0.y)}; // 向量<p0, p1>
    let v12 = {x:(p2.x - p1.x), y:(p2.y - p1.y)}; // 向量<p1, p2>

    let q0 = {x:(p0.x + v01.x * speed),y: (p0.y + v01.y * speed)};
    let q1 = {x:(p1.x + v12.x * speed),y:( p1.y + v12.y * speed)};

    let v = {x:(q1.x - q0.x), y:(q1.y - q0.y)}; // 向量<q0, q1>

    let b = {x:(q0.x + v.x * speed),y: (q0.y + v.y * speed)};

    let gradient = ctx.createLinearGradient(b.x, b.y, Math.round(b.x - movelength[0]), Math.round(b.y - movelength[1]));
    if(gradients.addColorStop1){
        gradient.addColorStop(gradients.addColorStop1[0], gradients.addColorStop1[1]);
    }else if(gradients.addColorStop2){
        gradient.addColorStop(gradients.addColorStop2[0], gradients.addColorStop2[1]);
    }else if(gradients.addColorStop3){
        gradient.addColorStop(gradients.addColorStop3[0], gradients.addColorStop3[1]);
    }else{
        gradient.addColorStop("0", "#27fd03");
    }
    gradient.addColorStop("1.0", "rgba(255,255,255,0)");
    ctx.strokeStyle = gradient;
    ctx.moveTo(p0.x, p0.y);
    ctx.quadraticCurveTo(
        q0.x, q0.y,
        b.x, b.y
    );
}


/**
 *绘画渐变贝塞尔曲线,可虚线可实线
 * @param context1
 * @param start
 * @param point
 * @param end
 * @param style
 * @param gradients
 * @returns {*}
 */
CanvasRenderingContext2D.prototype.drawBezierLine = function (context1,start,point,end,style,gradients) {
    const gradient = context1.createLinearGradient(start.x, start.y, end.x, end.y);
    if(style.lineWidth){
        context1.lineWidth = style.lineWidth;
    }else{
        context1.lineWidth = 1;
    }
    if(style.setLineDash){
        context1.setLineDash ([style.setLineDash[0],style.setLineDash[1]]);;//'#1a5e56'
    }else{
        context1.setLineDash([15,5]);// 虚线    1,0  实线
    }
    context1.moveTo(start.x,start.y);
    context1.quadraticCurveTo(point.x,point.y,end.x,end.y);
    if(gradients.addColorStop1){
        gradient.addColorStop(gradients.addColorStop1[0], gradients.addColorStop1[1]);
    }else if(gradients.addColorStop2){
        gradient.addColorStop(gradients.addColorStop2[0], gradients.addColorStop2[1]);
    }else if(gradients.addColorStop3){
        gradient.addColorStop(gradients.addColorStop3[0], gradients.addColorStop3[1]);
    }else{
        gradient.addColorStop("0", "#27fd03");
    }
    context1.strokeStyle = gradient;
    return context1;
}
    
</script>

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值