Zu den Funktionen dieser Komponente gehören:
Bildzuschnitt (Ziehen Sie das Zuschneidefeld und ändern Sie die Größe des Zuschneidefelds);
Bildmosaik (Mosaik zeichnen, Mosaik löschen);
Bildvorschau, Bildwiederherstellung (zurück zum Originalbild, zurück zum verarbeiteten Bild);
Bild-Upload (Signatur erhalten, Bild hochladen).
2. Kernlogik2.1 Bildzuschnitt
Ermitteln Sie die Position des Zuschneidefelds (Rechteck) relativ zur Leinwand (oben links) sowie die Höhe und Breite des Zuschneidefelds. Holen Sie sich (getImageData) das Bildobjekt (ImageData) an der entsprechenden Position der Leinwand. Löschen Sie die Leinwand. Zeichnen Sie das von (putImageData) erhaltene Bildobjekt (ImageData) an der entsprechenden Position der Leinwand. Vorschaubild erzeugen.
2.2 Bildmosaik
Beim Mosaikzeichnen wird der Bereich in der Mitte des Mausstrichpfads (Pinselbreite) in andere Farben neu gezeichnet. Das allgemeine Ergebnis ist, dass die umgebenden Farben ähnlich sind.
Farbauswahlmethode:
1) Wenn Sie beispielsweise die Koordinaten (x, y) eines von der Maus gekreuzten Punktes haben, definieren Sie ein Rechteck mit den Koordinaten der oberen linken Ecke (x, y), 30 Pixel breit und 30 Pixel hoch. Wir teilen die Breite und Höhe des Rechtecks durch 5 (unterteilt in 5 Teile, die auf n Teile angepasst werden können), sodass es jetzt 25 kleine Gitter mit 6 Pixeln gibt. Jedes kleine Raster hat eine Breite und Höhe von 6 Pixel.
2) Dann erhalten wir zufällig ein kleines Raster und erhalten (getImageData) das Bildobjekt (ImageData) dieses kleinen Rasters. Anschließend erhalten wir zufällig die Farbfarbe (rgba: ImageD) eines bestimmten Pixels (Breite 1 Pixel, Höhe 1 Pixel). Bildobjekt ata.data[0], ImageData.data[1], ImageData.data[2], ImageData.data[3]); Schließlich setzen wir die Farbe jedes Pixels des ersten 6x6px kleinen Rasters auf color .
3) Für die Farben der anderen 24 kleinen Gitter befolgen Sie einfach 2 Schritte.
2.3 Klares Mosaik
Wir müssen ein Problem verstehen, egal ob es sich um das Zeichnen eines Mosaiks oder das Löschen eines Mosaiks handelt, das Wesentliche besteht darin, ein Bild zu zeichnen. Wir haben das Mosaik an einer bestimmten Stelle gezeichnet. Wenn wir es löschen, zeichnen wir das ursprüngliche Bildobjekt erneut an der aktuellen Stelle. Der Reinigungseffekt wird erreicht. Daher müssen wir eine Leinwand sichern, die genau mit dem Originalbild übereinstimmt. Beim Löschen müssen wir das Bild an der entsprechenden Position auf der Sicherungsleinwand abrufen und an die Position des Mosaiks zeichnen.
2.4 Bildvorschau
Die Bildvorschau dient dazu, den Bereich des Zuschneiderahmens und die Bildobjekte in diesem Bereich abzurufen. Dann zeichne es auf die Leinwand.
2.5 Stellen Sie das Bild auf das Originalbild wieder her
Räumen Sie die Leinwand frei und zeichnen Sie das Originalbild erneut
2.6 Wiederherstellen des manipulierten Bildes
Die Vorschau besteht darin, das Leinwandbildobjekt (ImageData) zu speichern, die Leinwand zu löschen und das gespeicherte Bildobjekt auf die Leinwand zu zeichnen.
2.7 Bild-Upload
Rufen Sie den Canvas-Bildpfad (toDataURL) ab und konvertieren Sie das erhaltene Base64-Bild in ein Dateiobjekt. hochladen.
3. Der vollständige Code lautet wie folgt:
<template> <div class=canvas-clip :loading=loading> <div v-show=isDrop class=canvas-mainBox ref=canvas-mainBox id=canvas-mainBox @mousedown.stop=startMove($event) > <div class=canvas-minBox left-up @mousedown.stop=startResize($event,0)></div> <div class=canvas-minBox up @mousedown.stop=startResize($event,1)></div> <div class=canvas-minBox right-up @mousedown.stop=startResize($event,2)></div> <div class=canvas- minBox rechts @mousedown.stop=startResize($event,3)></div> <div class=canvas-minBox rechts unten @mousedown.stop=startResize($event,4)></div> <div class=canvas-minBox left-down @mousedown.stop=startResize($event,5)></div> <div class=canvas-minBox left-down @mousedown.stop=startResize($event,6)></ div div> <div class=canvas-minBox left @mousedown.stop=startResize($event,7)></div> </div> <!-- Canvas--> <canvas class=canvas-area ref=canvas id=canvas :width=canvasWidth :height=canvasHeight @mousedown.stop=startMove($event) :class={hoverPaint:isMa,hoverClear:isMaClear} ></canvas> <!-- Backup-Canvas--> <canvas class=canvas-copy ref=canvasCopy :width=canvasWidth :height=canvasHeight></canvas> <div class=canvas-btns> <button v-if=backBtn @click=clipBack>Zurück</button> <button :class={active:btnIndex==0} @click= sourceImg>Originalbild</button> <button :class={active:btnIndex==1} @click=paintRectReady :disabled=isDisabled>Mosaik</button> <button :class={active:btnIndex==2} @click=paintRectClearReady :disabled=isDisabled>Radiergummi</button> <button :class={active:btnIndex==3 } @click=clipReady :disabled=isDisabled>Zuschneiden</button> <button :class={active:btnIndex==4} @click=clipPosition>Vorschau</button> <button @click=getSignature>Hochladen</button> <button class=close @click=canvasClose()>x</button> <!-- <div class=paint-size v-if=isMaClear ||. isMa> <span>Pinselgröße</span> <input :defaultValue=maSize v-model=maSize max=100 min=1 type=range> <span class=size-num>{{maSize}}</span> </div> --> </div> </div></template><script>axios aus axios importieren; md5 aus js-md5 importieren ;import req from ../../axios/config;export default { props: [imgUrl], data() { return { resizeFX: , movePrev: , canvasWidth: 800, // Leinwandbreite canvasHeight: 600, // Leinwandhöhe laden: false, isDrop: false, // Zuschneiden isMa: false, // Mosaik maSize: 30, // Mosaikgröße isMaClear: false, // Mosaik löschen backBtn: false, // Return-Schaltfläche isDisabled: false, // Schaltfläche deaktivieren btnIndex: 0, //Aktuelle Schaltfläche MouseX:'', // Mausposition MouseY:'', ClipEle: , // Zuschneidefeldelement CanvasDataSession: , // Canvas-Informationen vor Vorschau Canvas: , // Canvas ctx: , // Canvas-Kontext canvasCopy: , // Canvas kopieren ctxCopy: , // Canvas-Kontext kopieren uploadOption: { // Bild-Upload-Parameter Pfad: , Richtlinie: , Signatur: , Benutzername: } }; }, Mounted() { this.clipEle = this.$refs[canvas-mainBox]; this.canvas = this.$refs[canvas]; = this.$refs[canvasCopy]; this.ctxCopy = this.canvasCopy.getContext(2d); Erstellen Sie ein Bild draw() { var img = new Image(); img.setAttribute('crossOrigin', 'anonymous'); , 600); this.ctxCopy.drawImage(img, 0, 0, 800, 600); img.src = this.imgUrl + '?time=' + new Date().valueOf(); }, //Preview berechnet die Position des Zuschneidefelds (obere linke Koordinate) clipPosition() { this.isDisabled = true; this.backBtn = true; this.isMaClear = false; //Canvas position var canvasPx = this.canvas.offsetLeft, canvasPy = this.canvas.offsetTop; if (this.isDrop) { // Position des Zuschneidefelds var clipPx = this.clipEle.offsetLeft, clipPy = this.clipEle.offsetTop, x = clipPx - canvasPx, y = clipPy - canvasPy, w = this.clipEle.offsetWidth, h = this.clipEle.offsetHeight, // Vorschaubild zentrieren positionX = 400 - this.clipEle.offsetWidth / 2, positionY = 300 - this.clipEle.offsetHeight / 2; } else { // Kein Zuschneidefeld, speichere das komplette Bild var x = 0, y = 0, w = this.canvas.offsetWidth , h = this.canvas.offsetHeight, // Zentrieren Sie das Vorschaubild positionX = 0, positionY = 0; } var imageData = this.ctx.getImageData(x, y, w, h); this.canvasDataSession = this.ctx.getImageData( 0, 0, this.canvasWidth, this.canvasHeight ); this.ctx.clearRect(0, 0, this. canvasWidth, this.canvasHeight); this.ctx.putImageData(imageData, positionX, positionY); this.clipEle.style.display = none; this.canvasCopy.style.display = none }, // Rückkehr zum Vorschauzustand clipBack() { this.backBtn = false; = false ; this.isDrop = false; this.ctx.putImageData(this.canvasDataSession, 0, 0); block; // Originalbild sourceImg() { this.isMaClear = false; this.isMaClear = false; = new Image(); this.ctx.clearRect(0, 0, this.canvasWidth, this.canvasHeight); img.setAttribute('crossOrigin', 'anonymous'); img.onload = () => { this.ctx.drawImage(img, 0, 0, this.canvasWidth, this.canvasHeight); .imgUrl + '?time=' + new Date().valueOf(); this.canvasCopy.style.display = block }, // Holen Sie sich die Signatur getSignature() { // Canvas-Bild base64 zum Dateiobjekt var dataURL = this.canvas.toDataURL(image/jpg), arr = dataURL.split(,), mime = arr[0].match(/:( . *?);/)[1], bstr = atob(arr[1]), n = bstr.length, u8arr = new Uint8Array(n); (n--) { u8arr[n] = bstr.charCodeAt(n); } var obj = new Blob([u8arr], { type: mime }), time = new Date().toGMTString(), formData = new FormData(); formData.append(file, obj); // Holen Sie sich das Dateisuffix var suffix = formData.get(file).type.split(/)[1]; req .get(/carsource-api/upyun/sign, { suffix: suffix }) .then(response => { if (response.data.code === 0) { this.uploadOption.path = Response.data.data.path; formData.append(policy, Response.data.data.policy); formData.append(authorization, response.data.data.signatur); this.updateImg(formData); .catch(function(error) {} }, // Upload updateImg({ url : http://v0.api.upyun.com/tmp-img, Methode: POST, Daten: formData }).then(response => { if (response.data.code == 200) { this.$message.success(image Erfolgreich geändert); this.canvasClose(upload, Response.data.url.slice(4) }); Box-Zoom-Bewegung startResize(e, n) { this.resizeFX = n; document.addEventListener(mouseup, this.stopResize); stopResize(e) { $(document).off(mousemove, this.resizeDiv); this.movePrev = [e.pageX, e.pageY]; $(document).mousemove(this.moveDiv); document.addEventListener(mouseup, this.stopMove }, stopMove(e) { $(document).off(mousemove, this.moveEventListener(mouseup, this.stopMove); }, moveDiv(e) { // Mosaik if (this.isMa) { this.paintRect(e); } // Mosaik löschen if (this.isMaClear) { this.paintRectClear(e } // Crop if (this.isDrop) { var targetDiv = $(#canvas-mainBox), offsetArr = targetDiv.offset(); var chaX = e.pageX - this.movePrev[0], chaY = e.pageY - this.movePrev[1], ox = parseFloat(targetDiv.css(left)), oy = parseFloat(targetDiv.css(top)); targetDiv.css({ left: ox + chaX + px, top: oy + chaY + px }); this.movePrev = [e.pageX, e.pageY] }, resizeDiv(e) { e.preventDefault(); e.stopPropagation(); // Den Abstand vom Element, dessen Größe geändert werden muss, zur Seite ermitteln var targetDiv = $(#canvas-mainBox), offsetArr = targetDiv.offset(); = targetDiv.width() , eleSHeight = targetDiv.height(), ox = parseFloat(targetDiv.css(left)), oy = parseFloat(targetDiv.css(top)); // Ermitteln Sie die Mausposition und vergleichen Sie sie mit dem anfänglichen Offset des Elements, var chaX = e.pageX - offsetArr.left, chaY = e.pageY - offsetArr.top; this.resizeFX) { case 0: //Wenn die Bewegungsdistanz nahe an der Breite oder Höhe liegt, wird keine Änderung vorgenommen, wenn (chaX >= eleSWidth - 10 || chaY >= eleSHeight - 10) { return; } // Ermitteln Sie die Positionsdifferenz (me), legen Sie zuerst die Breite und Höhe fest und legen Sie dann die Position fest // Originalbreite und -höhe + ((me) *-1), Originalposition + (me) targetDiv.css({ width: eleSWidth + chaX * -1 + px, height: eleSHeight + chaY * -1 + px, left: ox + chaX + px, top: oy + chaY + px }); break; case 1: //Wenn die Bewegungsdistanz nahe an der Breite oder Höhe liegt, wird keine Änderung vorgenommen if (chaY >= eleSHeight - 10) { return; // Positionsdifferenz (me) abrufen, Breite festlegen und Zuerst die Höhe und dann die Position festlegen // Ursprüngliche Breite und Höhe + ((me) *-1), ursprüngliche Position + (me) targetDiv.css({ height: eleSHeight + chaY * -1 + px, top: oy + chaY + px }); break; case 2: //Wenn die Bewegungsdistanz nahe an der Breite oder Höhe liegt, wird keine Änderung vorgenommen if (chaX <= 10 || chaY >= eleSHeight - 10) { return; Differenz (me), Legen Sie zuerst die Breite und Höhe fest, legen Sie die Position fest // Originalhöhe + ((me) *-1), Originalbreite + ((me)), Originalposition + (me) targetDiv.css({ width : chaX + px, height: eleSHeight + chaY * -1 + px, top: oy + chaY + px }); ) { return; } // Ermitteln Sie die Positionsdifferenz (me), legen Sie zuerst die Breite und Höhe fest und legen Sie dann die Position fest // Originalbreite und -höhe + ((me) *-1), Originalposition + (me) targetDiv .css({ width: chaX + px }); break; case 4: //Wenn die Bewegungsdistanz nahe an der Breite oder Höhe liegt, wird keine Änderung vorgenommen if (chaX <= 10 || chaY <= 10) { return; Differenz (me), Legen Sie zuerst die Breite und Höhe fest, dann legen Sie die Position fest // Originalbreite und -höhe + ((me) *-1), Originalposition + (me) targetDiv.css({ width: chaX + px, height : chaY + px }); break; case 5: //Wenn die Bewegungsdistanz nahe an der Breite oder Höhe liegt, wird keine Änderung vorgenommen. if (chaY <= 10) { return; // Positionsdifferenz (me) abrufen, Breite und Höhe festlegen zuerst und dann die Position festlegen // Ursprüngliche Breite und Höhe + ((me) *-1), ursprüngliche Position + (me) targetDiv.css({ height: chaY + px }); Liegt die Bewegungsdistanz nahe an der Breite oder Höhe, wird keine Aktion durchgeführt, wenn (chaX >= eleSWidth - 10 ||. chaY <= 10) { return; // Ermitteln Sie die Positionsdifferenz ((me)), legen Sie zuerst die Breite und Höhe fest und legen Sie dann die Position fest // Originalbreite und -höhe + ((me) * -1), ursprüngliche Position + (me) targetDiv.css({ width: eleSWidth + chaX * -1 + px, height: chaY + px, left: ox + chaX + px }); 7: //Wenn die Bewegungsdistanz nahe an der Breite oder Höhe liegt, wird keine Änderung vorgenommen if (chaX >= eleSWidth - 10) { return; // Positionsdifferenz (me) abrufen, zuerst Breite und Höhe festlegen , und legen Sie dann die Position fest // Original Breite und Höhe + ((me) *-1), Originalposition + (me) targetDiv.css({ width: eleSWidth + chaX * -1 + px, left: ox + chaX + px }); break; default: break; }, // clipReady() { this.isMa = false }, //mosaik paintRectReady(); .btnIndex = 1; this.isMa = true; this.isDrop = false }, // Eraser paintRectClearReady() { this.btnIndex = 2; this.isMacle = false }, // Mosaik zeichnen paintRect(e) { var offT = this.canvas.offsetTop, / / Abstand von oben offL = this.canvas.offsetLeft, // Abstand von links x = e.clientX, y = e.clientY; if(this.mouseX - x > this.maSize/2 || x - this.mouseX > this.maSize/2 || this.mouseY - y > this.maSize/2 || y - this.mouseY > this.maSize/2){ var oImg = this.ctx.getImageData(x - offL ,y - offT,this.maSize,this.maSize); var w = oImg.height; //Der Grad des Mosaiks, je größer die Zahl, desto unschärfer ist sie. var num = 6; Canvas var stepW = w/ num; var stepH = h/num; //Hier sind die Pixel der Schleife Canvas for(var i=0;i<stepH;i++){ for(var j=0;j<stepW; j++){ //Erhalte die zufällige Farbe eines kleinen Quadrats. Dies ist die Variablenfarbe, die aus der zufälligen Position des kleinen Quadrats erhalten wird = this.getXY(oImg,j*num+Math.floor(Math.random()*num),i *num +Math.floor(Math.random()*num)); //Hier sind die Pixel des kreisförmigen kleinen Quadrats, for(var k=0;k<num;k++){ for(var l=0; l< num;l++){ //Setze die Farbe des kleinen Quadrats this.setXY(oImg,j*num+l,i*num+k,color); } } } } this.ctx.putImageData(oImg,x - offL ,y - offT) ; this.mouseX = e.clientX this.mouseY = e.clientY } }, getXY(obj,x,y){ var w = obj.width; var h = obj.height; var color = []; color[0] = d[4*(y*w+x)]; w+x)+1]; color[2] = d[4*(y*w+x)+2]; return color[3] = d[4*(y*w+x)+3]; ; }, setXY(obj,x,y,color){ var w = obj.width; var d = obj.data; d[4*(y*w+x)] = color[0]; d[4*(y*w+x)+1] = Farbe[1]; d[4*(y*w+x)+2] = Farbe[2]; d[4*(y*w+x)+3] = color[3]; }, // Mosaik löschen paintRectClear(e) { var offT = this.canvasCopy.offsetTop, // Abstand von oben offL = this.canvasCopy .offsetLeft, // Abstand nach links x = e.clientX, y = e.clientY, // Bilddaten an dieser Position des Originalbildes abrufen imageData = this.ctxCopy.getImageData( x - offL, y - offT, this.maSize, this.maSize ); this.ctx.putImageData(imageData, x - offL, y - offT); }, // Leinwand schließen(type , url) { this.$emit(isShowImgChange, type, url);</script><style Scoped>.canvas-clip { Position: behoben; unten: 0; Hintergrund: 000;}.canvas-mainBox { Position: absolut; 400px; Höhe links: 50%; Rand links: -150px; 1px solid #FFF; Cursor: move; z-index: 9009;}.canvas-minBox { position: absolute; width: 8px; height: 8px; : -4px; Cursor: nw-resize;}.up { top: -4px; margin-left: -4px; n-resize;}.right-up { top: -4px; right: ne-resize;}.right { top: 50%; right: e -resize;}.right-down { unten: -4px; rechts: -4px; Cursor: se-resize;}.down { unten: -4px; margin-left: -4px; Cursor: s-resize;}.left-down { unten: -4px; Cursor: sw-resize;}.left { top: 50%; ; links: -4px; Cursor: w-resize;}.canvas-btns { position: right: 50px; z-index: 9003;}.canvas-btns button { display: inline-blovk; border: none width: 30px; Schriftgröße: 15px;}.canvas-btns button.active { Hintergrund: rgb(32, 230, 32);}.canvas-btns button.close { Hintergrund: rgb(230, 72, 32);}.canvas-copy { Position: absolut; links: 50%; margin-left: -400px; z-index: 9007;}.canvas-mosatic { position: absolute; 50 %; Rand oben: -400 Pixel; margin-left: -400px; z-index: 9008;}.paint-size{ margin-top: 20px; 13px; color: #FFF; height: 30px; text-align: right;}.paint-size input{ Vertical-align: middle; display: inline-block; width: 15px;}.hoverClear{cursor: url('./paint.png'),auto;}.hoverPaint{ Cursor: url('./paint.png'),auto;}</style>
4. Die Darstellungen lauten wie folgt:
ZusammenfassenDas Obige stellt Ihnen der Editor basierend auf der HTML5-Leinwand vor, um die Zuschneide- und Mosaikfunktionen sowie die Cloud-Upload-Funktion zu realisieren. Wenn Sie Fragen haben, hinterlassen Sie mir bitte eine Nachricht Ich werde Ihnen rechtzeitig antworten. Ich möchte mich auch bei allen für die Unterstützung der VeVb-Kampfsport-Website bedanken!
Wenn Sie der Meinung sind, dass dieser Artikel für Sie hilfreich ist, können Sie ihn gerne erneut drucken. Bitte geben Sie die Quelle an. Vielen Dank!