The specific style

Function:

  1. Upload file: Upload a file and save the file data
  2. Preview: Convert the uploaded file into an image address and display it on the page
  3. Screenshot: Fix the selection box background, then place the image data on the canvas, move it to enlarge and then crop it
  4. Download: Convert the cropped data into a downloadable picture format for download

View code

<template>
  <div class="avatar">
    <a-button class="btn">
      <span>Upload the picture</span>
      <input type="file" name="" id="upload_file" @change="handleChange">
    </a-button>

    <! -- Preview and cut pop-ups -->
    <a-modal v-model="visible" title="Picture Preview or Edit" @ok="handleOk"              class="avatar_modal">
      <div class="main">
        <img :src="imgSrc" alt="" v-if="isView">
        <template  v-else>
          <div>
            <! -- Slider to enlarge image -->
            <input id="slider" type="range" max="4" min="1" v-model="currentSize" @input="handleRange"/>
          </div>
          <div id="demo"> 
            <canvas id="myCanvas" width="400px" height="400px" ref="canvas"></canvas>
            <canvas id="myImg"  width="400px" height="400px" ref="myImg"></canvas>
          </div>
        </template>
      </div>
      <div class="model_btn">
        <a-button style="margin-right:20px" @click="handleView('VIEW')">preview</a-button>
        <a-button @click="handleView('CLIP')">screenshots</a-button>
      </div>
    </a-modal>
  </div>
</template>
Copy the code

Data Data and props data codes

data(){
  return {
    visible:false.// Open the preview and screenshot pop-up
    isView:true.// Switch preview to screenshot again
    imgSrc:' '.// Preview the image address
    currentSize:1.// Image magnification (1-4)
    move: {// Canvas motion path data
      lastMoveX:null.lastMoveY:null.currentMoveX:null.currentMoveY:null.isMoving:false
    },
    canvas_edit: {// Canvas to be edited
      el:null./ / canvas element
      ctx:null.// Canvas's 2D environment
      image:null.// Canvas image element
      left:0.// Canvas width to the left of the parent element
      top:0 // Canvas height from the top of the parent element
    },
    blackMask: {// Select the canvas element data of the box
      el:null./ / canvas element
      ctx:null  // Canvas's 2D environment}}},props: {// Limit the upload format
  limited: {default:() = >{return ['image/png']},
    type:Array}},Copy the code

File upload and image preview

handleChange(e){
  let file_dom = document.getElementById('upload_file')
  let file = e.target.files[0]
  if(this.limited.includes(file.type)){
    this.imgSrc = window.URL.createObjectURL(file) 
    this.visible = true
  }else{
    let str = this.limited.reduce((total,currentValue) = >{ return  total + currentValue.split('/') [1] + ', '},' ')
    this.$message.warn('Upload file format error, supported only'+str)
  }
  file_dom.value = null
}
Copy the code

Description:

  1. Obtain the uploaded filefile
  2. judgefileThe format, unqualified to give hints
  3. willfileConvert to the address of the picture that can be displayedimgSrc
  4. Preview the image by showing it to the corresponding node
  5. Clear the cache of uploaded files

Initialize the mask and Canvas images

drawCanavs(){
  this.$nextTick(() = >{
    this.canvas_edit.el = this.$refs.canvas // This is the canvas to manipulate the image
    this.canvas_edit.ctx = this.canvas_edit.el.getContext('2d')
    this.canvas_edit.image = new Image()
    this.canvas_edit.image.src = this.imgSrc
    this.canvas_edit.image.onload = () = >{
      this.initCanvas() // Initialize canvas element
    }

    // Initialize the elements of mask
    this.blackMask.el = this.$refs.myImg
    this.blackMask.ctx = this.blackMask.el.getContext('2d')
    this.blackMask.ctx.fillStyle = 'rgba (0,0,0,0.3)'
    this.blackMask.ctx.fillRect(0.0.400.400)
    this.blackMask.ctx.clearRect(100.100.200.200) 

    // Since it is not possible to listen directly on the canvas_edit.el element, you can choose to do so in the mask
    this.blackMask.el.onmousedown = (e) = >{
      this.move.isMoving = true
      this.move.lastMoveX = e.clientX
      this.move.lastMoveY = e.clientY

    }
    this.blackMask.el.onmousemove = (e) = >{
      if(this.move.isMoving){
        let width = e.clientX -  this.move.lastMoveX + this.canvas_edit.left
        let height = e.clientY -  this.move.lastMoveY+this.canvas_edit.top
        this.drawCanvas(width,height)
      }
    }
    this.blackMask.el.onmouseup = (e) = >{
      if(this.move.isMoving){
        this.move.isMoving = false
        let width = e.clientX -  this.move.lastMoveX + this.canvas_edit.left
        let height = e.clientY -  this.move.lastMoveY+this.canvas_edit.top
        this.drawCanvas(width,height)
        this.canvas_edit.left = width
        this.canvas_edit.top = height
      }
    }
  })
},

Copy the code
// Draw the center image to the Canvas image
initCanvas(){
  let width = (400 - this.canvas_edit.image.width*this.currentSize)/2 // The initial coordinates of the image (width,heigth)
  let height = (400 - this.canvas_edit.image.height*this.currentSize)/2
  this.canvas_edit.left = width
  this.canvas_edit.top = height
  this.canvas_edit.ctx.drawImage(this.canvas_edit.image,width,height,this.canvas_edit.image.width*this.currentSize,this.canvas_edit.image.height*this.currentSize)
},
Copy the code
// Update canvas image
drawMask(width,height){
  this.canvas_edit.ctx.clearRect(0.0.400.400)
  this.canvas_edit.ctx.drawImage(this.canvas_edit.image,width,height,this.canvas_edit.image.width * this.currentSize,this.currentSize * this.canvas_edit.image.height)
},
Copy the code

Description:

  1. Draws the image to the Canvas image
  2. Draw the mask layer
  3. Bind the pressed, moved, and pressed events in the mask layer
  4. When pressing, determine the current position of the mouse
  5. When moving, move the position of the picture in the canvas image according to the distance that the mouse moves, and update the canvas image
  6. When pressing on, determine the position of the mouse away as the coordinates of the image in the Canvas image, and update the image

Clipping and downloading

handleOk(){
  // Retrieve the cropped image data
  let image_data = this.canvas_edit.ctx.getImageData(100.100.200.200) 
  this.canvas_edit.ctx.clearRect(0.0.400.400)
  
  // Change the canvas to the same width and height as the selected image
  this.canvas_edit.el.height = 200
  this.canvas_edit.el.width = 200
  this.canvas_edit.el.style.left = '100px'
  this.canvas_edit.el.style.top = '100px'
  this.canvas_edit.ctx.putImageData(image_data,0.0) // Put the cropped element into the Canvas

  // Convert the Canvas image to a subtractable image format and download it
  let base64_img = this.canvas_edit.el.toDataURL('image/png')
  let blob_img = this.dataURLToBlob(base64_img)
  let url = URL.createObjectURL(blob_img)
  let a = document.createElement('a')
  a.setAttribute('download'.'Profile picture data' + '.png')
  a.setAttribute('href',url)
  a.click()
  this.visible = false
  this.$emit('getUrl',url)
}
Copy the code
// Convert base64 to Blob object
dataURLToBlob(code) {
  let parts = code.split('; base64,')
  let contentType = parts[0].split(':') [1]
  let raw = window.atob(parts[1])
  let rawLength = raw.length
  let uInt8Array = new Uint8Array(rawLength)
  for(let i = 0; i < rawLength; ++i) {
    uInt8Array[i] = raw.charCodeAt(i)
  }
  return new Blob([uInt8Array], {
    type: contentType
  })
},

Copy the code

Description:

  1. Gets the selected image data in the Canvas image
  2. Clear the screen, change the size of the Canvas element, and place the Canvas image in the center
  3. Put the acquired image data into the Canvas element
  4. Convert the Canvas into a downloadable image for download