>  기사  >  웹 프론트엔드  >  캔버스를 사용하여 이미지 모자이크를 구현하는 방법

캔버스를 사용하여 이미지 모자이크를 구현하는 방법

不言
不言원래의
2018-06-14 11:15:153591검색

이 글은 캔버스에 이미지 모자이크를 구현하기 위한 샘플 코드에 대한 관련 정보를 주로 소개합니다. 내용이 꽤 좋아서 지금 공유하고 참고하겠습니다.

1. 네이티브 캔버스 구현에 사용되는 API

1) getContext(contextID) ---캔버스에 그리기 위한 환경을 반환합니다

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) --- 직사각형 영역의 이미지 정보 가져오기

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

4) startPath() --- 경로 시작 또는 현재 경로 재설정 5) ret(x, y, width, height) -- -직사각형 그리기

6) lineWidth ---현재 선의 너비 설정 또는 반환

7) fillStyle ---그림을 채우는 데 사용되는 색상, 그라데이션 또는 모드 설정 또는 반환

ctx.fillStyle = color|gradient|pattern

8) 스트로크 스타일 - -- 획에 사용되는 색상, 그라데이션 또는 패턴을 설정하거나 반환합니다.

9) globalAlpha --- 그림의 현재 투명도 값을 설정하거나 반환합니다.

10) fill() --- 현재 이미지(경로)를 채웁니다. 기본 색상은 검정색입니다

【참고】경로가 닫혀 있지 않은 경우 fill() 메서드는 경로의 끝점에서 시작점까지 선을 추가하여 경로를 닫은 다음 경로를 채웁니다.

11) 스트로크() --- 실제로 moveTo() 및 lineTo() 메서드에 의해 정의된 경로를 그립니다. 기본 색상은 검정색

12) toDataURL(type, EncoderOptions) ---이미지 내보내기, type은 이미지 유형, EncoderOptions 이미지 품질, [0, 1]

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

2는 fabric.js

을 단순화합니다. 캔버스 쓰기 라이브러리, 캔버스에 누락된 개체 모델 제공

fabric.js가 할 수 있는 작업

1) 캔버스에 그래픽을 만들고 채웁니다(그림, 텍스트, 일반 그래픽 및 그래픽을 형성하는 복잡한 경로 포함)

2) 그라데이션 색상으로 그래픽 채우기

3) 그래픽 결합(조합 그래픽, 그래픽 텍스트, 그림 등 포함)

4) 그래픽 애니메이션 설정 사용자 상호 작용 설정

5) JSON, SVG 데이터 등 생성

3 . 구현에 사용된 fabric.js API 사용

1) 캔버스 선언

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

그림 삽입

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

3) 배경 이미지 설정 setBackgroundImage

canvas.setBackgroundImage(imgInstance)

4) renderAll() redraw

5) on() 사용자 상호 작용

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() 캔버스의 너비와 높이 설정

8) 직사각형 그리기

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

add(obj) 그래픽 추가

canvas.add(rect)

10) Remove(obj) 그래픽 제거

11) set() Set object content

12) toDataURL(obj)

4. 네이티브 캔버스 구현 코드

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

위 내용은 모두의 학습에 도움이 되기를 바랍니다. . 더 많은 관련 내용을 보시려면 PHP 중국어 넷을 주목해주세요!

위 내용은 캔버스를 사용하여 이미지 모자이크를 구현하는 방법의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.