In diesem Artikel wird hauptsächlich Folgendes vorgestellt:
Name: Intelligentes Zeichenbrett
Technologie-Stack: HTML5, CSS3, JavaScript, mobil
Funktionsbeschreibung:
Vorschauadresse der Projektadresse
Vorschau
PC-Vorschau:
Mobile Vorschau:
Nachdem ich die Vorschau oben gelesen und das Smart Drawing Pad erlebt habe, denke ich, dass es in Ordnung ist, ihm einen Daumen nach oben zu geben. Egal, ob Sie sehr aufgeregt sind oder nicht, ich bin jedenfalls sehr stolz darauf Ich habe die Projektergebnisse erreicht. Eine Menge Unsinn, jetzt können Sie mit der Eingabe von Code beginnen, um den gewünschten Effekt zu erzielen! ! !
Hinweis: Die folgenden Projekteffekte beziehen sich hauptsächlich auf JavaScript. Das Folgende ist nur der Code, der Implementierungsideen bereitstellt , nicht der gesamte Code .
3. Projektergebnisse Schritt für Schritt erzielen(1) Analyseseite
Durch das Anwendungsfalldiagramm wissen wir, mit welchen Funktionen Benutzer unsere Website betreten können.
Was Benutzer tun können:
(2) HTML-Layout
Als ich HTML schrieb, führte ich CSS-Dateien und JS-Dateien ein
<!DOCTYPE html><html lang=en><head> <meta charset=UTF-8> <meta name=viewport content=width=device-width, initial-scale=1.0> <meta http-equiv=X-UA -Kompatibler Inhalt=ie=edge> <title>Smart Drawing Pad</title> <link rel=shortcut icon href=./image/favicon.png type=image/x-icon> <link rel=stylesheet href=./css/style.css></head><body> <canvas id=canvas></canvas> <div class=bg-btn></ div> <div class=color-group id=bgGroup> <h3>Hintergrundfarbe auswählen:</h3> <ul class=clearfix> <li class=bgcolor-item style=background-color: blau;></li> <li class=bgcolor-item style=background-color: schwarz;></li> <li class=bgcolor-item style=background-color: #FF3333;></li> <li class=bgcolor-item style=background-color: #0066FF;></li> <li class=bgcolor-item style=background-color: #FFFF33;></li> <li class=bgcolor-item style=background-color: #33CC66;></li> <li class=bgcolor-item style=background-color: grey;></li> <li class=bgcolor-item style=background- Farbe: #F34334;></li> <li class=bgcolor-item style=background-color: #fff;box-shadow: 0 1px 2px 0 rgba(32,33,36,0.28);></li> <li class=bgcolor-item style=background-color: #9B27AC;></li> <li class=bgcolor-item style=background-color: #4CB050;></li> <li class=bgcolor-item style=background-color: #029688;></li> </ul> <i class=closeBtn></i> </div> <div class=tools> <div class=container> <button class=save id=save <button class=brush active id=brush <button class=eraser id=eraser < button class=clear id=clear <button class=undo id=undo <button class=redo id=redo </div> </div> <div class=pen-detail id=penDetail> <i class=closeBtn></i> <p>Stiftgröße</p> <span class=circle-box><i id=thickness></i></span> <input type=range id=range1 min=1 max=10 value=1> <p>Stiftfarbe</p> <ul class=pen-color clearfix> <li class=color-item active style=background-color: black;></ li> <li class=color-item style=background-color: #FF3333;></li> <li class=color-item style=background-color: #99CC00;></li> <li class=color-item style=background -color: #0066FF;></li> <li class=color-item style=background-color: #FFFF33;></li> <li class=color-item style=background-color: #33CC66;></li> </ul> <p>Deckkraft</p> <i class=showOpacity></i> <input type=range id=range2 min=1 max=10 value=1> </ div> <script src=./js/main.js></script></body></html>
(3) Verwenden Sie CSS, um die Schnittstelle zu verschönern
Der CSS-Code kann die Benutzeroberfläche entsprechend den persönlichen Gewohnheiten verschönern, daher werde ich den CSS-Code hier nicht schreiben. Sie können sich den Projektcode direkt ansehen oder die Elemente aus den Entwicklertools überprüfen. Wenn Sie Fragen haben, können Sie privat mit mir chatten. Ich glaube nicht, dass das ein großes Problem ist.
(4) Verwenden Sie JS, um bestimmte Funktionen des Projekts zu implementieren
1. Vorbereitung
Bereiten Sie zunächst einen Container vor, bei dem es sich um ein Zeichenbrett handelt. Der Container wurde im vorherigen HTML geschrieben.
<canvas id=canvas></canvas>
Dann initialisieren Sie js
let canvas = document.getElementById('canvas');let context = canvas.getContext('2d'); Ich habe vor, die Zeichenfläche im Vollbildmodus zu gestalten, daher werde ich als Nächstes die Breite und Höhe canvas
let pageWidth = document.documentElement.clientWidth;let pageHeight = document.documentElement.clientHeight;canvas.width = pageWidth;canvas.height = pageHeight;
Da einige IEs kein canvas unterstützen, können wir, wenn wir mit dem IE kompatibel sein möchten, ein canvas erstellen, es dann mit excanvas initialisieren und exCanvas.js für IE hinzufügen. Wir berücksichtigen IE hier ausdrücklich nicht.
Aber wenn ich das Browserfenster auf meinem Computer ändere, skaliert das Zeichenbrett nicht adaptiv. Lösung:
// Denken Sie daran, die Funktion autoSetSize auszuführen. function autoSetSize(){ canvasSetSize(); // Beim Ausführen dieser Funktion werden zuerst die Breite und Höhe der Leinwand festgelegt. function canvasSetSize(){ let pageWidth = document.documentElement.clientWidth; pageHeight = document.documentElement.clientHeight; canvas.width = pageWidth; // Nachdem sich die Fenstergröße geändert hat, wird das Größenänderungsereignis ausgelöst, um die Breite und Höhe des Leinwandfensters zurückzusetzen.onresize = function(){ canvasSetSize( }}2. Erkennen Sie die Funktion des Zeichnens
Umsetzungsidee: Mausereignisse abhören und mit drawLine() die aufgezeichneten Daten zeichnen.
painting = false .mousedown ), wird painting auf true gesetzt, um anzuzeigen, dass gerade gemalt wird und die Maus nicht losgelassen wird. Zeichnen Sie die Mausklicks auf.mousemove ). Wenn sich die Maus zu schnell bewegt, kann der Browser nicht mit der Zeichengeschwindigkeit mithalten und es entstehen Lücken zwischen den Punkten. Daher müssen wir die gezeichneten Punkte mit Linien verbinden ( lineTo() ).mouseup ), setzen Sie painting auf false . Hinweis: Die Methode drawCircle muss eigentlich nicht geschrieben werden. Dies dient nur dazu, dass jeder versteht, wo er mit dem Klicken beginnen soll.
function listenToUser() { // Definieren Sie eine Variable, um den Pinselstatus zu initialisieren let painting = false; // Zeichnen Sie die letzte Position des Pinsels auf let lastPoint = {x: undefiniert, y: undefiniert}; = function (e){ painting = true; let x = e.clientX; let y = e.clientY; drawCircle(x,y,5); } //Mausbewegungsereignis canvas.onmousemove = function(e){ if(painting){ let x = e.clientX; let newPoint = {'x' :x,'y':y}; drawLine(lastPoint.x, lastPoint.y, newPoint.x, newPoint.y); Mausfreigabeereignis canvas.onmouseup = function(){ painting = false; }}// Punktfunktion zeichnen function drawCircle(x,y,radius){ // Nach der Generierung wird auf den Grafikzeichenbefehl verwiesen Pfad Pfad generieren. context.beginPath(); // Zeichne einen Bogen (Kreis) mit (x, y) als Mittelpunkt und Radius als Radius, // beginnend bei startAngle und endend bei endAngle, in der durch „gegen den Uhrzeigersinn“ angegebenen Richtung (die Standardeinstellung ist im Uhrzeigersinn). ) zu generieren. context.arc(x,y,radius,0,Math.PI*2); // Erzeugen Sie eine solide Grafik, indem Sie den Inhaltsbereich des Pfads füllen context.fill( // Nach dem Schließen des Pfads wird die Grafik Der Zeichenbefehl wird in die Kontextmitte umgeleitet. context.closePath();}function drawLine(x1,y1,x2,y2){ //Legen Sie die Linienbreite fest context.lineWidth = 10; //Legen Sie den Stil des Linienendes fest. context.lineCap = Round; // Legen Sie den Stil der Verbindung zwischen Linien fest context.lineJoin = Round; // moveTo(x,y) verschiebt den Strich zu den angegebenen Koordinaten x und y context.moveTo(x1,y1 ); / lineTo(x, y) zeichnet eine gerade Linie von der aktuellen Position zur angegebenen x- und y-Position context.lineTo(x2,y2); // Zeichne den grafischen Umriss durch Linien context.Stroke(); context.closePath();}3. Implementieren Sie die Radiergummifunktion
Umsetzungsideen:
eraserEnabled = false .click des Radiergummis an, klicken Sie auf den Radiergummi, ändern Sie den Radiergummistatus, eraserEnabled = true , und wechseln Sie die Klasse, um den aktivierten Effekt zu erzielen.eraserEnabled true ist, bewegen Sie die Maus und verwenden Sie context.clearRect() um eraser zu implementieren. Ich habe jedoch festgestellt, dass in der Canvas-API die ClearRect-Methode Pixel löschen kann, die ClearRect-Methode jedoch den rechteckigen Bereich löscht. Schließlich sind die Radiergummis der meisten Leute daran gewöhnt, rund zu sein, daher wird die leistungsstarke Funktion des Beschneidungsbereichs eingeführt ist die Clip-Methode. Der folgende Code verwendet context.clearRect() um den Radiergummi zu implementieren. Bitte sehen Sie sich den Schritt-für-Schritt-Abschnitt an, um zu erfahren, wie Sie Gummi-Sassafras besser umsetzen können.
let eraser = document.getElementById(eraser);let eraserEnabled = false;// Denken Sie daran, die Funktion listenToUser auszuführen function listenToUser() { // ... bedeutet, dass der zuvor geschriebene Code weggelassen wird // ... // Maus drücken Nächstes Ereignis canvas.onmousedown = function(e){ // ... if(eraserEnabled){//Um den Radiergummi zu verwenden context.clearRect(x-5,y-5,10,10) }else{ lastPoint = {'x':x,'y':y} } } // Mausbewegungsereignis canvas.onmousemove = function(e){ let x = e.clientX; if( !painting){return} if(eraserEnabled){ context.clearRect(x-5,y-5,10,10); }else{ var newPoint = {'x':x,'y':y}; drawLine(lastPoint.x, lastPoint.y,newPoint.y); } // ...}// Klicken Sie auf den Radierer eraser.onclick = function(){ eraserEnabled = true; eraser.classList.add('active');brush.classList.remove('active');}4. Implementieren Sie die Bildschirmlöschfunktion
Umsetzungsideen:
Holen Sie sich den Elementknoten.
Klicken Sie auf die Schaltfläche „Löschen“, um die Leinwand zu leeren.
let reSetCanvas = document.getElementById(clear);//Realisierung des Bildschirms reSetCanvas.onclick = function(){ ctx.clearRect(0,0,canvas.width,canvas.height); setCanvasBg('white');}// Funktion „Canvas-Hintergrundfarbe zurücksetzen“ setCanvasBg(color) { ctx.fillStyle = color; 0, Canvas.width, Canvas.height);}5. Implementieren Sie die Funktion zum Speichern als Bild
Umsetzungsideen:
let save = document.getElementById(save); // Bild herunterladen save.onclick = function(){ let imgUrl = canvas.toDataURL('image/png'); body.appendChild(saveA); saveA.href = imgUrl; saveA.download = 'mypic'+(new Date).getTime(); saveA.target = '_blank'; saveA.click();}6. Implementieren Sie die Funktion zum Ändern der Hintergrundfarbe
Umsetzungsideen:
let selectBg = document.querySelector('.bg-btn');let bgGroup = document.querySelector('.color-group');let bgcolorBtn = document.querySelectorAll('.bgcolor-item');let penDetail = document. getElementById(penDetail);let activeBgColor = '#fff';//Umschaltung der Hintergrundfarbe für implementiert (let i = 0; i < bgcolorBtn.length; i++) { bgcolorBtn[i].onclick = function (e) { // Stop bubbling e.stopPropagation(); for (let i = 0; i < bgcolorBtn.length ; i++) { bgcolorBtn[i].classList.remove(active); this.classList.add(active); this.style.backgroundColor; setCanvasBg(activeBgColor); } }}document.onclick = function(){ bgGroup.classList.remove('active');}selectBg.onclick = function(e){ bgGroup.classList.add(' active'); e.stopPropagation();}7. Implementieren Sie die Funktion zum Ändern der Pinseldicke
Umsetzungsideen:
let range1 = document.getElementById('range1');let lWidth = 2;let ifPop = false;range1.onchange = function(){ console.log(range1.value); console.log(typeof range1.value) thick. style.transform = 'scale('+ (parseInt(range1.value)) +')'; console.log(thickness.style.transform ) lWidth = parseInt(range1.value*2);}// Linienzeichnungsfunktion function drawLine(x1,y1,x2,y2){ // ... context.lineWidth = lWidth; // ...}// Klicken Sie auf den Pinsel . onclick = function(){ eraserEnabled = false; brush.classList.add('active' Popup-Box console.log('pop') penDetail.classList.add('active'); }else{ penDetail.classList.remove('active' } ifPop = !ifPop;}8. Implementieren Sie die Funktion zum Ändern der Pinselfarbe
Die Umsetzungsidee ähnelt der Änderung der Hintergrundfarbe des Zeichenbretts .
let aColorBtn = document.getElementsByClassName(color-item);getColor();function getColor(){ for (let i = 0; i < aColorBtn.length; i++) { aColorBtn[i].onclick = function () { for ( sei i = 0; i < aColorBtn.length; aColorBtn[i].classList.remove(active); this.classList.add(active); activeColor = this.style.backgroundColor; ctx.fillStyle = activeColor;9. Implementieren Sie die Funktionen zum Rückgängigmachen und Wiederherstellen von Änderungen
Umsetzungsideen:
canvasHistory Array (verwenden Sie toDataURL() Methode von Canvas, um einen Snapshot zu generieren, der ein Base64-Bild generiert);canvasHistory Array mithilfe drawImage() von Canvas neu. let undo = document.getElementById(undo);let redo = document.getElementById(redo);// ...canvas.onmouseup = function(){ painting = false; canvasDraw();}let canvasHistory = [];let step = -1; // Zeichenmethode function canvasDraw(){ step++; if(step < canvasHistory.length){ canvasHistory.length = step; Fügen Sie dem Verlauf eine neue Zeichnung hinzu. canvasHistory.push(canvas.toDataURL());}//Methode rückgängig machen .width,canvas.height); let canvasPic = new Image(); canvasPic.src = canvasHistory[step]; ctx.drawImage(canvasPic, 0, 0); } undo.classList.add('active'); }else{ undo.classList.remove('active'); / Redo-Methode function canvasRedo(){ if(step < canvasHistory.length - 1){ step++; canvasHistory[step]; canvasPic.onload = function () { // ctx.clearRect(0,0,canvas.width,canvas.height); } redo.classList.add( 'active'); }else { redo.classList.remove('active') warning('Bereits der neueste Datensatz'); }}undo.onclick = function(){ canvasUndo();}redo.onclick = function(){ canvasRedo();}10. Kompatibel mit mobilen Endgeräten
Umsetzungsideen:
true , das touch wird verwendet; false , mouse wird verwendet // ...if (document.body.ontouchstart !== undefiniert) { // Touch-Ereignis verwenden anvas.ontouchstart = function (e) { // Mit dem Berühren beginnen} canvas.ontouchmove = function (e) { // Mit dem Gleiten beginnen } canvas.ontouchend = function () { // Ende des Schiebevorgangs }}else{ // Mausereignis verwenden // ... } // ... 4. Auf Fallstricken herumtrampeln Problem 1: Wenn Sie das Browserfenster auf Ihrem Computer ändern, passt sich das Zeichenbrett nicht an.Lösung:
Bei der Onresize-Antwortereignisverarbeitung sind die erhaltenen Seitengrößenparameter die geänderten Parameter.
Wenn sich die Fenstergröße ändert, setzen Sie die Breite und Höhe der Leinwand zurück. Vereinfacht gesagt, weisen Sie nach der Änderung des Fensters „canvas.width“ und „canvas.height“ neu zu.
// Denken Sie daran, die Funktion autoSetSize auszuführen. function autoSetSize(){ canvasSetSize(); // Beim Ausführen dieser Funktion werden zuerst die Breite und Höhe der Leinwand festgelegt. function canvasSetSize(){ let pageWidth = document.documentElement.clientWidth; pageHeight = document.documentElement.clientHeight; canvas.width = pageWidth; // Nachdem sich die Fenstergröße geändert hat, wird das Größenänderungsereignis ausgelöst, um die Breite und Höhe des Leinwandfensters zurückzusetzen.onresize = function(){ canvasSetSize( }} Frage 2: Wenn die Breite der gezeichneten Linie relativ klein ist, ist das in Ordnung, aber sobald sie dicker ist, treten Probleme auf.Lösung: Schauen Sie sich die Dokumentation an und finden Sie die Methode heraus. Sie müssen lediglich den Code zum Zeichnen von Linien ändern.
// Linienzeichnungsfunktion function drawLine(x1,y1,x2,y2){ context.beginPath(); context.lineWidth = lWidth; //-----Add----- // Linienendestil festlegen. context.lineCap = Round; // Legen Sie den Stil der Verbindung zwischen Linien fest context.lineJoin = Round //-----Join----- context.lineTo( x2; y2); context.Stroke(); context.closePath();} Frage 3: Wie erreicht man einen runden Gummi-Sassafras?Lösung:
In der Canvas-API kann die ClearRect-Methode Pixel löschen, aber die ClearRect-Methode löscht einen rechteckigen Bereich. Schließlich sind die Radiergummis der meisten Leute daran gewöhnt, rund zu sein, daher wird die leistungsstarke Funktion des Beschneidungsbereichs eingeführt, nämlich die Clip-Methode. Die Nutzung ist ganz einfach:
ctx.save()ctx.beginPath()ctx.arc(x2,y2,a,0,2*Math.PI);ctx.clip()ctx.clearRect(0,0,canvas.width,canvas.height) ;ctx.restore();
Der obige Code realisiert das Löschen eines kreisförmigen Bereichs, das heißt, er implementiert zuerst einen kreisförmigen Pfad, verwendet diesen Pfad dann als Beschneidungsbereich und löscht dann die Pixel. Beachten Sie, dass Sie zuerst die Zeichenumgebung speichern und nach dem Löschen der Pixel zurücksetzen müssen. Wenn Sie nicht zurücksetzen, sind zukünftige Zeichnungen auf diesen Beschneidungsbereich beschränkt.
Frage 4: Wie kann ich mit mobilen Endgeräten kompatibel sein?1. Meta-Tag hinzufügen
Da der Browser die Seite zunächst skaliert, wenn sie auf dem Mobiltelefon angezeigt wird, können wir das Meta-Viewport-Attribut im Meta-Tag festlegen, um den Browser anzuweisen, die Seite nicht zu skalieren = Bildschirmbreite des Benutzergeräts
<meta name=viewport content=width=device-width,initial-scale=1,user-scalable=no,maximum-scale=1.0,minimum-scale=1.0/>/*Page width=Mobile width:width=device-width Benutzer kann nicht skalieren: user-scalable=keine Skalierung: Anfangsskalierung=1 maximale Skalierung: maximale Skalierung=1,0 minimale Skalierung: minimale Skalierung=1,0*/
2. Fast alle Touch-Ereignisse werden auf der mobilen Seite verwendet, was sich von der PC-Seite unterscheidet.
Da die mobile Seite Touch-Ereignisse verwendet, werden die H5-Attribute touchstart/touchmove/touchend verwendet. Die PC-Seite unterstützt jedoch nur Mausereignisse, daher ist eine Funktionserkennung erforderlich.
Beim touch -Ereignis werden die Koordinaten über .touches[0].clientX und .touches[0].clientY abgerufen, was vom mouse zu unterscheiden ist.
Nun, es ist kein großes Problem. Ich habe es nur versäumt, context.beginPath(); zu schreiben, und ich habe einige Zeit damit verbracht, den Fehler zu beheben Kommentare sind nicht standardisiert; die Programmierung ist nicht standardisiert, und mein Kollege hat zwei Zeilen, es ist besser, nach den dokumentierten Betriebsspezifikationen zu arbeiten, es riecht so gut! ! !
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.