1200字范文,内容丰富有趣,写作的好帮手!
1200字范文 > vue裁切图片实现放大 缩小 旋转功能代码

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

时间:2024-04-13 06:23:55

相关推荐

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

web前端|js教程

旋转,缩小,放大

web前端-js教程

本文主要和大家介绍了vue实现裁切图片同时实现放大、缩小、旋转功能,小编觉得挺不错的,现在分享给大家,也给大家做个参考,希望能帮助到大家。

特娱网源码,vscode下载包卡死,ubuntu 测试外网,tomcat哪里设置密码,httputils爬虫,PHP分页视频,宿迁seo推广推荐公司,介绍一个最新的网站模板下载,婚纱摄影动易网站模板lzw

实现效果:

预约订餐系统源码,vscode修改字符编码,ubuntu 查看系统,tomcat 检查,华为备份文件sqlite,网页设计 张家港,n点 默认数据库,阿里云免费云服务器申请,bootstrap确认框插件,前端如何快速开发框架图,网络爬虫过程,php5 php7,网络推广与seo优化,springboot类,织梦文章tag调用标签,韩国网站模板 psd,bootstrap网页编辑器,物流公司网站模板,网站cms管理后台电话号码,优市网-卷烟订货登录页面,开源的固定资产管理系统,易语言监控程序lzw

裁切指定区域内的图片

英文分类信息网站源码,ubuntu子系统 磁盘,爬虫搜集文字作品,php内存占用长时间降不下来,商洛seo外包lzw

旋转图片

放大图片

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

效果图

大概原理:

利用h5 FileReader 对象, 获取 “上传到浏览器的文件” ,文件形式 为base64形式, 把 base64 赋给canvas的上下文。

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

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

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

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

代码

dom.js

export const on = ({el, type, fn}) => {if (typeof window) { if (window.addEventListener) { el.addEventListener(type, fn, false)} else { el.attachEvent(`on${type}`, fn)}} } export const off = ({el, type, fn}) => { if (typeof window) {if (window.addEventListener) { el.removeEventListener(type, fn)} else { el.detachEvent(`on${type}`, fn)} } } export const once = ({el, type, fn}) => { const hyFn = (event) => {try { fn(event)} finally { off({el, type, fn: hyFn})} } on({el, type, fn: hyFn}) } // 最后一个 export const fbTwice = ({fn, time = 300}) => { let [cTime, k] = [null, null] // 获取当前时间 const getTime = () => new Date().getTime() // 混合函数 const hyFn = () => {const ags = argmentsreturn () => { clearTimeout(k) k = cTime = null fn(...ags)} } return () => {if (cTime == null) { k = setTimeout(hyFn(...arguments), time) cTime = getTime()} else { if ( getTime() - cTime {return item !== className }) el.className = classList.join( ) } export const delay = ({fn, time}) => { let oT = null let k = null return () => {// 当前时间let cT = new Date().getTime()const fixFn = () => { k = oT = null fn()}if (k === null) { oT = cT k = setTimeout(fixFn, time) return}if (cT - oT {fn()this.off({type, fn: fixFn}) } this.on({type, fn: fixFn}) } Event.prototype.trigger = function (type){ if (this.typeList.hasOwnProperty(type)) {this.typeList[type].forEach(fn => { fn()}) } }

组件模板

+转-{{scale}}

uploadcancel

生成文件

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,base64: null,scale: 1.5, //放大比例deg: 0 //旋转角度 } }, computed: {width () { const {clip} = thisreturn parseFloat(clip.width.replace(px, \)) }, height () {const {clip} = thisreturn parseFloat(clip.height.replace(px, \)) } }, mounted () { const {$options, $refs, width, height} = this // 初始化 canvas file nX nYObject.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 {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 = ase64-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.xVObject.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)})} } } @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;}.base64-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;} }

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。