自学内容网 自学内容网

canvas:绘制点和点之间连线

效果图:
在这里插入图片描述

<template>
    <div class="home-box">
        <canvas id="canvas" />
        <div class="lightCircle" ref="circleRef" v-for="(item,index) in 5" :key="index"></div>
        <div class="lightCircle" ref="circleRef2" v-for="(item,index) in 5" :key="index + '1'"></div>
        <div :class="'lightCircle2 lightCircle2'+index" ref="circleRef3" v-for="(item,index) in 5" :key="index + '2'"></div>
        <div ref="circle0" class="circle circle0">
            <span class="chi">一级菜单</span>
        </div>
        <div ref="circle1" class="circle circle1">
            <span class="chi">二级菜单1</span>
        </div>
        <div ref="circle2" class="circle circle2">
            <span class="chi">二级菜单2</span>
        </div>
        <div ref="circle3" class="circle circle3">
            <span class="chi">二级菜单3</span>
        </div>
        <div ref="circle4" class="circle circle4">
            <span class="chi">二级菜单4</span>
        </div>
        <div ref="circle5" class="circle circle5">
            <span class="chi">二级菜单5</span>
        </div>
    </div>
</template>

<script>
export default {
    name: "homePage",
    data () {
        return {
            resizeTimer: null,
        }
    },
    mounted () {
        this.initCanvas();
    },
    methods: {
        initCanvas () {
            let that = this;
            let canvas = document.getElementById("canvas");
            let ctx = canvas.getContext("2d");

            this.canvasResize(canvas, ctx);
            window.onresize = function () {
                setTimeout(() => {
                    that.canvasResize(canvas, ctx, 1);
                }, 500)
            }
        },
        canvasResize (canvas, ctx, flag) {
            canvas.width = canvas.offsetWidth;
            canvas.height = canvas.offsetHeight;
            this.createLine(canvas, ctx, flag);//画线
        },
        createLine (canvas, ctx, flag) {
            let that = this;
            let { circle0, circle1, circle2, circle3, circle4, circle5 } = this.$refs,//offsetLeft依次对应 圆心,左上角
                r0 = circle0.offsetWidth / 2,
                r1 = circle1.offsetWidth / 2,
                dig0 = Math.PI / 9,//20度
                dig1 = Math.PI / 6,//30度
                dig3 = Math.PI / 3,//60度
                dig4 = Math.PI / 18,//10度
                dig5 = Math.PI * 11 / 36,//55度
                // console.log(Math.sin(Math.PI/2));//等于1,Math.PI代表180度
                //五环上的坐标
                valueArr1 = [
                    {//value1
                        x: circle1.offsetLeft + r1 + r1 * Math.cos(dig1),
                        y: circle1.offsetTop + r1 + r1 * Math.sin(dig1),
                    },
                    {//value2
                        x: circle2.offsetLeft + r1 - r1 * Math.sin(dig3),
                        y: circle2.offsetTop + r1 + r1 * Math.cos(dig3),
                    },
                    {//value3
                        x: circle3.offsetLeft,
                        y: circle3.offsetTop + r1,
                    },
                    {//value4
                        x: circle4.offsetLeft + r1 - r1 * Math.sin(dig1),
                        y: circle4.offsetTop + r1 - r1 * Math.cos(dig1),
                    },
                    {//value5
                        x: circle5.offsetLeft + r1 + r1 * Math.cos(dig0),
                        y: circle5.offsetTop + r1 - r1 * Math.sin(dig0),
                    },
                ],
                //圆心上的坐标
                valueArr0 = [
                    {//对应value1
                        x: circle0.offsetLeft - r0 * Math.cos(dig0),
                        y: circle0.offsetTop - r0 * Math.sin(dig0),
                    },
                    {//对应value2
                        x: circle0.offsetLeft + r0 * Math.cos(dig1),
                        y: circle0.offsetTop - r0 * Math.sin(dig1),
                    },
                    {//对应value3
                        x: circle0.offsetLeft + r0 * Math.cos(dig4),
                        y: circle0.offsetTop + r0 * Math.sin(dig4),
                    },
                    {//对应value4
                        x: circle0.offsetLeft + r0 * Math.cos(dig5),
                        y: circle0.offsetTop + r0 * Math.sin(dig5),
                    },
                    {//对应value5
                        x: circle0.offsetLeft - r0 * Math.cos(dig0),
                        y: circle0.offsetTop + r0 * Math.sin(dig0),
                    },
                ];

            clear();
            createCircle(flag);
            for (let i = 0; i < valueArr1.length; i++) {
                drawDynamicLine(valueArr1[i].x, valueArr1[i].y, valueArr0[i].x, valueArr0[i].y);
            }

            /*清除画布*/
            function clear () {
                ctx.clearRect(0, 0, canvas.width, canvas.height);
            }

            /*画点*/
            function createCircle (flag) {
                ctx.fillStyle = "#01abf9";

                let style = document.styleSheets[0];//keyframes
                if (flag == 1) {
                    //自适应拖动屏幕时,删除keyframes样式
                    for (let j = 0; j < valueArr1.length; j++) {
                        style.deleteRule("Mylight" + j);
                    }
                }

                for (let i = 0; i < valueArr1.length; i++) {
                    that.$nextTick(() => {
                        if (that.$refs.circleRef[i]) {
                            that.$refs.circleRef[i].style.left = valueArr1[i].x - 1 + 'px';
                            that.$refs.circleRef[i].style.top = valueArr1[i].y - 1 + 'px';
                        }
                        if (that.$refs.circleRef2[i]) {
                            that.$refs.circleRef2[i].style.left = valueArr0[i].x - 1 + 'px';
                            that.$refs.circleRef2[i].style.top = valueArr0[i].y - 1 + 'px';
                        }
                        // 写入keyframes样式
                        style.insertRule(`@keyframes Mylight${i}{
                            0% { left:${that.$refs.circleRef[i].style.left};top:${that.$refs.circleRef[i].style.top}}
                            90%{ opacity:1}
                            100%{left:${that.$refs.circleRef2[i].style.left};opacity:0;top:${that.$refs.circleRef2[i].style.top};}
                        }`, 1);
                    })
                }
                ctx.shadowBlur = 2;//Reseting the blur
            }

            /*
                绘制两点直线
                画动态直线
                @(x1,y1)    起点
                @(x2,y2)    终点
            */
            function drawDynamicLine (x1, y1, x2, y2) {
                const x22 = x2;
                const y22 = y2;

                if (x1 == x2) {
                    drawVerticalLine(x1, y1, x2, y2);   /*斜率不存在的情况*/
                } else {
                    drawCommonLine(x1, y1, x2, y2);    /*斜率为正或者负或者0*/
                }

                /*k存在的情况*/
                function drawCommonLine (x1, y1, x2, y2) {
                    let timer1 = null;
                    clearInterval(timer1);

                    //y=kx+b
                    let k = (y2 - y1) / (x2 - x1)   //斜率k     正 负 0
                    let b = y1 - k * x1           //常数b
                    let i = 0;
                    let flag = compare(x1, x2);

                    function draw () {
                        let xi = x1 + i;
                        let yi = k * xi + b;
                        let xj = x1 + i + 20;     //控制步长决定绘制的是虚线还是实线
                        let yj = k * xj + b;
                        //最后一段 线段的步长缝合
                        if (xj + 20 > x22 || yj + 20 > y22) {
                            let a = x22 + 20 - xj;
                            xj = x1 + i + a;
                            yj = k * xj + b;
                            // console.log(1,xj,yj,x22,y22);
                            drawLine(xi, yi, xj, yj);
                            return
                        }
                        drawLine(xi, yi, xj, yj);
                        i += 20 * flag;

                        if (Math.abs(i) <= Math.abs(x1 - x2)) {
                            timer1 = window.setTimeout(function () {
                                draw();
                            }, 50);
                        }
                    }

                    draw();
                }

                /*k不存在,也就是垂直的情况*/
                function drawVerticalLine (x1, y1, x2, y2) {
                    let timer2 = null;
                    clearInterval(timer2);
                    let i = 0;
                    let flag = compare(y1, y2);

                    function draw () {
                        let yi = y1 + i;
                        let yj = y1 + i + 5 * flag;
                        drawLine(x1, yi, x2, yj);
                        i += 20 * flag;
                        if (Math.abs(i) <= Math.abs(y1 - y2)) {
                            timer2 = window.setTimeout(function () {
                                draw();
                            }, 50);
                        }
                    }
                    draw();
                }

                /*比较函数*/
                function compare (a, b) {
                    if (a < b) {
                        return 1;
                    } else {
                        return -1;
                    }
                }

                /*线条片段*/
                function drawLine (x1, y1, x2, y2) {
                    //线条发光
                    ctx.shadowColor = "#fff";
                    ctx.shadowOffsetX = 0;
                    ctx.shadowOffsetY = 0;
                    ctx.shadowBlur = 15;

                    ctx.beginPath();
                    ctx.moveTo(x1, y1);
                    ctx.lineTo(x2, y2);
                    ctx.lineWidth = 2;
                    ctx.strokeStyle = "#01bbf3";//线条颜色
                    ctx.stroke();
                    ctx.closePath();
                    ctx.fill();
                }
            }
        }
    }
}
</script>

<style scoped lang="less">
.home-box {
width: 100%;
height: 100%;
color: #ffffff;
font-size: 32px;
font-weight: 600;
line-height: 38px;
position: relative;
background: #f2f2f2;

canvas {
width: 100%;
height: 100%;
position: absolute;
}

span.chi {
width: 90px;
text-align: center;
height: auto;
animation: none;
}

.circle {
width: 250px;
height: 250px;
display: flex;
justify-content: center;
align-items: center;
position: absolute;
cursor: pointer;

&.circle0 {
width: 360px;
height: 360px;
left: 50%;
top: 45%;
transform: translateX(-50%) translateY(-50%);

.chi {
width: 130px;
text-align: center;
height: 92px;
font-size: 30px;
font-family: PingFangSC-Semibold, PingFang SC;
font-weight: 600;
color: rgba(181, 232, 255, 1);
line-height: 46px;
text-shadow: 0px 0px 2px rgba(137, 218, 255, 1);
}
}

&.circle1 {
left: 22%;
top: 8%;
}

&.circle2 {
left: 63%;
top: 5%;
}

&.circle3 {
left: 77%;
top: 35%;
}

&.circle4 {
overflow: hidden;
left: 55%;
top: 69%;
}

&.circle5 {
left: 10%;
top: 55%;
}
}
}

.lightCircle {
position: absolute;
width: 5px;
height: 5px;
border-radius: 200%;
background-color: #01abf9;
box-shadow: 0 0 10px 8px #01abf9;
}

.lightCircle2 {
display: none\0;
position: absolute;
width: 5px;
height: 5px;
border-radius: 50%;
background-color: #01abf9;
box-shadow: 0 0 20px 10px #01abf9;
&.lightCircle20 {
animation: Mylight0 5s infinite forwards;
}
&.lightCircle21 {
animation: Mylight1 5s infinite forwards;
}
&.lightCircle22 {
animation: Mylight2 5s infinite forwards;
}
&.lightCircle23 {
animation: Mylight3 5s infinite forwards;
}
&.lightCircle24 {
animation: Mylight4 5s infinite forwards;
}
}
</style>


原文地址:https://blog.csdn.net/xilejie/article/details/103765227

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!