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>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值