本篇文章主要介绍了vue实现裁切图片同时实现放大、缩小、旋转功能,分享给大家,具体如下:
实现效果:
- 裁切指定区域内的图片
- 旋转图片
- 放大图片
- 输出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 = argments
return () => {
clearTimeout(k)
k = cTime = null
fn(...ags)
}
}
return () => {
if (cTime == null) {
k = setTimeout(hyFn(...arguments), time)
cTime = getTime()
} else {
if ( getTime() - cTime < 0) {
// 清除之前的函数堆 ---- 重新记录
clearTimeout(k)
k = null
cTime = getTime()
k = setTimeout(hyFn(...arguments), time)
}
}}
}
export const contains = function(parentNode, childNode) {
if (parentNode.contains) {
return parentNode != childNode && parentNode.contains(childNode)
} else {
return !!(parentNode.comparedocumentPosition(childNode) & 16)
}
}
export const addClass = function (el, className) {
if (typeof el !== "object") {
console.log('el is not elem')
return null
}
let classList = el['className']
classList = classList === '' ? [] : classList.split(/s+/)
if (classList.indexOf(className) === -1) {
classList.push(className)
el.className = classList.join(' ')
} else {
console.warn('warn className current')
}
}
export const removeClass = function (el, className) {
let classList = el['className']
classList = classList === '' ? [] : classList.split(/s+/)
classList = classList.filter(item => {
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 < time) {
oT = cT
clearTimeout(k)
k = setTimeout(fixFn, time)
}
}
}
export const Event = function () {
// 类型
this.typeList = {}
}
Event.prototype.on = function ({type, fn}){
if (this.typeList.hasOwnProperty(type)) {
this.typeList[type].push(fn)
} else {
this.typeList[type] = []
this.typeList[type].push(fn)
}
}
Event.prototype.off = function({type, fn}) {
if (this.typeList.hasOwnProperty(type)) {
let list = this.typeList[type]
let index = list.indexOf(fn)
if (index !== -1 ) {
list.splice(index, 1)
}
} else {
console.warn('not has this type')
}
}
Event.prototype.once = function ({type, fn}) {
const fixFn = () => {
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}}
upload
cancel
生成文件
@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;
}
}
项目代码:https://github.com/L6zt/vuesrr
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持考高分网。



