绘制线条

153 阅读1分钟

定义画布和获取渲染上下文对象

<div class="box">
        <canvas id="hb" width="700px" height="600px"></canvas>
    </div>
    <script>
        //  获取canvas元素就相当于定义画布
        let canvas=document.querySelector("#hb");
        // 得到绘制上下文对象就相当于定义一只画图的画笔,绘制二维图像
        let ctx=canvas.getContext("2d");
     </script>   

获取渲染上下文对象调用getContext()方法,传入参数是2d表示二维平面画图,3d是三维平面画图。

moveTo()和lineTo()

moveTo(x, y)

把画笔移动到指定的坐标(x, y)。相当于设置路径的起始点坐标,不创建线条。

lineTo(x,y)

表示将画笔从某一个点移动到另一个点,会将之前定义的线段起点和指定的新的点连接起来绘制一条从从当前位置到指定坐标的直线;会把上一次的终点作为这一次的起点,如果上一次没有终点就没有这一次的起点。

//把上一次的终点作为这一次的起点
let ctx=canvas.getContext("2d");
        ctx.moveTo(100,100);
        ctx.lineTo(300,300);
        ctx.lineTo(200,100);
        ctx.lineTo(100,100);
        ctx.stroke();

image.png

//如果上一次没有终点就没有这一次的起点
let ctx=canvas.getContext("2d");
        ctx.lineTo(100,100);
        ctx.lineTo(300,300);
        ctx.lineTo(400,200);
        ctx.stroke();

ctx.lineTo(100,100)定义了终点,没有起始点这个点就是这一次的终点。把ctx.lineTo(400,200)的坐标作为这一次的终点,上一次的终点(100,100)作为这一次的起点。同理ctx.lineTo(400,200)的坐标是这次终点,上一次终点(400,200)是这次起点

image.png

绘制模拟心电图的折线变化

<body>
    <canvas class="canvas" width="1000px" height="600px"></canvas>
    <script>
        /** @type {HTMLCanvasElement} */
        let canvas=document.querySelector(".canvas");
        let ctx=canvas.getContext("2d");
        //心跳数据
        let arr=[60,67,74,80,70,66,77,67,80,89,97,101,10,117];
        //用计时器给一段时间获取数据
        setInterval(()=>{
            //随机产生数据
            let heart=Math.round(Math.random()*((120-60)+60));
            arr.push(heart);
        },700);
        //绘制坐标图
        function fn(arg, width, height) {
            //for循环画格子
            for (let i = 0; i < height; i++) {
                //一个格子高度为20,总的是1000,就能画50个
                //画横线,循环次数就是画布的高度,
                arg.moveTo(0, 20 * i);
                //连接的横线宽度是画布宽度
                arg.lineTo(width, 20 * i);
            };
            //画竖线
            // 一个格子高度为20,总的是600,就能画30个
            for (let j = 0; j < width; j++) {
                arg.moveTo(20*j,0);
                //连接的竖线高度是画布高度
                arg.lineTo(20*j,height);
            };
            arg.stroke();
            //画坐标轴
            //开启新的轨迹,可以重新定义线条样式等
            arg.beginPath()
            arg.lineWidth=3;
            arg.moveTo(50,50);
            arg.lineTo(50,570);//笛卡尔坐标原点
            arg.lineTo(770,570);
            arg.lineTo(740,590);
            arg.moveTo(770,570);
            arg.lineTo(740,550);
            arg.moveTo(50,50);
            arg.lineTo(70,80);
            arg.moveTo(50,50);
            arg.lineTo(30,80);
            //绘制
            arg.stroke();
        };
        //绘制心跳折线
        let x=60;
        function fg(ctx,data){
            ctx.beginPath();
            ctx.strokeStyle="green";
            //根据数据容器的数据绘制图形,就循环数组
            for(let i=0;i<data.length;i++){
                //横坐标是两个数据之间的间隔需要加上笛卡尔坐标在页面原点的距离,纵坐标根据数据来变化但需要转换
                //需要用笛卡尔坐标原点的高度减去数据的大小就是数据在笛卡尔坐标纵轴的位置
                ctx.lineTo(i*30+x,560-data[i]);     
            };
            ctx.stroke();
        };
        //让计时器每隔一段时间调用绘制图形的函数就可以实现动画的效果
        setInterval(()=>{
                //需要清除画布,重新设置画布的宽度即可,避免每执行一次就重叠在之前画布中的线上
                canvas.width=canvas.width;
                //让横坐标每隔一段时间向左移,用变量保存一个固定的值,绘制让这个值向右移动,就让x坐标加上变量
                //横坐标先左移动就让这个变量减少一些,x坐标就会少加一些这个值
                x-=30;
                fn(ctx,canvas.width,canvas.height);
                fg(ctx,arr);
            },1000);
        
    </script>
</body>

1A2E83364B15DEEDF3F2208B9D5A6868.png

2.gif

清除画布利用重新设置画布的宽度即可,因为图片的属性值改变就会让图片的编码重新执行一次