hi,你好!欢迎访问本站!登录
本站由简数采集腾讯云宝塔系统阿里云强势驱动
当前位置:首页 - HTML - 正文 请牢记本站网址www.sosophp.cn

怎样运用canvas画出腻滑的曲线?(代码)【html5教程】

2019-11-26HTML搜搜PHP网42°c
A+ A-
本篇文章给人人带来的内容是关于怎样运用canvans画出腻滑的曲线?(代码),有肯定的参考价值,有须要的朋侪能够参考一下,愿望对你有所协助。

背景提要

置信人人日常平凡在进修canvas 或 项目开辟中运用canvas的时刻应当都遇到过如许的需求:完成一个能够誊写的画板小工具。

嗯,置信这对canvas运用较熟的童鞋来讲仅仅只是几十行代码就能够搞掂的事变,以下demo就是一个再也简朴不过的例子了:

<!DOCTYPE html>
<html>
<head>
    <title>Sketchpad demo</title>
    <style type="text/css">
        canvas {
            border: 1px blue solid; 
        }
    </style>
</head>
<body>
    <canvas id="canvas" width="800" height="500"></canvas>
    <script type="text/javascript">
        let isDown = false;
        let beginPoint = null;
        const canvas = document.querySelector('#canvas');
        const ctx = canvas.getContext('2d');

        // 设置线条色彩
        ctx.strokeStyle = 'red';
        ctx.lineWidth = 1;
        ctx.lineJoin = 'round';
        ctx.lineCap = 'round';

        canvas.addEventListener('mousedown', down, false);
        canvas.addEventListener('mousemove', move, false);
        canvas.addEventListener('mouseup', up, false);
        canvas.addEventListener('mouseout', up, false);

        function down(evt) {
            isDown = true;
            beginPoint = getPos(evt);
        }

        function move(evt) {
            if (!isDown) return;
            const endPoint = getPos(evt);
            drawLine(beginPoint, endPoint);
            beginPoint = endPoint;
        }

        function up(evt) {
            if (!isDown) return;
            
            const endPoint = getPos(evt);
            drawLine(beginPoint, endPoint);

            beginPoint = null;
            isDown = false;
        }

        function getPos(evt) {
            return {
                x: evt.clientX,
                y: evt.clientY
            }
        }

        function drawLine(beginPoint, endPoint) {
            ctx.beginPath();
            ctx.moveTo(beginPoint.x, beginPoint.y);
            ctx.lineTo(endPoint.x, endPoint.y);
            ctx.stroke();
            ctx.closePath();
        }
    </script>
</body>
</html>

它的完成逻辑也很简朴:

  1. 我们在canvas画布上重要监听了三个事宜:mousedown、mouseup和mousemove,同时我们也创建了一个isDown变量;

  2. 当用户按下鼠标(mousedown,即起笔)时将isDown置为true,而放下鼠标(mouseup)的时刻将它置为false,如许做的优点就是能够推断用户当前是不是处于绘画状况;

  3. 经由过程mousemove事宜不停收集鼠标经由的坐标点,当且仅当isDown为true(即处于誊写状况)时将当前的点经由过程canvas的lineTo要领与前面的点举行衔接、绘制;

经由过程以上几个步骤我们就能够完成基础的画板功用了,但是事变并没那末简朴,细致的童鞋或许会发明一个很严重的题目——经由过程这类体式格局画出来的线条存在锯齿,不够腻滑,而且你画得越快,折线感越强。表现如下图所示:

为何会如许呢?

题目剖析

涌现该征象的缘由重如果:

  • 我们是以canvas的lineTo要领衔接点的,衔接相邻两点的是条直线,非曲线,因而经由过程这类体式格局绘制出来的是条折线;


  • 受限于浏览器对mousemove事宜的收集频次,人人都晓得在mousemove时,浏览器是每隔一小段时候去收集当前鼠标的坐标的,因而鼠标挪动的越快,收集的两个邻近点的间隔就越远,故“折线感越显著“;

怎样才画出腻滑的曲线?

要画出腻滑的曲线,实在也是有要领的,lineTo靠不住那我们能够采纳canvas的另一个画图API——quadraticCurveTo ,它用于绘制二次贝塞尔曲线。

二次贝塞尔曲线

quadraticCurveTo(cp1x, cp1y, x, y)

挪用quadraticCurveTo要领须要四个参数,cp1x、cp1y形貌的是控制点,而x、y则是曲线的尽头:

更多细致的信息可移步MDN

既然要运用贝塞尔曲线,很显然我们的数据是不够用的,要完全形貌一个二次贝塞尔曲线,我们须要:起始点、控制点和尽头,这些数据怎样来呢?

有一个很奇妙的算法能够协助我们猎取这些信息

猎取二次贝塞尔症结点的算法

这个算法并不难理解,这里我直接举例子吧:

  1. 假定我们在一次绘画中共收集到6个鼠标坐标,分别是A, B, C, D, E, F;

  2. 取前面的A, B, C三点,盘算出B和C的中点B1,以A为出发点,B为控制点,B1为尽头,应用quadraticCurveTo绘制一条二次贝塞尔曲线线段;


  3. 接下来,盘算得出C与D点的中点C1,以B1为出发点、C为控制点、C1为尽头继承绘制曲线;


  4. 顺次类推不停绘制下去,当到末了一个点F时,则以D和E的中点D1为出发点,以E为控制点,F为尽头完毕贝塞尔曲线。


OK,算法就是如许,那我们基于该算法再对现有代码举行一次升级革新:

let isDown = false;
let points = [];
let beginPoint = null;
const canvas = document.querySelector('#canvas');
const ctx = canvas.getContext('2d');

// 设置线条色彩
ctx.strokeStyle = 'red';
ctx.lineWidth = 1;
ctx.lineJoin = 'round';
ctx.lineCap = 'round';

canvas.addEventListener('mousedown', down, false);
canvas.addEventListener('mousemove', move, false);
canvas.addEventListener('mouseup', up, false);
canvas.addEventListener('mouseout', up, false);

function down(evt) {
    isDown = true;
    const { x, y } = getPos(evt);
    points.push({x, y});
    beginPoint = {x, y};
}

function move(evt) {
    if (!isDown) return;

    const { x, y } = getPos(evt);
    points.push({x, y});

    if (points.length > 3) {
        const lastTwoPoints = points.slice(-2);
        const controlPoint = lastTwoPoints[0];
        const endPoint = {
            x: (lastTwoPoints[0].x + lastTwoPoints[1].x) / 2,
            y: (lastTwoPoints[0].y + lastTwoPoints[1].y) / 2,
        }
        drawLine(beginPoint, controlPoint, endPoint);
        beginPoint = endPoint;
    }
}

function up(evt) {
    if (!isDown) return;
    const { x, y } = getPos(evt);
    points.push({x, y});

    if (points.length > 3) {
        const lastTwoPoints = points.slice(-2);
        const controlPoint = lastTwoPoints[0];
        const endPoint = lastTwoPoints[1];
        drawLine(beginPoint, controlPoint, endPoint);
    }
    beginPoint = null;
    isDown = false;
    points = [];
}

function getPos(evt) {
    return {
        x: evt.clientX,
        y: evt.clientY
    }
}

function drawLine(beginPoint, controlPoint, endPoint) {
    ctx.beginPath();
    ctx.moveTo(beginPoint.x, beginPoint.y);
    ctx.quadraticCurveTo(controlPoint.x, controlPoint.y, endPoint.x, endPoint.y);
    ctx.stroke();
    ctx.closePath();
}

在原有的基础上,我们创建了一个变量points用于保留之前mousemove事宜中鼠标经由的点,依据该算法可知要绘制二次贝塞尔曲线最少须要3个点以上,因而我们只要在points中的点数大于3时才最先绘制。接下来的处置惩罚就跟该算法一毛一样了,这里不再赘述。

代码更新后我们的曲线也变得腻滑了很多,如下图所示:

本文到这里就完毕了,愿望人人在canvas画板中“画”得兴奋~我们下次再会:)

以上就是怎样运用canvas画出腻滑的曲线?(代码)的细致内容,更多请关注ki4网别的相干文章!

  选择打赏方式
微信赞助

打赏

QQ钱包

打赏

支付宝赞助

打赏

  选择分享方式
  移步手机端
怎样运用canvas画出腻滑的曲线?(代码)【html5教程】

1、打开你手机的二维码扫描APP
2、扫描左则的二维码
3、点击扫描获得的网址
4、可以在手机端阅读此文章