Vue + Canvas 实现头像截图上传功能
首先,我们需要两张画布,一个展示选取图片的压缩图,一个展示截取后的图片。废话不多讲上代码如下:HTML<!DOCTYPE html><html><head><meta charset="UTF-8"><meta name="viewport&q
·
首先,我们需要两张画布,一个展示选取图片的压缩图,一个展示截取后的图片。
废话不多讲上代码如下:
HTML
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />
<!--<meta name="viewport" content="target-densitydpi=320,width=640,user-scalable=no">--><!--1.禁止缩放-->
<title></title>
<!--引入vue-->
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17-beta.0/vue.min.js"></script>
<!--引入css-->
<link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet">
<link rel="stylesheet" type="text/css" href="global.css"/>
<link rel="stylesheet" type="text/css" href="index.css" />
</head>
<body>
<div id="app" v-cloak>
<div class="container">
<ul class="information creater_class">
<li class="infor files">
<div style="width: 100%;height: 300px;border: 1px solid #ccc;" class="center">
<div class="center">
<canvas style="border: 1px solid #ccc;border-radius: 50%;width: 300px;height: 300px;margin: 0 auto;display: block;" ref="originalCanvas" ref="originalCanvas" @touchstart.prevent="hasImgSrc?pressDown(originalCtx,$event):false" @touchmove.prevent="mouseDown?moveMouse($event):false" @touchend.prevent="stopCut">
您的浏览器不支持canvas,请升级最新版本
</canvas>
<p class="img-scale theme-red center">
图片压缩:
<span v-text="Math.round(originalCanvasWidth) + ' * ' + Math.round(originalCanvasHeight)"></span>
</p>
<div v-if="hasImgSrc" class="center">
<button @click="chooseSize(cutSize)" type="button" class="btn btn-danger">Min</button>
<button @click="reduceSize" type="button" class="btn btn-danger">-</button>
<button @click="plusSize" type="button" class="btn btn-danger">+</button>
<button @click="chooseSize(scaleSize)" type="button" class="btn btn-danger">Max</button>
</div>
<div class="bg-info text-center" style="line-height: 50px;height: 50px;">选择图片
<input type="file" @change="chooseImg($event)">
</div>
</div>
<div v-show="hasImgSrc" class="center">
<canvas ref="cutCanvas">
您的浏览器不支持canvas,请升级最新版本
</canvas>
<p class="theme-red center">
截图长度:
<span v-text="Math.round(cutSize) + ' * ' + Math.round(cutSize)"></span>
</p>
<button @click="submitImg" class="btn btn-info">上传头像</button>
</div>
</div>
</li>
</ul>
</div>
</div>
<script src="index.js" type="text/javascript" charset="utf-8"></script>
</body>
</html>
JS
//model
var data = {
//图片
originalCanvas: null, // 原图 画布
originalCtx: null, // 原图 上下文
originalImg: null, // 原图片的对象
cutCanvas: null, // 显示裁剪后图片的画布
cutCtx: null, // 裁图 画布 上下文
cutImg: null, // 裁剪后 图片的对象
originalCanvasWidth: 0, // 原图 压缩后 宽度
originalCanvasHeight: 0, // 原图 压缩后 高度
scaleSize: 300, // 原图压缩的尺寸
cutSize: 200, // 裁剪 正方形的宽高
hasImgSrc: false, // 是否有可裁剪图片
centerX: 0, // 原图画布中心 X坐标
centerY: 0, // 原图画布中心 Y坐标
mouseX: 0, // 鼠标所在点 X坐标
mouseY: 0, // 鼠标所在点 Y坐标
differenceX: 0, // 原点X - 鼠标X点 差值
differenceY: 0, // 原点Y - 鼠标Y点 差值
mouseDown: false, // 鼠标是否点击
hasImgSrc: false, // 是否有可裁剪图片
imageDate: null, // 截图 对象
tempImageData: null, // 实时截图 缓存对象
imgFormat: ['jpg', 'png'] // 图片上传格式
}
//ViewModel
var app = new Vue({
el: "#app",
data: data,
mounted () {
// 初始化 原图的画布
let originalCanvas = this.originalCanvas = this.$refs.originalCanvas
let originalCtx = this.originalCtx = originalCanvas.getContext('2d')
// 初始化 裁图 画布
let cutCanvas = this.cutCanvas = this.$refs.cutCanvas
this.cutCtx = cutCanvas.getContext('2d')
// 设置画布宽高
originalCanvas.width = this.originalCanvasWidth = this.scaleSize
originalCanvas.height = this.originalCanvasHeight = this.scaleSize
cutCanvas.width = this.cutSize
cutCanvas.height = this.cutSize
// 绘制默认图片
if (originalCanvas.getContext) {
let originalImg = this.originalImg = new Image()
originalImg.src = 'data:image/jpeg;base64,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MiYiuwPlkxw3s3+NblFCdjOrShVjyTV0eN3lncWFy1vcxmORex7+49RXslZ+raPa6xbeVcLhx9yQfeQ/57VoVTdzjwWDeGnPW6drfiFcV8Qf+Yd/21/9lrta4r4g/wDMO/7a/wDstEdysz/3WXy/NHE0UUVofJhRRRQB23w+/wCYj/2y/wDZq7WuK+H3/MR/7Zf+zV2tZy3PrMs/3WPz/NhWdoelppGlx2wwZPvSMO7Hr/h+FaNFSdjgnJSe6/UKKKKCgooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAK4r4g/8w7/ALa/+y12tcV8Qf8AmHf9tf8A2WqjucOZ/wC6y+X5o4miiitD5MKKKKAO2+H3/MR/7Zf+zV2tcV8Pv+Yj/wBsv/Zq7Ws5bn1mWf7rH5/mwoooqTuCiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAK4r4g/8w7/ALa/+y12tcV8Qf8AmHf9tf8A2WqjucOZ/wC6y+X5o4miiitD5MKKKKAO0+H7APqC55IjP/oX+NdvXlvhnVF0vWEkkOIZR5ch9Aeh/A4r1IEEZByDWctz6fKqilh1Fbr/AIcKKKKk9MKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAriPiAwL6eueQJCf/Hf8K7ckAEk4A6k15Z4m1RdV1h5IzmGMeXGfUDv+JzVR3PMzWoo4dxe7/wCHMeiiitD5gKKKKACur8PeLmsI1tL/AHPbrwkg5ZB6H1FcpRQ1c2oV50Jc8GexWuoWd6ga2uYpQf7rcj6jqKs14pRUch60c6dtYfj/AMA9rorxSijkH/bX9z8f+Ae10V4pRRyB/bX9z8f+Ae10V4pRRyB/bX9z8f8AgHtdFeKUUcgf21/c/H/gHtdFeKUUcgf21/c/H/gHtdFeKUUcgf21/c/H/gHtdFeKUUcgf21/c/H/AIB7XRXilFHIH9tf3Px/4B7XRXilFHIH9tf3Px/4B7XRXilFHIH9tf3Px/4B7XRXilFHIH9tf3Px/wCAe10V4pRRyB/bX9z8f+Ae10V4pRRyB/bX9z8f+Ae10V4pRRyB/bX9z8f+Ae10V4pRRyB/bX9z8f8AgHtdFeKUUcgf21/c/H/gHtdFeKUUcgf21/c/H/gHtdFeKUUcgf21/c/H/gHtdFeKUUcgf21/c/H/AIB7XVa61GzsULXNzFEB2ZuT9B1NeO0UcgpZ07aQ/H/gHU+IfFrahG1pYho7c8O54Zx6ewrlqKKtKx5NavOtLnmwooooMQooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooA//9k=';
originalImg.onload = () => {
originalCtx.drawImage(originalImg, originalCanvas.width / 2 - this.cutSize / 2, originalCanvas.height / 2 - this.cutSize / 2, this.cutSize, this.cutSize)
}
}
},
methods:{
// 选择图片
chooseImg:function (e) {
// 选中文件择执行
if (e.target.files.length !== 0) {
// 获取文件
let file = e.target.files[0]
// 限定上传格式
let arr = this.imgFormat
let str = file.name.split('.').pop()
if (arr.indexOf(str) !== -1) {
// 转换成Base 64位
this.changeDataURL(file, (dataUrl) => {
this.originalImg.src = dataUrl
// 获取图片 宽高
let width = this.originalImg.width
let height = this.originalImg.height
//在画布没发生变化时,清除画布区域,重置画布的宽高为默认的值,然后对比宽高,短的一边给默认值(300),长的一边等比计算:
// 清除画布
this.clearCanvas()
// 重置画布的宽高
let originalCanvas = this.originalCanvas
originalCanvas.width = this.originalCanvasWidth = this.scaleSize
originalCanvas.height = this.originalCanvasHeight = this.scaleSize
// 设置画布压缩后的宽高
if (width > height) {
originalCanvas.width = this.originalCanvasWidth = width * this.scaleSize / height
} else if (width < height) {
originalCanvas.height = this.originalCanvasHeight = height * this.scaleSize / width
}
// 设置绘图原点
this.centerX = Math.round(originalCanvas.width / 2)
this.centerY = Math.round(originalCanvas.height / 2)
// 图片加载完成 绘制选中的图片
this.originalImg.onload = () => {
// 允许鼠标点击事件
this.hasImgSrc = true
// 绘制图片
this.drawOriginal(this.originalImg, originalCanvas.width, originalCanvas.height)
}
})
} else {
alert('图片格式错误')
}
}
},
// 转换成dataUrl
changeDataURL:function (fileObj, callback) {
let file = new FileReader()
file.readAsDataURL(fileObj)
file.onload = (e) => { callback(e.target.result) }
},
// 清除画布
clearCanvas:function () {
// 绘制原图片
this.originalCtx.clearRect(0, 0, this.originalCanvasWidth, this.originalCanvasHeight)
},
// 绘制 压缩后的图片
drawOriginal:function (img, width, height) {
// 绘制 原图
this.originalCtx.drawImage(img, 0, 0, width, height)
// 缓存 截图对象
this.imageData = this.originalCtx.getImageData(this.centerX - this.cutSize / 2, this.centerY - this.cutSize / 2, this.cutSize, this.cutSize)
// 清除截图区域时使用
this.tempImageData = this.originalCtx.getImageData(this.centerX - this.cutSize / 2 - 1, this.centerY - this.cutSize / 2 - 1, this.cutSize + 2, this.cutSize + 2)
// 绘制 截图框
this.drawCuttingFrame(this.originalCtx, this.centerX, this.centerY, this.cutSize / 2, 20)
// 绘制 裁剪图片
this.drawCutImage(this.imageData)
},
drawCuttingFrame:function (ctx, x, y, l, d) {
ctx.beginPath()
// 右上框
ctx.moveTo(x - 1, y - l)
ctx.lineTo(x + 1, y - l)
ctx.moveTo(x + d, y - l)
ctx.lineTo(x + l, y - l)
ctx.lineTo(x + l, y - d)
// 右下框
ctx.moveTo(x + l, y - 1)
ctx.lineTo(x + l, y + 1)
ctx.moveTo(x + l, y + d)
ctx.lineTo(x + l, y + l)
ctx.lineTo(x + d, y + l)
// 左下框
ctx.moveTo(x - 1, y + l)
ctx.lineTo(x + 1, y + l)
ctx.moveTo(x - d, y + l)
ctx.lineTo(x - l, y + l)
ctx.lineTo(x - l, y + d)
// 左上框
ctx.moveTo(x - l, y - 1)
ctx.lineTo(x - l, y + 1)
ctx.moveTo(x - l, y - d)
ctx.lineTo(x - l, y - l)
ctx.lineTo(x - d, y - l)
ctx.strokeStyle = 'green'
ctx.stroke()
ctx.closePath()
},
// 绘制 裁剪后的图片
drawCutImage:function (imageData) {
this.cutCtx.putImageData(imageData, 0, 0)
},
// 鼠标点击事件
pressDown:function (ctx,e) {
// pc:@mousedown.prevent="hasImgSrc ? pressDown(originalCtx, $event) : false" @mousemove="mouseDown ? moveMouse($event) : false" @mouseup="stopCut"
// pc:this.mouseX = e.offsetX
// this.mouseY = e.offsetY
console.log(e.touches[0].clientX +'...'+e.touches[0].clientY)
// 鼠标 坐标
// this.mouseX = e.touches[0].clientX
// this.mouseY = e.touches[0].clientY
this.mouseX = e.touches[0].clientX
this.mouseY = e.touches[0].clientY
// 原点到鼠标之间的差值
this.differenceX = this.centerX - this.mouseX
this.differenceY = this.centerY - this.mouseY
// 截图框内才能拖动
if (Math.abs(this.differenceX) <= this.cutSize / 2 && Math.abs(this.differenceY) <= this.cutSize / 2) {
// 允许鼠标移动事件
this.mouseDown = true
}
},
// 鼠标移动事件
moveMouse:function (e) {
if (this.mouseDown) {
// 清空 上个路径的截图框 X、Y坐标 - 1 宽高 + 2 彻底清除整个截图框区域
this.originalCtx.clearRect(this.centerX - this.cutSize / 2 - 1, this.centerY - this.cutSize / 2 - 1, this.cutSize + 2, this.cutSize + 2)
this.originalCtx.putImageData(this.tempImageData, this.centerX - this.cutSize / 2 - 1, this.centerY - this.cutSize / 2 - 1)
// 重新赋值 截图框原点位置
if (e.touches[0].clientX > this.cutSize / 2 - this.differenceX && e.touches[0].clientX + this.cutSize / 2 + this.differenceX < this.originalCanvas.width) {
// 可移动范围内赋值
this.centerX = e.touches[0].clientX + this.differenceX
} else {
// 不可移动范围内赋值
this.centerX = e.touches[0].clientX <= this.cutSize / 2 - this.differenceX ? this.cutSize / 2 : this.originalCanvas.width - this.cutSize / 2
}
if (e.touches[0].clientY > this.cutSize / 2 - this.differenceY && e.touches[0].clientY + this.cutSize / 2 + this.differenceY < this.originalCanvas.height) {
this.centerY = e.touches[0].clientY + this.differenceY
} else {
this.centerY = e.touches[0].clientY <= this.cutSize / 2 - this.differenceY ? this.cutSize / 2 : this.originalCanvas.height - this.cutSize / 2
}
// 缓存 截图对象
this.imageData = this.originalCtx.getImageData(this.centerX - this.cutSize / 2, this.centerY - this.cutSize / 2, this.cutSize, this.cutSize)
// 缓存 清除截图框的 绘图模块
this.tempImageData = this.originalCtx.getImageData(this.centerX - this.cutSize / 2 - 1, this.centerY - this.cutSize / 2 - 1, this.cutSize + 2, this.cutSize + 2)
// 重绘截图框
this.drawCuttingFrame(this.originalCtx, this.centerX, this.centerY, this.cutSize / 2, 20)
// 绘制 裁剪图片
this.drawCutImage(this.imageData);
//阻止页面的滑动默认事件
// document.addEventListener("touchmove",function(){
// event.preventDefault();
// },false);
}
},
// 松开鼠标点击
stopCut:function () {
// 停止鼠标拖动事件
this.mouseDown = false
},
// 尺寸减1 重绘
reduceSize:function () {
// 不能小于裁剪大小
if (this.originalCanvasWidth > this.cutSize && this.originalCanvasHeight > this.cutSize) {
// 清除画布
this.clearCanvas()
// 固定短边,计算长边的值
if (this.originalCanvasWidth > this.originalCanvasHeight) {
this.originalCanvas.height = this.originalCanvasHeight -= 1
this.originalCanvas.width = this.originalCanvasWidth = this.originalCanvasHeight / (this.originalCanvasHeight + 1) * this.originalCanvasWidth
} else if (this.originalCanvasWidth < this.originalCanvasHeight) {
this.originalCanvas.width = this.originalCanvasWidth -= 1
this.originalCanvas.height = this.originalCanvasHeight = this.originalCanvasWidth / (this.originalCanvasWidth + 1) * this.originalCanvasHeight
} else {
this.originalCanvas.width = this.originalCanvasWidth -= 1
this.originalCanvas.height = this.originalCanvasHeight -= 1
}
// 设置绘图原点
this.centerX = Math.round(this.originalCanvas.width / 2)
this.centerY = Math.round(this.originalCanvas.height / 2)
// 绘制 原图 截图框
this.drawOriginal(this.originalImg, this.originalCanvasWidth, this.originalCanvasHeight)
}
},
// 尺寸加1 重绘
plusSize:function () {
if (!(this.originalCanvasWidth >= 300 && this.originalCanvasHeight >= 300)) {
// 清除画布
this.clearCanvas()
// 计算长边的值
if (this.originalCanvasWidth > this.originalCanvasHeight) {
this.originalCanvas.height = this.originalCanvasHeight += 1
this.originalCanvas.width = this.originalCanvasWidth = this.originalCanvasHeight / (this.originalCanvasHeight - 1) * this.originalCanvasWidth
} else if (this.originalCanvasWidth < this.originalCanvasHeight) {
this.originalCanvas.width = this.originalCanvasWidth += 1
this.originalCanvas.height = this.originalCanvasHeight = this.originalCanvasWidth / (this.originalCanvasWidth - 1) * this.originalCanvasHeight
} else {
this.originalCanvas.width = this.originalCanvasWidth += 1
this.originalCanvas.height = this.originalCanvasHeight += 1
}
// 设置绘图原点
this.centerX = Math.round(this.originalCanvas.width / 2)
this.centerY = Math.round(this.originalCanvas.height / 2)
// 绘制 原图 截图框
this.drawOriginal(this.originalImg, this.originalCanvasWidth, this.originalCanvasHeight)
}
},
// 选择最大 最小 缩放比例 重绘
chooseSize:function (size) {
// 清除画布
this.clearCanvas()
// 计算长边的值
let width = this.originalCanvasWidth
let height = this.originalCanvasHeight
let originalCanvas = this.originalCanvas
if (width > height) {
originalCanvas.width = this.originalCanvasWidth = size / height * width
originalCanvas.height = this.originalCanvasHeight = size
} else if (width < height) {
originalCanvas.height = this.originalCanvasHeight = size / width * height
originalCanvas.width = this.originalCanvasWidth = size
} else {
originalCanvas.width = this.originalCanvasWidth = size
originalCanvas.height = this.originalCanvasHeight = size
}
// 设置绘图原点,最好取整,有奇怪的bug
this.centerX = Math.round(originalCanvas.width / 2)
this.centerY = Math.round(originalCanvas.height / 2)
// 绘制 原图 截图框
this.drawOriginal(this.originalImg, originalCanvas.width, originalCanvas.height)
},
// 上传头像
submitImg:function () {
// 生成截图
let dataUrl = this.cutCanvas.toDataURL('image/png');
console.log(dataUrl)
}
}
});
完整代码:https://download.csdn.net/download/qq_42396791/10731191
更多推荐
已为社区贡献15条内容
所有评论(0)