Ich glaube, dass jeder beim Erlernen von Canvas oder bei der Verwendung von Canvas in der Projektentwicklung auf ein solches Bedürfnis stoßen sollte: ein Skizzenblock-Gadget zu implementieren, das geschrieben werden kann.
Nun, ich glaube, dass dies für Kinder, die mit Canvas besser vertraut sind, mit nur ein paar Dutzend Codezeilen möglich ist. Die folgende Demo ist ein einfaches Beispiel:
<!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; document.querySelector('#canvas'); const ctx = canvas.getContext('2d'); // Linienfarbe festlegen ctx.lineWidth = 1; ctx.lineJoin = 'round'; .lineCap = 'round'; canvas.addEventListener('mousedown', down, false); move, false); canvas.addEventListener('mouseup', up, false); function down(evt) { isDown = beginPos(evt); move(evt) { if (!isDown) return; const endPoint = getPos(evt); drawLine(beginPoint, endPoint } function; up(evt) { if (!isDown) return; drawLine(beginPoint, endPoint) { 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.closePath(); >
Auch die Implementierungslogik ist sehr einfach:
mousedown
, mouseup
und mousemove
und erstellen außerdem eine isDown
Variable.mousedown
), setzen Sie isDown
auf true
, und wenn der Benutzer die Maus niederlegt ( mouseup
), setzen Sie sie auf false
. Der Vorteil besteht darin, dass festgestellt werden kann, ob sich der Benutzer derzeit in einem Zeichnungszustand befindet ;mousemove
-Ereignis passiert. Nur wenn isDown
true
ist (dh im Schreibzustand), wird der aktuelle Punkt über die lineTo
-Methode mit dem vorherigen Punkt verbunden und gezeichnet Leinwand;Durch die oben genannten Schritte können wir die grundlegende Funktion des Zeichenbretts erkennen. Bei vorsichtigen Kinderschuhen kann es jedoch zu einem sehr ernsten Problem kommen: Die auf diese Weise gezeichneten Linien sind gezackt und nicht glatt genug, und Sie werden schneller Je mehr Sie zeichnen, desto stärker wird das Gefühl von unterbrochenen Linien. Die Leistung ist unten dargestellt:
Warum passiert das? ProblemanalyseDie Hauptgründe für dieses Phänomen sind:
Wir verbinden die Punkte mit der lineTo
-Methode von Canvas. Was zwei benachbarte Punkte verbindet, ist eine gerade Linie, keine Kurve. Was auf diese Weise gezeichnet wird, ist also eine Polylinie.
Jeder weiß, dass der Browser während mousemove
mousemove
kurzen Zeiträume die Koordinaten der aktuellen Maus erfasst. Je schneller sich die Maus bewegt, desto größer ist der Abstand zwischen den beiden erfassten benachbarten Punkten weg, desto offensichtlicher ist das Gefühl der Faltlinien;
Es gibt tatsächlich Möglichkeiten, glatte Kurven zu zeichnen. Wenn lineTo
unzuverlässig ist, können wir eine andere Zeichen-API von Canvas verwenden – quadraticCurveTo
, die zum Zeichnen quadratischer Bezier-Kurven verwendet wird.
quadratische Bézier-Kurve
quadraticCurveTo(cp1x, cp1y, x, y)
Für den Aufruf quadraticCurveTo
-Methode sind vier Parameter erforderlich, cp1x
und cp1y
die die Kontrollpunkte beschreiben, während x
und y
die Endpunkte der Kurve sind:
Nähere Informationen finden Sie auf MDN
Da wir eine Bezier-Kurve verwenden möchten, ist es offensichtlich, dass unsere Daten nicht ausreichen, um eine quadratische Bezier-Kurve vollständig zu beschreiben. Woher kommen diese Daten?
Es gibt einen sehr cleveren Algorithmus, der uns dabei helfen kann, diese Informationen zu erhalten
Algorithmus zum Erhalten quadratischer Bezier-SchlüsselpunkteDieser Algorithmus ist nicht schwer zu verstehen. Lassen Sie mich direkt ein Beispiel geben:
Angenommen, wir sammeln insgesamt 6 Mauskoordinaten in einem Gemälde, nämlich A, B, C, D, E, F
Nehmen Sie die vorherigen drei Punkte A, B, C
, berechnen Sie den Mittelpunkt B1
von B
und C
und verwenden Sie A
der Startpunkt, B
ist der Kontrollpunkt B1
ist der Endpunkt. Verwenden Sie quadraticCurveTo
um ein quadratisches Bezier-Kurvensegment zu zeichnen.
Berechnen Sie als Nächstes den Mittelpunkt C1
zwischen den Punkten C
und D
und zeichnen Sie die Kurve weiter mit B1
als Startpunkt, C
als Kontrollpunkt und C1
als Endpunkt.
Die Zeichnung wird analog fortgesetzt, wenn der letzte Punkt F
erreicht ist. Die Bezier-Kurve endet mit D1
, dem Mittelpunkt von D
und E
, als Startpunkt, E
als Kontrollpunkt und F
als Endpunkt.
OK, der Algorithmus sieht so aus, dann werden wir den vorhandenen Code basierend auf diesem Algorithmus aktualisieren:
let isDown = false;let points = [];let beginPoint = null;const canvas = document.querySelector('#canvas');const ctx = canvas.getContext('2d');//Legen Sie die Linienfarbe fest 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; points.push({x, y}); beginPoint = {x, y};}function move(evt) { if (!isDown) return; x, y}); if (points.length > 3) { const lastTwoPoints = points.slice(-2); 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; points.push({x, y}); if (points.length > 3) { const lastTwoPoints = points.slice(-2); const endPoint = lastTwoPoints[1]; , controlPoint, endPoint); } beginPoint = null; isDown = false; points = [];}function getPos(evt) { return { x: evt.clientX, y: evt.clientY }}function drawLine(beginPoint, controlPoint) { ctx.moveTo(beginPoint.x, beginPoint.y); ctx.quadraticCurveTo(controlPoint.x, controlPoint. y, endPoint.x, endPoint.y); ctx.closePath();}
Auf der Grundlage des Originals haben wir eine Variable points
erstellt, um die Punkte zu speichern, die die Maus im vorherigen mousemove
-Ereignis durchlaufen hat. Gemäß diesem Algorithmus sind mindestens 3 Punkte erforderlich, um eine quadratische Bezier-Kurve zu zeichnen, sodass wir nur die Punkte haben Punkte in points
Die Ziehung beginnt erst, wenn die Anzahl der Punkte größer als 3 ist. Die anschließende Verarbeitung ist genau die gleiche wie bei diesem Algorithmus, daher werde ich hier nicht auf Details eingehen.
Nach der Codeaktualisierung ist unsere Kurve viel glatter geworden, wie in der folgenden Abbildung dargestellt:
Dieser Artikel endet hier. Ich wünsche Ihnen allen viel Spaß beim Zeichnen auf Leinwand. Bis zum nächsten Mal:)
Wenn Sie sich für Kinderschuhe interessieren, können Sie hier klicken, um meinem Blog zu folgen. Alle neuen und interessanten Blogbeiträge werden hier so schnell wie möglich veröffentlicht
Das Obige ist der gesamte Inhalt dieses Artikels. Ich hoffe, dass er für das Studium aller hilfreich ist. Ich hoffe auch, dass jeder das VeVb Wulin Network unterstützt.