Skip to content

实现canvas中图片的平移与缩放

vue2canvas

定义一个canvas

html
<canvas
    ref="canvas"
    :width="width"
    :height="height"
    @mousedown="mousedown($event)"
    @mousemove="mousemove($event)"
    @mouseout="mouseout"
    @mouseup="mouseup($event)"
    @wheel="wheel($event)"
  />
<canvas
    ref="canvas"
    :width="width"
    :height="height"
    @mousedown="mousedown($event)"
    @mousemove="mousemove($event)"
    @mouseout="mouseout"
    @mouseup="mouseup($event)"
    @wheel="wheel($event)"
  />

包括鼠标事件

  • 鼠标按下 mousedown
  • 鼠标移动 mousemove
  • 鼠标抬起 mouseup
  • 鼠标滚轮滚动 wheel
  • 鼠标指针移出 mouseout

定义所需的变量

传入参数 props

js
props: {
  imageUrl: { // 图片路径
    type: String,
    default: ''
  },
  height: { // 定义图片展示的高度
    type: Number,
    default: 480
  },
  width: { // 定义图片展示的宽度
    type: Number,
    default: 854
  },
}
props: {
  imageUrl: { // 图片路径
    type: String,
    default: ''
  },
  height: { // 定义图片展示的高度
    type: Number,
    default: 480
  },
  width: { // 定义图片展示的宽度
    type: Number,
    default: 854
  },
}

定义参数 data

js
data() {
  return {
    img: null,
    context: null,
    imgX: 0,
    imgY: 0,
    MINIMUM_SCALE: 0.1,  // 缩小最小限度
    pos: { x: 0, y: 0 },
    posl: { x: 0, y: 0 },
    dragging: false,  // 是否可以拖拽
    imgScale: 1,    // 缩放比例
    imgXAutoScale: 0,   // 图片适应拉伸宽度
    imgYAutoScale: 0,   // 图片适应拉伸高度
  }
}
data() {
  return {
    img: null,
    context: null,
    imgX: 0,
    imgY: 0,
    MINIMUM_SCALE: 0.1,  // 缩小最小限度
    pos: { x: 0, y: 0 },
    posl: { x: 0, y: 0 },
    dragging: false,  // 是否可以拖拽
    imgScale: 1,    // 缩放比例
    imgXAutoScale: 0,   // 图片适应拉伸宽度
    imgYAutoScale: 0,   // 图片适应拉伸高度
  }
}

初始化 init()

js
init() {
  this.imgScale = 1
  this.imgX = 0
  this.imgY = 0
  this.context = this.$refs.canvas.getContext('2d')
  this.loadImg()
}
init() {
  this.imgScale = 1
  this.imgX = 0
  this.imgY = 0
  this.context = this.$refs.canvas.getContext('2d')
  this.loadImg()
}

加载图片 loadImg()

js
loadImg() {
  const that = this
  this.img = new Image()
  this.img.src = this.imageUrl
  this.img.onload = function() {
    that.imgXAutoScale = that.$refs.canvas.width / that.img.width
    that.imgYAutoScale = that.$refs.canvas.height / that.img.height
    that.drawImage()
  }
}
loadImg() {
  const that = this
  this.img = new Image()
  this.img.src = this.imageUrl
  this.img.onload = function() {
    that.imgXAutoScale = that.$refs.canvas.width / that.img.width
    that.imgYAutoScale = that.$refs.canvas.height / that.img.height
    that.drawImage()
  }
}

绘制操作后的图片 drawImage()

js
drawImage() {
  this.context.clearRect(0, 0, this.$refs.canvas.width, this.$refs.canvas.height)
  this.context.drawImage(
    this.img, // 规定要使用的图像、画布或视频。
    0, 0, // 开始剪切的 x 坐标位置。
    this.img.width,
    this.img.height, // 被剪切图像的高度。
    this.imgX, this.imgY, // 在画布上放置图像的x、y坐标位置。
    this.img.width * this.imgScale * this.imgXAutoScale,
    this.img.height * this.imgScale * this.imgYAutoScale // 要使用的图像的宽度、高度
  )
}
drawImage() {
  this.context.clearRect(0, 0, this.$refs.canvas.width, this.$refs.canvas.height)
  this.context.drawImage(
    this.img, // 规定要使用的图像、画布或视频。
    0, 0, // 开始剪切的 x 坐标位置。
    this.img.width,
    this.img.height, // 被剪切图像的高度。
    this.imgX, this.imgY, // 在画布上放置图像的x、y坐标位置。
    this.img.width * this.imgScale * this.imgXAutoScale,
    this.img.height * this.imgScale * this.imgYAutoScale // 要使用的图像的宽度、高度
  )
}

鼠标移动事件 mousemove(event)

js
mousemove(event) {
  if (this.dragging) {
    this.posl = this.windowToCanvas(event.clientX, event.clientY)
    this.imgX += this.posl.x - this.pos.x
    this.imgY += this.posl.y - this.pos.y
    this.pos = JSON.parse(JSON.stringify(this.posl))
    this.drawImage()
  }
}
mousemove(event) {
  if (this.dragging) {
    this.posl = this.windowToCanvas(event.clientX, event.clientY)
    this.imgX += this.posl.x - this.pos.x
    this.imgY += this.posl.y - this.pos.y
    this.pos = JSON.parse(JSON.stringify(this.posl))
    this.drawImage()
  }
}

鼠标按下事件 mousedown(event)

js
mousedown(event) {
  this.dragging = true
  this.pos = this.windowToCanvas(event.clientX, event.clientY)
}
mousedown(event) {
  this.dragging = true
  this.pos = this.windowToCanvas(event.clientX, event.clientY)
}

鼠标抬起事件 mouseup()

js
mouseup() {
  this.dragging = false
},
mouseup() {
  this.dragging = false
},

监听图片路径发生改变

js
watch: {
  'imageUrl'(val) {
    if (val) {
      this.init()
    }
  }
}
watch: {
  'imageUrl'(val) {
    if (val) {
      this.init()
    }
  }
}

计算鼠标位置相对于canvas的坐标 windowToCanvas(x, y)

js
windowToCanvas(x, y) {
  var box = this.$refs.canvas.getBoundingClientRect()
  return {
    x: x - box.left - (box.width - this.$refs.canvas.width) / 2,
    y: y - box.top - (box.height - this.$refs.canvas.height) / 2
  }
}
windowToCanvas(x, y) {
  var box = this.$refs.canvas.getBoundingClientRect()
  return {
    x: x - box.left - (box.width - this.$refs.canvas.width) / 2,
    y: y - box.top - (box.height - this.$refs.canvas.height) / 2
  }
}

鼠标滚轮事件 wheel(event)

js
wheel(event) {
  // 参考点坐标
  var pos = this.windowToCanvas(event.clientX, event.clientY)
  const wheelDelta = event.wheelDelta ? event.wheelDelta : (event.deltaY * (-40))
  // 图片上次的参考
  var newPos = {
    x: Number(((pos.x - this.imgX) / this.imgScale).toFixed(2)),
    y: Number(((pos.y - this.imgY) / this.imgScale).toFixed(2))
  }
  if (wheelDelta > 0) {
    this.imgScale += 0.1
  } else {
    this.imgScale -= 0.1
    if (this.imgScale < this.MINIMUM_SCALE) {
      this.imgScale = this.MINIMUM_SCALE
    }
  }
  this.imgX = (1 - this.imgScale) * newPos.x + (pos.x - newPos.x)
  this.imgY = (1 - this.imgScale) * newPos.y + (pos.y - newPos.y)
  this.drawImage()
}
wheel(event) {
  // 参考点坐标
  var pos = this.windowToCanvas(event.clientX, event.clientY)
  const wheelDelta = event.wheelDelta ? event.wheelDelta : (event.deltaY * (-40))
  // 图片上次的参考
  var newPos = {
    x: Number(((pos.x - this.imgX) / this.imgScale).toFixed(2)),
    y: Number(((pos.y - this.imgY) / this.imgScale).toFixed(2))
  }
  if (wheelDelta > 0) {
    this.imgScale += 0.1
  } else {
    this.imgScale -= 0.1
    if (this.imgScale < this.MINIMUM_SCALE) {
      this.imgScale = this.MINIMUM_SCALE
    }
  }
  this.imgX = (1 - this.imgScale) * newPos.x + (pos.x - newPos.x)
  this.imgY = (1 - this.imgScale) * newPos.y + (pos.y - newPos.y)
  this.drawImage()
}

鼠标移出元素事件 mouseout()

js
mouseout() {
  this.dragging = false
}
mouseout() {
  this.dragging = false
}