最新文章专题视频专题问答1问答10问答100问答1000问答2000关键字专题1关键字专题50关键字专题500关键字专题1500TAG最新视频文章推荐1 推荐3 推荐5 推荐7 推荐9 推荐11 推荐13 推荐15 推荐17 推荐19 推荐21 推荐23 推荐25 推荐27 推荐29 推荐31 推荐33 推荐35 推荐37视频文章20视频文章30视频文章40视频文章50视频文章60 视频文章70视频文章80视频文章90视频文章100视频文章120视频文章140 视频2关键字专题关键字专题tag2tag3文章专题文章专题2文章索引1文章索引2文章索引3文章索引4文章索引5123456789101112131415文章专题3
当前位置: 首页 - 科技 - 知识百科 - 正文

vue裁切图片实现放大、缩小、旋转功能代码

来源:动视网 责编:小OO 时间:2020-11-27 20:02:02
文档

vue裁切图片实现放大、缩小、旋转功能代码

实现效果。裁切指定区域内的图片。旋转图片;放大图片;输出bolb 格式数据 提供给 formData 对象。效果图;;;;大概原理。利用h5 FileReader 对象,获取 <;input type=";file";/>;“上传到浏览器的文件” ,文件形式 为base形式,把 base 赋给canvas的上下文。然后给canvas 元素上加入对(mousedown)监听事件。当用户鼠标左键在canvas按下时。挂载对 window 对象mousemove事件 --->;获取 鼠标移动x,y距离.从而操作 canvas里的图像的位置移动。
推荐度:
导读实现效果。裁切指定区域内的图片。旋转图片;放大图片;输出bolb 格式数据 提供给 formData 对象。效果图;;;;大概原理。利用h5 FileReader 对象,获取 <;input type=";file";/>;“上传到浏览器的文件” ,文件形式 为base形式,把 base 赋给canvas的上下文。然后给canvas 元素上加入对(mousedown)监听事件。当用户鼠标左键在canvas按下时。挂载对 window 对象mousemove事件 --->;获取 鼠标移动x,y距离.从而操作 canvas里的图像的位置移动。
 本文主要和大家介绍了vue实现裁切图片同时实现放大、缩小、旋转功能,小编觉得挺不错的,现在分享给大家,也给大家做个参考,希望能帮助到大家。

实现效果:

  1. 裁切指定区域内的图片

  2. 旋转图片

  3. 放大图片

  4. 输出bolb 格式数据 提供给 formData 对象

效果图







大概原理:

利用h5 FileReader 对象, 获取 <input type="file"/> “上传到浏览器的文件” ,文件形式 为base形式, 把 base 赋给canvas的上下文。

然后给canvas 元素上加入对(mousedown)监听事件。 当用户鼠标左键在canvas按下时:

  1. 挂载对 window 对象mousemove事件 ---> 获取 鼠标移动x,y距离.从而操作 canvas里的图像的位置移动。

  2. 挂载对 window 对象mouseup 事件, 清除 mousemove事件的绑定。(同时该事件触发后会被删除)

剩下的 放大、缩小 、 旋转 是对 canvas 对象的操作/坐标体系的操作。具体api详见mdn canvas 文档

代码

dom.js

组件模板

<template>
 <p class="jc-clip-image" :style="{width: `${clip.width}`}">
 <canvas ref="ctx"
 :width="clip.width"
 :height="clip.height"
 @mousedown="handleClip($event)"
 >
 </canvas>
 <input type="file" ref="file" @change="readFileMsg($event)">
 <p class="clip-scale-btn">
 <a class="add" @click="handleScale(false)">+</a>
 <a @click="rotate" class="right-rotate">转</a>
 <a class="poor" @click="handleScale(true)">-</a>
 <span>{{scale}}</span>
 </p>
 <p class="upload-warp">
 <a class="upload-btn" @click="dispatchUpload($event)">upload</a>
 <a class="upload-cancel">cancel</a>
 </p>
 <p class="create-canvas">
 <a class="to-send-file" @click="outFile" title="请打开控制台">生成文件</a>
 </p>
 </p>
</template>
<script>
 import {on, off, once} from '../../utils/dom'
 export default {
 ctx: null, 
 file: null, 
 x: 0, // 点击canvas x 鼠标地址
 y: 0,// 点击canvas y 鼠标地址
 xV: 0, // 鼠标移动 x距离
 yV: 0, // 鼠标移动 y距离
 nX: 0, // 原始坐标点 图像 x
 nY: 0,// 原始坐标点 图像 y
 img: null,
 props: {
 src: {
 type: String,
 default: null
 },
 clip: {
 type: Object,
 default () {
 return {width: '200px', height: '200px'}
 }
 }
 },
 data () {
 return {
 isShow: false,
 base: null,
 scale: 1.5, //放大比例
 deg: 0 //旋转角度
 }
 },
 computed: {
 width () {
 const {clip} = this
 return parseFloat(clip.width.replace('px', ''))
 },
 height () {
 const {clip} = this
 return parseFloat(clip.height.replace('px', ''))
 }
 },
 mounted () {
 const {$options, $refs, width, height} = this
 // 初始化 canvas file nX nY
 Object.assign($options, {
 ctx: $refs.ctx.getContext('2d'),
 file: $refs.file,
 nX: -width / 2,
 nY: -height / 2
 })
 },
 methods: {
 // 旋转操作
 rotate () {
 const {$options, draw} = this
 this.deg = (this.deg + Math.PI /2)% (Math.PI * 2)
 draw($options.img, $options.nX + $options.xV, $options.nY + $options.yV, this.scale, this.deg)
 },
 // 处理放大
 handleScale (flag) {
 const {$options, draw, deg} = this
 flag && this.scale > 0.1 && (this.scale = this.scale - 0.1)
 !flag && this.scale < 1.9 && (this.scale = this.scale + 0.1)
 $options.img && draw($options.img, $options.nX + $options.xV, $options.nY + $options.yV, this.scale, deg)
 },
 // 模拟file 点击事件
 dispatchUpload (e) {
 this.clearState()
 const {file} = this.$options
 e.preventDefault()
 file.click()
 },
 // 读取 input file 信息
 readFileMsg () {
 const {file} = this.$options
 const {draw, createImage, $options: {nX, nY}, scale, deg} = this
 const wFile = file.files[0]
 const reader = new FileReader()
 reader.onload = (e) => {
 const img = createImage(e.target.result, (img) => {
 draw(img, nX, nY, scale, deg)
 })
 file.value = null
 }
 reader.readAsDataURL(wFile)
 },
 // 生成 图像
 createImage (src, cb) {
 const img = new Image()
 this.$el.append(img)
 img.className = 'base-hidden'
 img.onload = () => {
 cb(img)
 }
 img.src = src
 this.$options.img = img
 },
 // 操作画布画图
 draw (img, x = 0, y = 0, scale = 0.5,deg = Math.PI ) {
 const {ctx} = this.$options
 let {width, height} = this
 // 图片尺寸
 let imgW = img.offsetWidth
 let imgH = img.offsetHeight
 ctx.save()
 ctx.clearRect( 0, 0, width, height)
 ctx.translate( width / 2, height / 2, img)
 ctx.rotate(deg)
 ctx.drawImage(img, x, y, imgW * scale, imgH * scale)
 ctx.restore()
 },
 // ... 事件绑定
 handleClip (e) {
 const {handleMove, $options, deg} = this
 if (!$options.img) {
 return
 }
 Object.assign(this.$options, {
 x: e.screenX,
 y: e.screenY
 })
 on({
 el: window,
 type: 'mousemove',
 fn: handleMove
 })
 once({
 el: window,
 type: 'mouseup',
 fn: (e) =>{
 console.log('down')
 switch (deg) {
 case 0: {
 Object.assign($options, {
 nX: $options.nX + $options.xV,
 nY: $options.nY + $options.yV,
 xV: 0,
 yV: 0
 })
 break;
 }
 case Math.PI / 2: {
 Object.assign($options, {
 nX: $options.nY + $options.yV,
 nY: $options.nX - $options.xV,
 xV: 0,
 yV: 0
 })
 break;
 }
 case Math.PI: {
 Object.assign($options, {
 nX: $options.nX - $options.xV,
 nY: $options.nY - $options.yV,
 xV: 0,
 yV: 0
 })
 break;
 }
 default: {
 // $options.nY - $options.yV, $options.nX + $options.xV
 Object.assign($options, {
 nX: $options.nY - $options.yV,
 nY: $options.nX + $options.xV,
 xV: 0,
 yV: 0
 })
 }
 }
 off({
 el: window,
 type: 'mousemove',
 fn: handleMove
 })
 }
 })
 },
 // ... 处理鼠标移动
 handleMove (e){
 e.preventDefault()
 e.stopPropagation()
 const {$options, draw, scale, deg} = this
 Object.assign($options, {
 xV: e.screenX - $options.x,
 yV: e.screenY - $options.y
 })
 switch (deg) {
 case 0: {
 draw($options.img, $options.nX + $options.xV, $options.nY + $options.yV, scale, deg)
 break;
 }
 case Math.PI / 2: {
 draw($options.img, $options.nY + $options.yV, $options.nX - $options.xV, scale, deg)
 break;
 }
 case Math.PI: {
 draw($options.img, $options.nX - $options.xV, $options.nY - $options.yV, scale, deg)
 break;
 }
 default: {
 draw($options.img, $options.nY - $options.yV, $options.nX + $options.xV, scale, deg)
 break;
 }
 }
 },
 // 清除状态
 clearState () {
 const {$options, width, height} = this
 if ($options.img) {
 this.$el.removeChild($options.img)
 Object.assign($options, {
 x: 0,
 y: 0,
 xV: 0,
 yV: 0,
 nX: -width / 2,
 nY: -height / 2,
 img: null,
 })
 }
 },
 // 
输出文件 outFile () { const {$refs: {ctx}} = this console.log(ctx.toDataURL()) ctx.toBlob((blob) => {console.log(blob)}) } } } </script> <style> @component-namespace jc { @component clip-image{ position: relative; width: 100%; canvas { position: relative; width: 100%; height: 100%; cursor: pointer; box-shadow: 0 0 3px #333; } input { display: none; } .base-hidden { position: absolute; top: 0; left: 0; display: block; width: 100%; height: auto; z-index: -999; opacity: 0; } .clip-scale-btn { position: relative; @utils-clearfix; margin-bottom: 5px; text-align: center; a { float: left; width: 20px; height: 20px; border-radius: 50%; color: #fff; background: #49a9ee; text-align: center; cursor: pointer; } &>.poor, &>.right-rotate { float: right; } &>span{ position: absolute; z-index: -9; top: 0; left: 0; display: block; position: relative; width: 100%; text-align: center; height: 20px; line-height: 20px; } } .upload-warp { @utils-clearfix; .upload-btn,.upload-cancel { float: left; display:inline-block; width: 60px; height: 25px; line-height: 25px; color: #fff; border-radius: 5px; background: #49a9ee; box-shadow: 0 0 0 #333; text-align: center; top: 0; left: 0; right: 0; bottom: 0; margin: auto; cursor: pointer; margin-top: 5px; } .upload-cancel{ background: gray; float: right; } } .to-send-file { margin-top: 5px; display: block; width: 50px; height: 25px; line-height: 25px; color: #fff; border-radius: 5px; background: #49a9ee; cursor: pointer; } }

文档

vue裁切图片实现放大、缩小、旋转功能代码

实现效果。裁切指定区域内的图片。旋转图片;放大图片;输出bolb 格式数据 提供给 formData 对象。效果图;;;;大概原理。利用h5 FileReader 对象,获取 <;input type=";file";/>;“上传到浏览器的文件” ,文件形式 为base形式,把 base 赋给canvas的上下文。然后给canvas 元素上加入对(mousedown)监听事件。当用户鼠标左键在canvas按下时。挂载对 window 对象mousemove事件 --->;获取 鼠标移动x,y距离.从而操作 canvas里的图像的位置移动。
推荐度:
标签: 图片 旋转 VUE
  • 热门焦点

最新推荐

猜你喜欢

热门推荐

专题
Top