Maison > interface Web > Tutoriel H5 > Comment utiliser Canvas pour implémenter une mosaïque d'images

Comment utiliser Canvas pour implémenter une mosaïque d'images

不言
Libérer: 2018-06-14 11:15:15
original
3657 Les gens l'ont consulté

Cet article présente principalement les informations pertinentes sur l'exemple de code pour implémenter la mosaïque d'images sur toile. Le contenu est assez bon, je vais le partager avec vous maintenant et le donner comme référence.

1. API utilisée pour l'implémentation native du canevas

1) getContext(contextID) ---Renvoie un environnement pour dessiner sur le canevas

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

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)的位置上
Copier après la connexion

3) getImageData(x, y, width, height) --- Obtenez les informations d'image de la zone rectangulaire

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

4) startPath() --- Démarrer un chemin ou réinitialiser le chemin actuel 5) rect(x, y, width, height) --- Dessiner un rectangle

6) lineWidth - --Définir ou renvoyer la largeur de la ligne actuelle

7) fillStyle ---Définir ou renvoyer la couleur, le dégradé ou le motif utilisé pour remplir la peinture

ctx.fillStyle = color|gradient|pattern
Copier après la connexion

8) StrokeStyle - -- Définit ou renvoie la couleur, le dégradé ou le mode utilisé pour les traits

9) globalAlpha --- Définit ou renvoie la valeur de transparence actuelle du dessin

10) fill() --- Remplir l'image actuelle (chemin). La couleur par défaut est le noir

[Note]Si le chemin n'est pas fermé, la méthode fill() ajoutera une ligne depuis le point final du chemin jusqu'au point de départ pour fermer le chemin. chemin, puis remplissez-le.

11) Stroke() --- dessinera en fait le chemin défini par les méthodes moveTo() et lineTo(). La couleur par défaut est le noir

12) toDataURL(type, encoderOptions) ---Exporter l'image, le type est le type d'image, encoderOptions qualité de l'image, [0, 1]

Canvas.toDataURL("image/png", 1)
Copier après la connexion

2. fabric.js

Une bibliothèque qui simplifie l'écriture du canevas et fournit le modèle d'objet manquant pour le canevas

Ce que fabric.js peut faire

1) Créez et remplissez des graphiques sur toile (y compris des images, du texte, des graphiques réguliers et des chemins complexes pour former des graphiques)

2) Remplissez les graphiques avec des couleurs dégradées

3) Combinez graphiques (y compris les graphiques combinés, le texte graphique, les images, etc.)

4) Configurer un ensemble d'animations graphiques pour l'interaction de l'utilisateur

5) Générer des données JSON, SVG, etc.

3. Utilisez l'API fabric.js utilisée pour implémenter

1) Déclarer le canevas

let canvas =new fabric.Canvas('canvas') {
   width: 200,
   height: 200
}
Copier après la connexion

Insérer une image

let imgInstance = new fabric.Image(imgElement,{
  left: 0,
  top: 0,
  width: 100,
  height: 100,
  angle: 0
}
Copier après la connexion

3) Définir l'image d'arrière-plan setBackgroundImage

canvas.setBackgroundImage(imgInstance)
Copier après la connexion

4) renderAll() redessiner

5) on() interaction utilisateur

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对象被移除 
*/
Copier après la connexion

6) getPointer()

7) setWidth( ), paramètres setHeight() La largeur et la hauteur du canevas

8) Dessinez un rectangle

let rect = new fabric.Rect({
 left: 0,
 top: 0,
 width: 100,
 height: 100
})
Copier après la connexion

ajouter (obj) ajouter des graphiques

canvas.add(rect)
Copier après la connexion

10) supprimer (obj) supprimer les graphiques

11) set() définit le contenu de l'objet

12) toDataURL(obj)

Code d'implémentation du canevas natif

<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>
Copier après la connexion

Ce qui précède représente l'intégralité du contenu de cet article. J'espère qu'il sera utile à l'étude de chacun. Pour plus de contenu connexe, veuillez faire attention au site Web PHP chinois !

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Étiquettes associées:
source:php.cn
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal