Home >Web Front-end >H5 Tutorial >How to draw smooth curves using canvas? (code)
The content of this article is about how to use canvas to draw smooth curves? (code). It has certain reference value. Friends in need can refer to it. I hope it will be helpful to you.
Background Summary
I believe that everyone should have encountered such a need when learning canvas or using canvas in project development: to implement a small drawing board that can be written tool.
Well, I believe that for children who are more familiar with canvas, this can be done with just a few dozen lines of code. The following demo is a simple example:
nbsp;html> <title>Sketchpad demo</title> <style> canvas { border: 1px blue solid; } </style> <canvas></canvas> <script> 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>
Its implementation logic is also very simple:
We mainly listen to three events on the canvas canvas: mousedown, mouseup and mousemove, and we also create an isDown variable;
When the user presses the mouse (mousedown), set isDown to true, and when the user puts down the mouse (mouseup), set it to false. The advantage of this is It can be judged whether the user is currently in the drawing state;
Continuously collects the coordinate points that the mouse passes through through the mousemove event. If and only if isDown is true (that is, in the writing state), it will The current point is connected and drawn with the previous point through the lineTo method of canvas;
Through the above steps, we can realize the basic drawing board function, but things don’t work. It's not that simple. Careful children's shoes may find a very serious problem - the lines drawn in this way are jagged and not smooth enough, and the faster you draw, the stronger the sense of folding. The performance is as shown in the figure below:
# Why is this happening?
Problem Analysis
The main reason for this phenomenon is:
We use the lineTo method of canvas to connect the points , connecting two adjacent points is a straight line, not a curve, so what is drawn in this way is a polyline;
How can we draw a smooth curve?
There are actually ways to draw smooth curves. If lineTo is unreliable, we can use another drawing API of canvas - quadraticCurveTo, which is used to draw quadratic Bezier curves. Quadratic Bezier CurvequadraticCurveTo(cp1x, cp1y, x, y)Calling the quadraticCurveTo method requires four parameters. cp1x and cp1y describe the control points , and x and y are the end points of the curve:More detailed information can be found on MDNSince you want to use Bezier curve, obviously our data is not enough.
To completely describe a quadratic Bezier curve, we need: starting point, control point and end point, how do these data come from?
There is a very clever algorithm that can help us obtain this informationAlgorithm for obtaining quadratic Bezier key pointsThis algorithm is not difficult to understand, here I will directly Let’s give an example: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画板中“画”得愉快~我们下次再见:)
The above is the detailed content of How to draw smooth curves using canvas? (code). For more information, please follow other related articles on the PHP Chinese website!