Heim  >  Artikel  >  Web-Frontend  >  So verwenden Sie Canvas zum Implementieren eines Bildmosaiks

So verwenden Sie Canvas zum Implementieren eines Bildmosaiks

不言
不言Original
2018-06-14 11:15:153573Durchsuche

In diesem Artikel werden hauptsächlich relevante Informationen zum Beispielcode für die Implementierung von Bildmosaiken auf Leinwand vorgestellt. Ich werde ihn jetzt als Referenz mit Ihnen teilen.

1. Für die native Canvas-Implementierung verwendete API

1) getContext(contextID) ---Gibt eine Umgebung zum Zeichnen auf dem Canvas zurück

Canvas.getContext('2d') // 返回一个 CanvasRenderingContext2D 对象,使用它可以绘制到 Canvas 元素中

2) drawImage

drawImage(imgObj, x, y)  // 按原图大小绘制, x、y为图片在画布中的位置坐标
drawImage(imgObj, x, y, width, height) // 按指定宽高绘制
drawImage(imgObj, sourceX, sourceY, sourceWidth, sourceHeight, destX, destY, destWidth, destHeight) // 从原来图片上某一个位置开始(sourceX,sourceY),指定长宽进行剪切(sourceWidth,sourceHeight),然后将剪切的内容放到位置为(destX,destY),宽度为(destWidth),高度为(destHeight)的位置上

3) getImageData(x, y, width, height) --- Bildinformationen des rechteckigen Bereichs abrufen

ctx.getImageData(0, 0, 10, 10) // 获取左上角坐标为(0, 0),宽高为区域内的图像信息
// 返回ImageData: { width: 10, height: 10, data: Uint8ClampedArray[400] }

4 ) beginPath() --- Einen Pfad starten oder den aktuellen Pfad zurücksetzen 5) rect(x, y, width, height) --- Ein Rechteck zeichnen

6) lineWidth --- Setze oder gib The zurück Breite der aktuellen Linie

7) fillStyle ---Legt die Farbe, den Farbverlauf oder das Muster zum Füllen des Gemäldes fest oder gibt sie zurück

ctx.fillStyle = color|gradient|pattern

8) StrokeStyle ---Legt die verwendete Farbe fest oder gibt sie zurück für Striche, Farbverlauf oder Muster

9) globalAlpha --- Setzt den aktuellen Transparenzwert der Zeichnung oder gibt ihn zurück

10) fill() --- Füllt das aktuelle Bild (Pfad). Die Standardfarbe ist Schwarz

[Hinweis]Wenn der Pfad nicht geschlossen ist, fügt die Methode fill() eine Linie vom Endpunkt des Pfads zum Startpunkt hinzu, um den zu schließen Pfad und füllen Sie ihn dann mit dem Pfad aus.

11) Stroke() --- zeichnet tatsächlich den durch die Methoden moveTo() und lineTo() definierten Pfad. Die Standardfarbe ist Schwarz

12) toDataURL(type, EncoderOptions) ---Exportieren Sie das Bild, Typ ist der Bildtyp, EncoderOptions Bildqualität, [0, 1]

Canvas.toDataURL("image/png", 1)

2. fabric.js

Eine Bibliothek, die das Canvas-Schreiben vereinfacht und das fehlende Objektmodell für Canvas bereitstellt

Was fabric.js kann

1) Erstellen und füllen Sie Grafiken auf Leinwand (einschließlich Bildern, Text, regulären Grafiken und komplexen Pfaden, um Grafiken zu bilden)

2) Füllen Sie Grafiken mit Verlaufsfarben

3) Kombinieren Sie Grafiken ( einschließlich Kombinationen) Grafiken, grafischer Text, Bilder usw.)

4) Grafikanimationsset für Benutzerinteraktion einrichten

5) JSON-, SVG-Daten usw. generieren

3. Verwenden Sie fabric.js, um die API zu implementieren

1) Leinwand deklarieren

let canvas =new fabric.Canvas('canvas') {
   width: 200,
   height: 200
}

Bild einfügen

let imgInstance = new fabric.Image(imgElement,{
  left: 0,
  top: 0,
  width: 100,
  height: 100,
  angle: 0
}

3) Hintergrundbild setBackgroundImage festlegen

canvas.setBackgroundImage(imgInstance)

4 ) renderAll() redraw

5) on() Benutzerinteraktion

canvas.on('mouse:down', function(options) {  
   console.log(options.e.clientX, options.e.clientY)  
})

// 监听事件
/* 
   mouse:down :鼠标按下时
   mouse:move :鼠标移动时
   mouse:up :鼠标抬起时
   after:render :画布重绘后
   object:selected:对象被选中
   object:moving:对象移动
   object:rotating:对象被旋转
   object:added:对象被加入
   object:removed对象被移除 
*/

6) getPointer()

7) setWidth(), setHeight() legt die Breite und Höhe fest der Leinwand

8) Zeichne ein Rechteck

let rect = new fabric.Rect({
 left: 0,
 top: 0,
 width: 100,
 height: 100
})

add(obj) Grafiken hinzufügen

canvas.add(rect)

10) remove(obj) Grafiken entfernen

11) gesetzt () Objektinhalt festlegen

12) auf DataURL(obj)

4. Nativer Canvas-Implementierungscode

<template>
<p class="container">
  <p class="operations">
    <ul>
      <li @click="mosaic">马赛克</li>
      <li @click="addText">添加文字</li>
      <li @click="tailor">裁剪</li>
      <li @click="rotate">旋转</li>
      <li @click="exportImg">导出图片</li>
    </ul>
  </p>
  <canvas ref="imgContent" class="img-wrap">
    你的浏览器太low
    </canvas>
</div>
</template>
 
<script>
  export default {
    data () {
      return {
        context: &#39;&#39;,
        canvas: &#39;&#39;,
        isMasic: false,
        isText: false,
        isTailor: false,
        isTranslate: false,
        squareEdgeLength: 20,
        angle: 0,
        img: &#39;&#39;
      }
    },
    mounted () {
      this.initData()
    },
    methods: {
      initData () {
        let imgContent = this.$refs.imgContent
        this.canvas = imgContent
        this.context = imgContent.getContext(&#39;2d&#39;)
        let  Img = new Image()
        this.image = Img
        Img.crossOrigin = "Anonymous"
        Img.src = &#39;http://oia85104s.bkt.clouddn.com/PictureUnlock_193139.pictureunlock.jpg&#39;
        this.canvas.setAttribute(&#39;width&#39;, Img.width)
        this.canvas.setAttribute(&#39;height&#39;, Img.height)
        let self = this
        Img.onload = () => {
          let beginX, beginY, endX, endY
          self.context.drawImage(Img, 0, 0)
          self.context.save()
 
          self.canvas.addEventListener(&#39;mousedown&#39;, e => {
            beginX = e.offsetX
            beginY = e.offsetY
            self.canvas.addEventListener(&#39;mouseup&#39;, e => {
              endX = e.offsetX
              endY = e.offsetY
              if (self.isMasic) {
                self.makeGrid(beginX, beginY, endX - beginX, endY - beginY)
                return
              }
              if (self.isTailor) {
                self.context.drawImage(Img, beginX, beginY, endX - beginX, endY - beginY, 0, 0, endX - beginX, endY - beginY)
                return
              }
            })
          })
        }
      },
      drawRect  (x, y, width, height, fillStyle, lineWidth, strokeStyle, globalAlpha) {
        this.context.beginPath()
        this.context.rect(x, y, width, height)
        this.context.lineWidth = lineWidth
        this.context.strokeStyle = strokeStyle
        fillStyle && (this.context.fillStyle = fillStyle)
        globalAlpha && (this.context.globalAlpha = globalAlpha)
 
        this.context.fill()
        this.context.stroke()
      },
      // 打马赛克
      mosaic () {
        let self = this
        this.resetClickStatus()
        this.isMasic = true
      },
      makeGrid (beginX, beginY, rectWidth, rectHight) {
        const row = Math.round(rectWidth / this.squareEdgeLength) + 1
        const column = Math.round(rectHight / this.squareEdgeLength) + 1
        for (let i = 0; i < row * column; i++) {
          let x = (i % row) * this.squareEdgeLength + beginX
          let y = parseInt(i / row) * this.squareEdgeLength + beginY
          this.setColor(x, y)
        }
      },
      setColor (x, y) {
        const imgData = this.context.getImageData(x, y, this.squareEdgeLength, this.squareEdgeLength).data
        let r = 0, g = 0, b = 0
        console.log(this.context.getImageData(x, y, this.squareEdgeLength, this.squareEdgeLength), JSON.stringify(imgData))
        for (let i = 0; i < imgData.length; i += 4) {
          r += imgData[i]
          g += imgData[i + 1]
          b += imgData[i + 2]
        }
        r = Math.round(r / (imgData.length / 4))
        g = Math.round(g / (imgData.length / 4))
        b = Math.round(b / (imgData.length / 4))
        this.drawRect(x, y, this.squareEdgeLength, this.squareEdgeLength, `rgb(${r}, ${g}, ${b})`, 2, `rgb(${r}, ${g}, ${b})`)
      },
      // 添加文字
      addText () {
        this.resetClickStatus()
        this.isText = true
        console.log(&#39;添加文字&#39;)
      },
      // 裁剪
      tailor () {
        this.resetClickStatus()
        this.isTailor = true
        console.log(&#39;裁剪&#39;)
      } ,
      // 旋转
      rotate () {
        // if (this.angle === 360) {
        //   this.angle = 90
        // } else {
        //   this.angle += 90
        // }
        // if ([90, 270].includes(this.angle)) {
        //   this.canvas.setAttribute(&#39;width&#39;, this.image.height)
        //   this.canvas.setAttribute(&#39;height&#39;, this.image.width)
        // } else {
        //   this.canvas.setAttribute(&#39;width&#39;, this.image.width)
        //   this.canvas.setAttribute(&#39;height&#39;, this.image.height)
        // }
        const x = this.image.width / 2
        const y = this.image.height / 2
        this.context.clearRect(0,0, this.canvas.width, this.canvas.height)  // 清理画布内容
        this.context.translate(x, y)
        this.context.rotate(90 * Math.PI / 180)
        this.context.translate(-x, -y)
        this.context.drawImage(this.image, 0, 0)
      },
      resetClickStatus () {
        this.isMasic = false
        this.isText = false
        this.isTailor = false
        this.isTranslate = false
      },
      exportImg () {
        this.resetClickStatus()
        const exportUrl = this.canvas.toDataURL("image/jpeg")
        let a = document.createElement(&#39;a&#39;)
        a.setAttribute(&#39;download&#39;, &#39;&#39;)
        a.href = exportUrl
        document.body.appendChild(a)
        a.click()
      }
    }
  }
</script>
 
<style scoped lang="less">
.operations {
  width: 1200px;
  margin: 0 auto;
  ul {
    display: flex;
    align-items: center;
    margin-bottom: 30px;
    li {
      list-style: none;
      margin-right: 20px;
      cursor: pointer;
    }
  }
}
.img-wrap {
  display: block;
  margin: 0 auto;
}
</style>

Das Obige ist der gesamte Inhalt davon Ich hoffe, dass er für das Lernen aller hilfreich ist. Weitere verwandte Inhalte finden Sie auf der chinesischen PHP-Website!

Das obige ist der detaillierte Inhalt vonSo verwenden Sie Canvas zum Implementieren eines Bildmosaiks. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
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