Kürzlich hat der Autor eine Anforderung: Eine Textgruppe wird um den Ring herum angezeigt Bewegen Sie die Maus über den kleinen blauen Punkt über dem Ring, um das Dreieck auszustrahlen und dann den Text anzuzeigen. Schauen wir uns zunächst den Animationseffekt an!
Wie im Bild oben gezeigt, muss beim Platzieren der Maus auf dem entsprechenden kleinen blauen Punkt ein dreieckiger Strahl ausgesendet werden, und der entsprechende Text wird außerhalb des Dreiecks angezeigt, und der kleine blaue Punkt wird zu einem kleinen weißen Punkt.
Wenn der Benutzer oben Inhalte eingibt, werden die Inhalte um den Ring unten herum hinzugefügt. Wie im Bild oben gezeigt.
Die ursprüngliche Idee des Autors bestand darin, CSS zur Implementierung zu verwenden, genau wie das dynamische Sekundärmenü im Bild unten.
Wenn man jedoch bedenkt, dass der Inhalt am Rand des Rings variabel ist und um den Ring herum positioniert werden muss, kann es schwierig sein, CSS zu implementieren. Also wow, der Autor hat beschlossen, Canvas zu verwenden, um dies zu erreichen. (Der Autor hat sich erst vor kurzem mit Canvas beschäftigt. Wenn etwas nicht stimmt, akzeptiere ich Ihre Korrekturen).
Implementierungsprozess:Erste:
Der HTML-Teil des Codes lautet wie folgt:
<canvas style=margin-left: 50px;padding-top: 20px; display:block id=canvas > Die aktuelle Version Ihres Browsers unterstützt kein Canvas</canvas>
Die spezifischen Implementierungsschritte sind wie folgt:
1. Zeichnen Sie einen großen Kreis.
Verwenden Sie die Canvas-Methode: context.arc(x, y, radius, startAngle, endAngle [, gegen den Uhrzeigersinn]);
x, y: Kreismittelpunktkoordinaten, Radius: Kreismittelpunktradius, startAngle: Zeichnen des Startbogenmaßes, endAngle: Zeichnen des Endbogenmaßes, [, gegen den Uhrzeigersinn]: optionaler Parameter, ob der Bogen im oder gegen den Uhrzeigersinn gezeichnet werden soll.
Um das Zeichnen zu erleichtern, hat der Autor den Ursprung der Leinwand von der vorherigen oberen linken Ecke in die Mitte der Leinwand verschoben.
Der vom Autor berechnete Radius des Rings beträgt r-80
canvas.width = 500canvas.height = 500//Berechnen Sie den Radius der Leinwandmitte, sei r = 500/2//Verschieben Sie den Ursprung der Leinwand in die Mitte der Leinwand, wenn die Schnittstelle initialisiert wird ctx.translate(r ,r) //Bewege den Pinsel auf rund
Der spezifische Code lautet wie folgt:
//Canvas-Initialisierung let canvas = document.getElementById('canvas')let ctx= canvas.getContext('2d')let ratio = getPixelRato(ctx)canvas.width = 500canvas.height = 500//Berechnen Sie den Radius der Mitte der Leinwand let r = 500 / 2// Wenn die Schnittstelle initialisiert wird, verschieben Sie den Ursprung der Leinwand in die Mitte der Leinwand ctx.translate(r,r) //Bewegen Sie den Pinsel zum Kreis ctx.lineWidth = 3; //Legen Sie die Linienbreite des Pinsels fest ctx.beginPath(); //Starten Sie den Pinsel//Zeichnen Sie die Verlaufskantenfarbe der Kante des Kreises var arcColor = ctx.createLinearGradient(-170, -170, 0, 170)arcColor.addColorStop(0, '#8ec1ff')arcColor.addColorStop(0.2, '#83beff')arcColor.addColorStop(0.5, '#75b1ff')arcColor.addColorStop(0.7,'#5998ff')arcColor.addColorStop(1, '#2065ff')ctx .StrokeStyle= arcColor;//Legen Sie die Farbe des Pinsels fest ctx.arc(0,0,r - 80,0,2*Math.PI,false) //Zeichnen Sie einen Kreis, Koordinaten 0,0, Radius 250-80, Vollkreis (0 -360 Grad), false bedeutet im Uhrzeigersinn ctx.closePath()ctx.Stroke() //DrawingDie Zeichnungsergebnisse sind wie folgt
2. Zeichnen Sie das Hintergrundbild in die Mitte des Rings (der Ursprung der aktuellen Leinwand ist die Mitte der Leinwand).
drawImage(image, dx, dy, dWidth, dHeight)
Bild: Canvas-Bildressource, z. B. <img>-Bild, SVG-Bild, Canvas-Element selbst usw.
dx, dy: Planen Sie einen Bereich auf der Leinwand, um Bilder zu platzieren. dx sind die horizontalen und vertikalen Koordinaten der oberen linken Ecke dieses Bereichs.
dWidth, dHeight: Planen Sie einen Bereich auf der Leinwand, in dem Bilder platziert werden sollen, sowie die Breite und Höhe dieses Bereichs.
Die folgenden Koordinaten wurden vom Autor berechnet
let image = new Image()image.src = 'image/quan.png'image.onload = () => { // Den Ursprung in die Mitte verschieben ctx.drawImage(image,-140,-140,280,280)}Die Zeichnungsergebnisse sind wie folgt:
3. Zeichnen Sie Text und kleine Punkte auf den Ring (der Ursprung der aktuellen Leinwand ist die Mitte der Leinwand).
Zeichenziele für Text und kleine Punkte:
3.1 Kleine Punkte werden gleichmäßig auf dem großen Ring angezeigt
3.2 Der Text ist außerhalb der kleinen Punkte etwas verstreut
Lösung:1. Der Autor verwendet ein Array, um die aktuellen Wörter zu speichern
let textArr = ['Weites Meer und Himmel','Technische Möglichkeiten','Starke Mittel','Wartungskontrolle','Leben und arbeiten Sie in Frieden und Zufriedenheit','Beobachten Sie die Blumen','Den letzten Schliff geben',' „Befreien Sie sich von der Schlacke“, „Gegen Sie den Wind“, „Karriereentwicklung“]
2. Da die Anzahl der kleinen Punkte und die Anzahl der Wörter gleich sind, entspricht die Anzahl beider der Länge des Arrays textArr oben.
3. Der Bogenmaß eines Vollkreises beträgt 2π. Damit die kleinen Punkte den Ring gleichmäßig teilen, berechnet der Autor zunächst den Bogenmaß des Punktes, an dem sich jeder kleine Punkt befindet.
for(let i = 0;i<lengths;i++){ // Bogenmaß berechnen let rad = 2*Math.PI/lengths*i}4. Mithilfe trigonometrischer Funktionen können die Koordinaten (x, y) des aktuellen kleinen Punkts auf der Leinwand berechnet werden (der Ursprung der aktuellen Leinwand ist die Mitte der Leinwand).
Darunter die Beziehung zwischen Bogenmaß, kleinem Punkt, Ring, Ringradius und Leinwandursprung. Der Autor zeichnete ein Bild, um sie zu beschreiben.
Berechnen Sie die Koordinaten des Textes:
// Berechnen Sie die Koordinaten des Mittelpunkts des kleinen Kreises let x = (r - 40)*Math.cos(rad)let y = (r - 40)*Math.sin(rad)
Berechnen Sie die Koordinaten des kleinen Punkts: Da der Mittelpunkt des kleinen Punkts auf dem Ring liegen muss, lauten die berechneten horizontalen und vertikalen Koordinaten wie folgt:
// Berechnen Sie die Koordinaten des Textes let x = (r - 80)*Math.cos(rad) let y = (r - 80)*Math.sin(rad)
Der spezifische Code lautet wie folgt:
// Text zeichnen ctx.font = '13px Arial'ctx.textAlign = 'center'ctx.textBaseline = 'middle'ctx.fillStyle=#000000let lengths = textArr.lengthtextArr.forEach(function(text,i){ //radians let rad = 2*Math.PI/lengths*i // Berechnen Sie die Koordinaten des Mittelpunkts des kleinen Kreises let x = (r - 40)*Math.cos(rad) let y = (r - 40)*Math.sin(rad) ctx.fillText(text,x+0.5,y+0.5)});// Kleine Punkte zeichnen for(let i = 0;i<lengths;i++){ // // let rad = 2*Math.PI/lengths*i let x = (r - 80)*Math.cos(rad) let y = (r - 80)*Math.sin(rad)// // Kleine graue durchscheinende Punkte am Rand zeichnen ctx.beginPath() ctx.fillStyle = 'rgba(226,235,250, 0,8)' ctx.arc(x,y,8,0,2*Math.PI,false) ctx.closePath() ctx.fill() // Kleine blaue Punkte zeichnen ctx.beginPath() ctx.fillStyle = '#208fe5' ctx.arc(x,y,4,0,2*Math.PI,false) ctx.closePath( ) ctx .füllen() }Die Zeichnungsergebnisse sind wie folgt:
4. Zeichnen Sie außerhalb jedes kleinen Punktes ein Dreieck (der Ursprung der aktuellen Leinwand ist die Mitte der Leinwand).
4.1 Da Sie eine Dreiecksform zeichnen möchten, besteht die Idee beim Zeichnen eines Dreiecks darin, Linien zu beiden Seiten mit der Mitte des aktuellen kleinen Punkts als Ausgangspunkt zu zeichnen und dann die Form mit ctx.fill () zu schließen Füllen Sie den Innenraum mit Farbverlauf.
Zeichnen Sie ein Dreieck: Die Koordinaten werden von selbst berechnet. Der Autor addiert und subtrahiert 35 auf der Abszisse und 70 auf der Ordinate (was auch immer Sie wollen, hahaha)
//Starte den Pinsel ctx.beginPath() ctx.moveTo(x,y) ctx.lineTo(x-35,y+70) ctx.lineTo(x+35,y+70) ctx.closePath()
Zeichnen Sie den Text unterhalb des Dreiecks: (Um ihn vom vorherigen Text zu unterscheiden, habe ich hier Rot für meinen Text verwendet.)
ctx.fillStyle= '#e3211c' ctx.fillText(textArr[i],x,y+75)
Der spezifische Code lautet wie folgt:
for(let i = 0;i<lengths;i++){ // // let rad = 2*Math.PI/lengths*i let x = (r - 80)*Math.cos(rad) let y = (r - 80)*Math.sin(rad) // // Dreieck zeichnen // // ctx.rotate( -Math.PI / 4) ctx.beginPath() //Starte den Pinsel ctx.moveTo(x,y) ctx.lineTo(x-35,y+70) ctx.lineTo(x+35,y+70) ctx.closePath() // // Farbverlauf festlegen- - ->Farbe von der Mitte zu beiden Seiten hinzufügen var sColor = ctx.createLinearGradient (x,y,x+18,y+50) sColor.addColorStop(0,'rgba(106,128,243,0.5)') sColor.addColorStop(0.6,'rgba(83,183,243,0.5)') sColor.addColorStop(0.7,'rgba(129,200,224,0.5)') sColor.addColorStop(0.8,'rgba(130,219,251,0.5)') sColor.addColorStop(1,'rgba(195,228,223,0.5)') ctx.fillStyle= sColor ctx.fill() ctx.fillStyle= '#e3211c' ctx.fillText(textArr[i],x,y+75)}Die Zeichnungsergebnisse sind wie folgt:
4.2 Die Anforderung besteht darin, dass sich die Richtung jedes Dreiecks nach außen ausbreitet und die Richtung der Dreiecke jetzt nach unten zeigt. Daher müssen Sie jetzt die Leinwandrotationsmethode verwenden.
ctx.save() ctx.translate(x,y) // Der Drehwinkel ist auf jeden kleinen Punkt zentriert ctx.rotate( rad - Math.PI/2 ) // Weil der kleine Punkt ctx.translate(- x, - y) Lassen Sie den Code zum Zeichnen von Dreiecken und Text weg.
Aus der Berechnung ist ersichtlich, dass der Drehwinkel des Dreiecks, wenn man den Mittelpunkt des kleinen Punkts als Startpunkt der Drehung nimmt, der Bogen des aktuellen kleinen Punkts minus π/2 sein sollte, da die Startposition der Drehung immer ist beginnt in der positiven Richtung der x-Koordinatenachse, das heißt, es beginnt bei 0 Bogenmaß, aber jetzt haben die Dreiecke alle π/2 Bogenmaß, also:
Bogenmaß der Rotation = Bogenmaß des kleinen Punktes – π/2
Denken Sie daran, beim Drehen die Canvas-Statusspeichermethode save() zu verwenden.
„restore()“ entfernt den gespeicherten Canvas-Status nacheinander von oben im Stapel. Wenn kein gespeicherter Canvas-Status vorhanden ist, ändert sich bei der Ausführung dieser Methode nichts.
Denken Sie daran, am Ende die Methode „restore()“ zu verwenden. An diesem Punkt vergoss der Autor Tränen des Bedauerns. . .
Spezifischer Code:
for(let i = 0;i<lengths;i++){ // // let rad = 2*Math.PI/lengths*i let x = (r - 80)*Math.cos(rad) let y = (r - 80)*Math.sin(rad) // Zeichne ein s-Dreieck ctx.save() // Der Drehwinkel ist auf jedem kleinen Punkt zentriert, da die kleinen Punkte am Anfang sind ctx.translate(x,y) ctx.rotate( rad - Math.PI/2 ) ctx.translate(-x, -y) // Starten Sie den Pinsel ctx.beginPath() ctx.moveTo(x,y) ctx.lineTo(x-35,y+ 70 ) ctx.lineTo(x+35,y+70) ctx.closePath() //Farbverlauf festlegen --->Farbvariable von der Mitte zu beiden Seiten hinzufügen sColor = ctx.createLinearGradient (x,y,x+18,y+50) sColor.addColorStop(0,'rgba(106,128,243,0.5)') sColor.addColorStop(0.6,'rgba(83,183,243,0.5)') sColor.addColorStop(0.7,'rgba(129,200,224,0.5)') sColor.addColorStop(0.8,'rgba(130,219,251,0.5)') sColor.addColorStop(1,'rgba(195,228,223,0.5)') ctx.fillStyle= sColor ctx.fill() ctx.fillStyle= '#e3211c' ctx.fillText(textArr[i],x,y+75) ctx.restore()}Zeichnen Sie das Ergebnis auf:
Schauen Sie genauer hin, was? ? ? Einige Texte stehen aufgrund von Rotationsproblemen auf dem Kopf. Durch Beobachtung ergibt sich, dass der Text auf dem Kopf steht, wenn das Bogenmaß größer als π ist.
Es ist Zeit, eine Welle von Urteilen zu verfassen. . . .
So drehen Sie Text:
function rotateContext(ctx, x, y, Degree) { // Text drehen ctx.translate(x, y) // ctx.rotate(degree * Math.PI / 180) ctx.rotate(degree) ctx.translate(-x , -y) }Bestimmen Sie kleine Punkte, deren Bogenmaß größer als π ist
if (rad > Math.PI) { // Da der Text am Rand des Dreiecks angezeigt werden muss, sollte sich der Text mit dem Dreieck drehen, damit er nach der Drehung immer am Rand des Dreiecks gehalten werden kann , der Text wird angezeigt, wenn das Bogenmaß größer als π ist. Drehen Sie das Problem um, also drehen Sie den Text ctx.save() ctx.beginPath() // Drehen Sie den Text rotateContext(ctx, x, y+75, Math.PI) ctx.font = '13px Arial' ctx.textAlign = 'center' ctx.fillStyle = #ff2238 ctx.fillText(textArr[i], x, y+ 75) ctx.restore()} else { ctx.fillStyle = '#ff2238' ctx.fillText(textArr[i ], x, y + 75)}Die Zeichnungsergebnisse sind wie folgt:
Wir freuen uns auf den Sieg, zumindest haben wir einen groben Plan. Die Revolution ist noch nicht gelungen, und Genossen müssen noch hart arbeiten. !
5. Das Folgende ist die Implementierung. Wenn sich die Maus über dem kleinen Punkt befindet, werden das Dreieck am Rand und der Text am Rand des Dreiecks angezeigt, der Text am Rand des Kreises wird jedoch nicht angezeigt.
Idee:1. Binden Sie das Mauseingabeereignis an die Leinwand
2. Bestimmen Sie, ob die Koordinaten der aktuellen Mausposition auf der Leinwand mit den Koordinaten in der Nähe eines kleinen Punkts übereinstimmen. Wenn ja, zeigen Sie das Dreieck an, das dem kleinen Punkt entspricht.
5.1 Binden Sie das Mousemove-Ereignis an die Leinwand: Die Maus befindet sich über dem Ereignis
canvas.addEventListener('mousemove',clickEvent)5.2 Berechnen Sie die aktuellen Koordinaten der Maus auf der Leinwand
Die Berechnungsmethode lautet: Verwenden Sie die aktuellen Koordinaten der Maus auf dem DOM, um den Abstand vom linken oder oberen Rand der Leinwand zu subtrahieren und den Abstand der Leinwand zu berechnen.
Die drawOne-Methode in der folgenden Abbildung ist die Zeichenmethode, die später im Artikel erläutert wird.
function clickEvent() { // Die Koordinaten der Mausposition let x = event.clientX - canvas.getBoundingClientRect().left let y = event.clientY - canvas.getBoundingClientRect().top drawOne(x,y)}5.3, da die oben berechneten Koordinaten der Maus auf der Leinwand mit der oberen linken Ecke der Leinwand als Ursprung berechnet werden, der Ursprung der aktuellen Leinwand jedoch bereits in die Mitte der Leinwand (250.250) verschoben wurde, also bei Verwendung um festzustellen, ob es sich bei einem Klick um kleine Punkte handelt Sie müssen 250 von den horizontalen und vertikalen Koordinaten abziehen, um sie mit den Koordinaten des kleinen Punktes auf der aktuellen Leinwand zu vergleichen. Ich weiß nicht, warum der Unterschied in der y-Richtung besteht des Autors beträgt 260 statt 250. Der Autor hat also 260 in y-Richtung subtrahiert.
Der Code lautet wie folgt:
Darunter sind Cx, Cy die Koordinaten der Maus auf der Leinwand (die obere linke Ecke der Leinwand ist der Ursprung), x, y sind die Koordinaten des aktuellen kleinen Punkts,
Der Autor berechnete direkt die Position von 15 Pixel in der Nähe der Mitte des kleinen Punkts, alle Dreiecke wurden angezeigt und der kleine Punkt wurde weiß.
Das Wichtigste ist, dass Sie bei jedem Neuzeichnen die vorherige Leinwand löschen müssen: Denken Sie daran, die Methode „clearRect“ zum Löschen der Leinwand zu verwenden
let XX = Cx - 250let YY = Cy- 260let leftX = x - 15 let rightX = x + 15let topY = y - 15let bottomY = y + 15if (XX >= leftX && XX <= rightX && YY <= BottomY && YY > = topY ) {//Es wird angeklickt. . . . . . //Den Zeichnungscode in die Mitte schreiben}Dem Code folgt ein Link:
6. Definieren Sie eine Eingabe auf der Schnittstelle und binden Sie das Änderungsereignis an die Eingabe.
Implementierung: Die Schnittstelle wird jedes Mal neu gezeichnet, wenn sich der Wert in der Eingabe ändert.
HTML-Code:
<input type=text id=inpt style=margin-left: 100px;margin-top: 50px placeholder=Please enter...>
js-Code:
let inpt = document.getElementById('inpt') inpt.addEventListener('change', function () { if (inpt.value !== '') { textArr.push(inpt.value) drawAll(2) //This Die Methode ist die Zeichenmethode, der Quellcode wird später im Artikel angegeben}})7. Es liegt ein Problem vor, wenn Sie auf die Schnittstelle klicken und die Schnittstelle neu zeichnen.
Wie unten gezeigt:
Da sich die Koordinaten der Maus jedes Mal ändern, müssen Sie den Inhalt um den Ring herum löschen und neu zeichnen, da sich die Koordinaten der Maus ändern. Sie müssen also die Leinwand freimachen, um dynamische Effekte zu erzielen.
clearRect() wird sehr häufig beim Zeichnen von Canvas-Animationen verwendet. Es löscht kontinuierlich den Canvas-Inhalt und zeichnet ihn dann, um einen Animationseffekt zu erzeugen.
clearRect() kann einen rechteckigen Bereich im Canvas des Canvas-Elements transparent machen.
context.clearRect(x, y, width, height);
x, y: x-, y-Koordinaten der oberen linken Ecke des Rechtecks.
Breite, Höhe: Die Breite und Höhe des freigeräumten rechteckigen Bereichs.
Da clearRect() nur den rechteckigen Bereich der Leinwand löschen kann, wird bei jedem Löschen auch das Hintergrundbild in der Mitte gemeinsam gelöscht.
Daher muss das Hintergrundbild jedes Mal neu geladen werden, und das Laden des Bildes dauert eine gewisse Zeit, sodass es jedes Mal blinkt, wenn es angezeigt wird.
Lösung:drawImage(image, dx, dy, dWidth, dHeight)
Der Parameter Bild: Canvas-Bildressource, z. B. <img>-Bild, SVG-Bild, Canvas-Element selbst usw.
Dann können Sie eine andere Leinwand zum Zwischenspeichern von Bildern verwenden.
Verwenden Sie eine zusätzliche Leinwand, um das Hintergrundbild zu zeichnen, aber für diese Leinwand, die nicht in der Benutzeroberfläche angezeigt wird: display:none, und verwenden Sie sie dann, um die Leinwand zu löschen und das zwischengespeicherte Leinwandobjekt direkt in der Mitte der anzuzeigenden Leinwand zu rendern Das heißt, es ist nicht erforderlich, Bilder einmal zu laden.
HTML-Code:
<canvas width=280 height=280 style=margin-left: 50px;padding-top: 20px; display:none> </canvas>
js-Code:
//Caching verwenden, um das Flash-Problem neu gezeichneter Bilder zu lösen var tempCanvas = document.getElementById('canvas2')const tempCtx = tempCanvas.getContext('2d')tempCanvas.width = 280; tempCanvas.height = 280let image = new Image( )image.src = 'image/quan.png'image.onload = () => { // Der Ursprung verschiebt sich in die Mitte tempCtx.drawImage(image,0,0,280,280)}Zeichnen Sie nach dem Löschen der Leinwand die zwischengespeicherte Leinwand:tempCanvas direkt beim Neuzeichnen des Bildes.
// Zeichne die zwischengespeicherte Leinwand direkt auf die Schnittstelle (die Zwischenreifenschnittstelle wird zwischengespeichert) ctx.drawImage(tempCanvas,-140,-140)
Okay, es ist mir gelungen, hier ist das Ergebnisbild:
Die Quellcode-Adresse lautet wie folgt:
https://github.com/Linefate/Dynamic-effect-of-canvas-ring.git
ZusammenfassenDas Obige ist die Einführung des Herausgebers in die Verwendung von HTML5-Canvas zum Zeichnen von Ringanimationen. Wenn Sie Fragen haben, hinterlassen Sie mir bitte eine Nachricht und der Herausgeber wird Ihnen rechtzeitig antworten. Ich möchte mich auch bei allen für die Unterstützung der VeVb-Kampfsport-Website bedanken!