Inhaltsverzeichnis
Code
Heim Web-Frontend H5-Tutorial Canvas implementiert die Bild-Graffiti-Funktion (mit Code)

Canvas implementiert die Bild-Graffiti-Funktion (mit Code)

Nov 16, 2018 pm 05:17 PM
canvas javascript vue.js

Der Inhalt dieses Artikels befasst sich mit der Umsetzung der Bild-Graffiti-Funktion auf Leinwand (mit Code). Ich hoffe, dass er für Sie hilfreich ist.

Anforderungen

  1. Sie müssen Bilder mit Anmerkungen versehen und exportieren.

  2. N mehrere Bilder müssen markiert und schließlich gleichzeitig gespeichert werden.

  3. muss entsprechend den Polygonflächendaten (Fläche, Farbe, Name) beschriftet werden.

Entsprechende Lösung

  1. Zeichnen Sie Graffiti, Kreise und Rechtecke auf der Leinwand und generieren Sie schließlich die Base64-Kodierung des Bildes zum Hochladen

  2. Das Stapel-Upload einer großen Anzahl von Bildern ist zeitaufwändig. Um das Benutzererlebnis zu verbessern, werden nur Kreise und Rechtecke gezeichnet und schließlich als Koordinaten gespeichert und dann bei der Anzeige entsprechend den Koordinaten gezeichnet Nächstes Mal.

  3. Die Anzeige des Polygonbereichs wird basierend auf den Koordinatenpunkten gezeichnet, und die Position, an der der Name angezeigt wird, ist der Polygonschwerpunkt.

Code

<template>
  <div>
    <canvas
      :id="radom"
      :class="{canDraw: &#39;canvas&#39;}"
      :width="width"
      :height="height"
      :style="{&#39;width&#39;:`${width}px`,&#39;height&#39;:`${height}px`}"
      @mousedown="canvasDown($event)"
      @mouseup="canvasUp($event)"
      @mousemove="canvasMove($event)"
      @touchstart="canvasDown($event)"
      @touchend="canvasUp($event)"
      @touchmove="canvasMove($event)">
    </canvas>
  </div>
</template>
<script>
  // import proxy from './proxy.js'
  const uuid = require('node-uuid')
  export default {
    props: {
      canDraw: { // 图片路径
        type: Boolean,
        default: true
      },
      url: { // 图片路径
        type: String
      },
      info: { // 位置点信息
        type: Array
      },
      width: { // 绘图区域宽度
        type: String
      },
      height: { // 绘图区域高度
        type: String
      },
      lineColor: { // 画笔颜色
        type: String,
        default: 'red'
      },
      lineWidth: { // 画笔宽度
        type: Number,
        default: 2
      },
      lineType: { // 画笔类型
        type: String,
        default: 'circle'
      }
    },
    watch: {
      info (val) {
        if (val) {
          this.initDraw()
        }
      }
    },
    data () {
      return {
        // 同一页面多次渲染时,用于区分元素的id
        radom: uuid.v4(),
        // canvas对象
        context: {},
        // 是否处于绘制状态
        canvasMoveUse: false,
        // 绘制矩形和椭圆时用来保存起始点信息
        beginRec: {
          x: '',
          y: '',
          imageData: ''
        },
        // 储存坐标信息
        drawInfo: [],
        // 背景图片缓存
        img: new Image()
      }
    },
    mounted () {
      this.initDraw()
    },
    methods: {
      // 初始化绘制信息
      initDraw () {
        // 初始化画布
        const canvas = document.getElementById(this.radom)
        this.context = canvas.getContext('2d')
        // 初始化背景图片
        this.img.setAttribute('crossOrigin', 'Anonymous')
        this.img.src = this.url
        this.img.onerror = () => {
          var timeStamp = +new Date()
          this.img.src = this.url + '?' + timeStamp
        }
        this.img.onload = () => {
          this.clean()
        }
        // proxy.getBase64({imgUrl: this.url}).then((res) => {
        //   if (res.code * 1 === 0) {
        //     this.img.src = 'data:image/jpeg;base64,'+res.data
        //     this.img.onload = () => {
        //       this.clean()
        //     }
        //   }
        // })
        // 初始化画笔
        this.context.lineWidth = this.lineWidth
        this.context.strokeStyle = this.lineColor
      },
      // 鼠标按下
      canvasDown (e) {
        if (this.canDraw) {
          this.canvasMoveUse = true
          // client是基于整个页面的坐标,offset是cavas距离pictureDetail顶部以及左边的距离
          const canvasX = e.clientX - e.target.parentNode.offsetLeft
          const canvasY = e.clientY - e.target.parentNode.offsetTop
          // 记录起始点和起始状态
          this.beginRec.x = canvasX
          this.beginRec.y = canvasY
          this.beginRec.imageData = this.context.getImageData(0, 0, this.width, this.height)
          // 存储本次绘制坐标信息
          this.drawInfo.push({
            x: canvasX / this.width,
            y: canvasY / this.height,
            type: this.lineType
          })
        }
      },
      Area (p0,p1,p2) {
        let area = 0.0 ;
        area = p0.x * p1.y + p1.x * p2.y + p2.x * p0.y - p1.x * p0.y - p2.x * p1.y - p0.x * p2.y;
        return area / 2 ;
      },
      // 计算多边形质心
      getPolygonAreaCenter (points) {
        let sum_x = 0;
        let sum_y = 0;
        let sum_area = 0;
        let p1 = points[1];
        for (var i = 2; i < points.length; i++) {
          let p2 = points[i];
          let area = this.Area(points[0],p1,p2) ;
          sum_area += area ;
          sum_x += (points[0].x + p1.x + p2.x) * area;
          sum_y += (points[0].y + p1.y + p2.y) * area;
          p1 = p2 ;
        }
        return {
          x: sum_x / sum_area / 3,
          y: sum_y / sum_area / 3
        }
      },
      // 根据坐标信息绘制图形
      drawWithInfo () {
        this.info.forEach(item => {
          this.context.beginPath()
          if (!item.type) {
            // 设置颜色
            this.context.strokeStyle = item.regionColor
            this.context.fillStyle = item.regionColor
            // 绘制多边形的边
            if (typeof item.region === 'string') {
              item.region = JSON.parse(item.region)
            }
            item.region.forEach(point => {
              this.context.lineTo(point.x * this.width, point.y * this.height)
            })
            this.context.closePath()
            // 在多边形质心标注文字
            let point = this.getPolygonAreaCenter(item.region)
            this.context.fillText(item.areaName, point.x * this.width, point.y * this.height)
          } else if (item.type === 'rec') {
            this.context.rect(item.x * this.width, item.y * this.height, item.w * this.width, item.h * this.height)
          } else if (item.type === 'circle') {
            this.drawEllipse(this.context, (item.x + item.a) * this.width, (item.y + item.b) * this.height, item.a > 0 ? item.a * this.width : -item.a * this.width, item.b > 0 ? item.b * this.height : -item.b * this.height)
          }
          this.context.stroke()
        })
      },
      // 鼠标移动时绘制
      canvasMove (e) {
        if (this.canvasMoveUse && this.canDraw) {
          // client是基于整个页面的坐标,offset是cavas距离pictureDetail顶部以及左边的距离
          let canvasX = e.clientX - e.target.parentNode.offsetLeft
          let canvasY = e.clientY - e.target.parentNode.offsetTop
          if (this.lineType === 'rec') { // 绘制矩形时恢复起始点状态再重新绘制
            this.context.putImageData(this.beginRec.imageData, 0, 0)
            this.context.beginPath()
            this.context.rect(this.beginRec.x, this.beginRec.y, canvasX - this.beginRec.x, canvasY - this.beginRec.y)
            let info = this.drawInfo[this.drawInfo.length - 1]
            info.w = canvasX / this.width - info.x
            info.h = canvasY / this.height - info.y
          } else if (this.lineType === 'circle') { // 绘制椭圆时恢复起始点状态再重新绘制
            this.context.putImageData(this.beginRec.imageData, 0, 0)
            this.context.beginPath()
            let a = (canvasX - this.beginRec.x) / 2
            let b = (canvasY - this.beginRec.y) / 2
            this.drawEllipse(this.context, this.beginRec.x + a, this.beginRec.y + b, a > 0 ? a : -a, b > 0 ? b : -b)
            let info = this.drawInfo[this.drawInfo.length - 1]
            info.a = a / this.width
            info.b = b / this.height
          }
          this.context.stroke()
        }
      },
      // 绘制椭圆
      drawEllipse (context, x, y, a, b) {
        context.save()
        var r = (a > b) ? a : b
        var ratioX = a / r
        var ratioY = b / r
        context.scale(ratioX, ratioY)
        context.beginPath()
        context.arc(x / ratioX, y / ratioY, r, 0, 2 * Math.PI, false)
        context.closePath()
        context.restore()
      },
      // 鼠标抬起
      canvasUp (e) {
        if (this.canDraw) {
          this.canvasMoveUse = false
        }
      },
      // 获取坐标信息
      getInfo () {
        return this.drawInfo
      },
      // 清空画布
      clean () {
        this.context.drawImage(this.img, 0, 0, this.width, this.height)
        this.drawInfo = []
        if (this.info && this.info.length !== 0) this.drawWithInfo()
      }
    }
  }
</script>
<style scoped>
  .canvas{
    cursor: crosshair;
  }
</style>
Nach dem Login kopieren

Parameter, die übergeben werden müssen

  • Bildpfad

url: string
Nach dem Login kopieren
  • Zeichenflächenbreite

width: string
Nach dem Login kopieren
  • Zeichenflächenhöhe

height: string
Nach dem Login kopieren

Wählen Sie aus, ob die eingehenden Parameter

  • gezeichnet werden können, der Standardwert ist wahr

canDraw: boolean
Nach dem Login kopieren
Nach dem Login kopieren
  • Koordinatenpunktinformationen werden nicht gezeichnet, wenn sie nicht übergeben werden

info: string
Nach dem Login kopieren
  • Ob sie gezeichnet werden können, die Standardeinstellung ist wahr

canDraw: boolean
Nach dem Login kopieren
Nach dem Login kopieren
  • Zeichenfarbe, Standard Rot

lineColor: string
Nach dem Login kopieren
  • Zeichenstiftbreite, Standard 2

lineWidth: number
Nach dem Login kopieren
  • Zeichenstifttyp, Aufnahme, Kreis, Standardaufnahme

lineType: string
Nach dem Login kopieren

Methoden, die aufgerufen werden können

  • Leinwand leeren

clean()
Nach dem Login kopieren
  • Koordinatenpunktinformationen zurückgeben

getInfo()
Nach dem Login kopieren

Besondere Anweisungen

  • Das Canvas-Objekt kann keine Koordinaten erhalten. Es wird über die Koordinaten des übergeordneten Elements ermittelt. Daher darf es nicht zu viele Positionierungen oder Verschachtelungen geben Ebene über dem übergeordneten Element der Komponente, andernfalls werden die Zeichnungskoordinaten versetzt.

  • Bilder mit unterschiedlichen Domänennamen haben möglicherweise domänenübergreifende Probleme und es gibt keine gute Lösung. Im endgültigen Projekt habe ich den Knotendienst verwendet eine Schnittstelle zum Konvertieren von Bildern in Base64 und dann durch Zeichnen auf Leinwand gelöst. Es ist möglicherweise nicht auf andere Projekte anwendbar. Wenn es eine bessere Lösung gibt, teilen Sie sie bitte mit.

  • Beim Exportieren von Koordinatenpunktdaten können nur die Koordinatenpunkte regelmäßiger Muster exportiert werden, denn wenn zu viele zufällig gekritzelte Koordinatenpunkte vorhanden sind, kollabieren sie (obwohl ich nicht versucht habe, inwieweit dies der Fall ist). wird zusammenbrechen). Wenn Sie über leistungsstarke Implementierungsmethoden verfügen, teilen Sie diese bitte mit.

  • Wenn die Bild-URL nach dem Speichern nach einem Graffiti nicht angefordert werden kann, liegt das an einem CDN-Caching-Problem, das durch Hinzufügen eines Zufallscodes nach dem Bildpfad gelöst werden kann.

Das obige ist der detaillierte Inhalt vonCanvas implementiert die Bild-Graffiti-Funktion (mit Code). Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn

Heiße KI -Werkzeuge

Undresser.AI Undress

Undresser.AI Undress

KI-gestützte App zum Erstellen realistischer Aktfotos

AI Clothes Remover

AI Clothes Remover

Online-KI-Tool zum Entfernen von Kleidung aus Fotos.

Undress AI Tool

Undress AI Tool

Ausziehbilder kostenlos

Clothoff.io

Clothoff.io

KI-Kleiderentferner

Video Face Swap

Video Face Swap

Tauschen Sie Gesichter in jedem Video mühelos mit unserem völlig kostenlosen KI-Gesichtstausch-Tool aus!

Heiße Werkzeuge

Notepad++7.3.1

Notepad++7.3.1

Einfach zu bedienender und kostenloser Code-Editor

SublimeText3 chinesische Version

SublimeText3 chinesische Version

Chinesische Version, sehr einfach zu bedienen

Senden Sie Studio 13.0.1

Senden Sie Studio 13.0.1

Leistungsstarke integrierte PHP-Entwicklungsumgebung

Dreamweaver CS6

Dreamweaver CS6

Visuelle Webentwicklungstools

SublimeText3 Mac-Version

SublimeText3 Mac-Version

Codebearbeitungssoftware auf Gottesniveau (SublimeText3)

Einfaches JavaScript-Tutorial: So erhalten Sie den HTTP-Statuscode Einfaches JavaScript-Tutorial: So erhalten Sie den HTTP-Statuscode Jan 05, 2024 pm 06:08 PM

JavaScript-Tutorial: So erhalten Sie HTTP-Statuscode. Es sind spezifische Codebeispiele erforderlich. Vorwort: Bei der Webentwicklung ist häufig die Dateninteraktion mit dem Server erforderlich. Bei der Kommunikation mit dem Server müssen wir häufig den zurückgegebenen HTTP-Statuscode abrufen, um festzustellen, ob der Vorgang erfolgreich ist, und die entsprechende Verarbeitung basierend auf verschiedenen Statuscodes durchführen. In diesem Artikel erfahren Sie, wie Sie mit JavaScript HTTP-Statuscodes abrufen und einige praktische Codebeispiele bereitstellen. Verwenden von XMLHttpRequest

Lernen Sie das Canvas-Framework kennen und erklären Sie das häufig verwendete Canvas-Framework im Detail Lernen Sie das Canvas-Framework kennen und erklären Sie das häufig verwendete Canvas-Framework im Detail Jan 17, 2024 am 11:03 AM

Entdecken Sie das Canvas-Framework: Um die häufig verwendeten Canvas-Frameworks zu verstehen, sind spezifische Codebeispiele erforderlich. Einführung: Canvas ist eine in HTML5 bereitgestellte Zeichen-API, mit der wir umfangreiche Grafik- und Animationseffekte erzielen können. Um die Effizienz und den Komfort des Zeichnens zu verbessern, haben viele Entwickler verschiedene Canvas-Frameworks entwickelt. In diesem Artikel werden einige häufig verwendete Canvas-Frameworks vorgestellt und spezifische Codebeispiele bereitgestellt, um den Lesern ein tieferes Verständnis für die Verwendung dieser Frameworks zu vermitteln. 1. EaselJS-Framework Ea

Entdecken Sie die wichtige Rolle und Anwendung von Canvas in der Spieleentwicklung Entdecken Sie die wichtige Rolle und Anwendung von Canvas in der Spieleentwicklung Jan 17, 2024 am 11:00 AM

Verstehen Sie die Leistungsfähigkeit und Anwendung von Canvas in der Spieleentwicklung. Überblick: Mit der rasanten Entwicklung der Internettechnologie werden Webspiele bei Spielern immer beliebter. Als wichtiger Bestandteil der Webspielentwicklung hat sich die Canvas-Technologie nach und nach in der Spieleentwicklung durchgesetzt und ihre leistungsstarke Leistungsfähigkeit und Anwendung unter Beweis gestellt. In diesem Artikel wird das Potenzial von Canvas in der Spieleentwicklung vorgestellt und seine Anwendung anhand spezifischer Codebeispiele demonstriert. 1. Einführung in die Canvas-Technologie Canvas ist ein neues Element in HTML5, das uns die Verwendung ermöglicht

So erhalten Sie auf einfache Weise HTTP-Statuscode in JavaScript So erhalten Sie auf einfache Weise HTTP-Statuscode in JavaScript Jan 05, 2024 pm 01:37 PM

Einführung in die Methode zum Abrufen des HTTP-Statuscodes in JavaScript: Bei der Front-End-Entwicklung müssen wir uns häufig mit der Interaktion mit der Back-End-Schnittstelle befassen, und der HTTP-Statuscode ist ein sehr wichtiger Teil davon. Das Verstehen und Abrufen von HTTP-Statuscodes hilft uns, die von der Schnittstelle zurückgegebenen Daten besser zu verarbeiten. In diesem Artikel wird erläutert, wie Sie mithilfe von JavaScript HTTP-Statuscodes erhalten, und es werden spezifische Codebeispiele bereitgestellt. 1. Was ist ein HTTP-Statuscode? HTTP-Statuscode bedeutet, dass der Dienst den Dienst anfordert, wenn er eine Anfrage an den Server initiiert

Wo kann man Canvas-Code schreiben? Wo kann man Canvas-Code schreiben? Dec 20, 2023 pm 03:17 PM

Canvas-Code kann in das <body>-Tag einer HTML-Datei geschrieben werden, normalerweise als Teil des HTML-Dokuments. Der Kern des Canvas-Codes besteht darin, den Kontext des Canvas-Elements abzurufen und zu bedienen über document.getElementById('myCanvas') und verwenden Sie dann getContext('2d'), um den 2D-Zeichnungskontext abzurufen.

JavaScript und WebSocket: Aufbau einer effizienten Echtzeitsuchmaschine JavaScript und WebSocket: Aufbau einer effizienten Echtzeitsuchmaschine Dec 17, 2023 pm 10:13 PM

JavaScript und WebSocket: Aufbau einer effizienten Echtzeit-Suchmaschine Einführung: Mit der Entwicklung des Internets stellen Benutzer immer höhere Anforderungen an Echtzeit-Suchmaschinen. Bei der Suche mit herkömmlichen Suchmaschinen müssen Benutzer auf die Suchschaltfläche klicken, um Ergebnisse zu erhalten. Diese Methode kann den Anforderungen der Benutzer an Echtzeit-Suchergebnissen nicht gerecht werden. Daher ist die Verwendung von JavaScript und WebSocket-Technologie zur Implementierung von Echtzeitsuchmaschinen zu einem heißen Thema geworden. In diesem Artikel wird die Verwendung von JavaScript ausführlich vorgestellt

Ist Vue.js schwer zu lernen? Ist Vue.js schwer zu lernen? Apr 04, 2025 am 12:02 AM

Vue.js ist nicht schwer zu lernen, insbesondere für Entwickler mit einer JavaScript -Stiftung. 1) Sein progressives Design und das reaktionsschnelle System vereinfachen den Entwicklungsprozess. 2) Komponentenbasierte Entwicklung macht das Codemanagement effizienter. 3) Die Nutzungsbeispiele zeigen eine grundlegende und fortgeschrittene Verwendung. 4) Häufige Fehler können durch VEDEVTOOLS debuggen werden. 5) Leistungsoptimierung und Best Practices, z. B. die Verwendung von V-IF/V-Shows und Schlüsselattributen, können die Anwendungseffizienz verbessern.

Vue.js vs. React: projektspezifische Überlegungen Vue.js vs. React: projektspezifische Überlegungen Apr 09, 2025 am 12:01 AM

Vue.js eignet sich für kleine und mittelgroße Projekte und schnelle Iterationen, während React für große und komplexe Anwendungen geeignet ist. 1) Vue.js ist einfach zu bedienen und für Situationen geeignet, in denen das Team nicht ausreicht oder die Projektskala klein ist. 2) React hat ein reichhaltigeres Ökosystem und eignet sich für Projekte mit hoher Leistung und komplexen funktionalen Bedürfnissen.

See all articles