首先,我们需要两张画布,一个展示选取图片的压缩图,一个展示截取后的图片。

废话不多讲上代码如下:

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.originalCanvaslet originalCtx = this.originalCtx = originalCanvas.getContext('2d')// 初始化 裁图 画布let cutCanvas = this.cutCanvas = this.$refs.cutCanvasthis.cutCtx = cutCanvas.getContext('2d')// 设置画布宽高originalCanvas.width = this.originalCanvasWidth = this.scaleSizeoriginalCanvas.height = this.originalCanvasHeight = this.scaleSizecutCanvas.width = this.cutSizecutCanvas.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.imgFormatlet str = file.name.split('.').pop()if (arr.indexOf(str) !== -1) {// 转换成Base 64位this.changeDataURL(file, (dataUrl) => {this.originalImg.src = dataUrl// 获取图片 宽高let width = this.originalImg.widthlet height = this.originalImg.height//在画布没发生变化时,清除画布区域,重置画布的宽高为默认的值,然后对比宽高,短的一边给默认值(300),长的一边等比计算:// 清除画布this.clearCanvas()// 重置画布的宽高let originalCanvas = this.originalCanvasoriginalCanvas.width = this.originalCanvasWidth = this.scaleSizeoriginalCanvas.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('图片格式错误')}}},// 转换成dataUrlchangeDataURL: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.offsetYconsole.log(e.touches[0].clientX +'...'+e.touches[0].clientY)// 鼠标 坐标
//        this.mouseX = e.touches[0].clientX
//        this.mouseY = e.touches[0].clientYthis.mouseX = e.touches[0].clientXthis.mouseY = e.touches[0].clientY// 原点到鼠标之间的差值this.differenceX = this.centerX - this.mouseXthis.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 -= 1this.originalCanvas.width = this.originalCanvasWidth = this.originalCanvasHeight / (this.originalCanvasHeight + 1) * this.originalCanvasWidth} else if (this.originalCanvasWidth < this.originalCanvasHeight) {this.originalCanvas.width = this.originalCanvasWidth -= 1this.originalCanvas.height = this.originalCanvasHeight = this.originalCanvasWidth / (this.originalCanvasWidth + 1) * this.originalCanvasHeight} else {this.originalCanvas.width = this.originalCanvasWidth -= 1this.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 += 1this.originalCanvas.width = this.originalCanvasWidth = this.originalCanvasHeight / (this.originalCanvasHeight - 1) * this.originalCanvasWidth} else if (this.originalCanvasWidth < this.originalCanvasHeight) {this.originalCanvas.width = this.originalCanvasWidth += 1this.originalCanvas.height = this.originalCanvasHeight = this.originalCanvasWidth / (this.originalCanvasWidth - 1) * this.originalCanvasHeight} else {this.originalCanvas.width = this.originalCanvasWidth += 1this.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.originalCanvasWidthlet height = this.originalCanvasHeightlet originalCanvas = this.originalCanvasif (width > height) {originalCanvas.width = this.originalCanvasWidth = size / height * widthoriginalCanvas.height = this.originalCanvasHeight = size} else if (width < height) {originalCanvas.height = this.originalCanvasHeight = size / width * heightoriginalCanvas.width = this.originalCanvasWidth = size} else {originalCanvas.width = this.originalCanvasWidth = sizeoriginalCanvas.height = this.originalCanvasHeight = size}// 设置绘图原点,最好取整,有奇怪的bugthis.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

Vue + Canvas 实现头像截图上传功能相关推荐

  1. 头像截图上传两种方式(SWFUpload、一个简单易用的flash插件)

    SWFUpload是一个客户端文件上传工具,最初由Vinterwebb.se开发,它通过整合Flash与JavaScript技术为WEB开发者提供了一个具有丰富功能继而超越传统<input ty ...

  2. 新浪微博 头像上传 php,使用canvas实现仿新浪微博头像截取上传功能_javascript技巧...

    最近看到微博头像上传功能很感兴趣,于是就使用canvas写了一个,本文写的不好还请见谅.本程序目前在谷歌浏览器和火狐浏览器测试可用,ie浏览器无法支持. 因为ie的安全机制不允许img使用本地路径,所 ...

  3. html头像裁剪仿微信,使用canvas实现仿新浪微博头像截取上传功能

    最近看到微博头像上传功能很感兴趣,于是就使用canvas写了一个,本文写的不好还请见谅.本程序目前在谷歌浏览器和火狐浏览器测试可用,ie浏览器无法支持. 因为ie的安全机制不允许img使用本地路径,所 ...

  4. 字节流读写文件案例——模拟文件(头像)上传功能

    字节流读写文件案例--模拟文件(头像)上传功能 需求:使用控制台输出模拟实际开发中上传用户头像的功能 需要定义单个方法 1.在控制台录入用户头像的路径 2.解析路径字符串中文件名是否合法:后缀名为:. ...

  5. ajax实现上传头像功能,网络编程Ajax实现注册并选择头像后上传功能

    在初次接触ajax后,我们做了一个crm训练的项目,大多数小组都有注册用户这一项,但是都忽略掉了一个功能,那就是,很多网站的注册是可以上传头像的,在这里我做了一个在已有的头像数组里选择图片上传作头像的 ...

  6. Vue 中实现 excel文件上传功能

    场景: 上传excel表,并将excel表中的数据构建成实体 <div class="pull-right" v-if="doc"><el-u ...

  7. mysql 存储用户头像_node+vue用户头像处理上传并保存

    2017年7月14日19:21:29 ,最近做个网站,需要有用户头像裁剪上传功能,具体流程是用户在本地选择图片,前端将图片裁剪好发给后端,后端接收到图片将它保存起来,并将信息存入数据库. 先说一下环境 ...

  8. 【Bootstrap-插件使用】Jcrop+fileinput组合实现头像上传功能

    作者:Dreawer 链接:https://zhuanlan.zhihu.com/p/24465742 来源:知乎 著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注明出处. 作者:梦游的龙 ...

  9. [Bootstrap-插件使用]Jcrop+fileinput组合实现头像上传功能

    很久没有更新博客了,再不写点东西都烂了. 这次更新一个小内容,是两个插件的组合使用,实现头像上传功能. 业务需求: 头像上传功能,要对上传的文件进行剪切,且保证头像到服务器时必须是正方形的. 优化&l ...

  10. java 上传头像_javaWeb头像上传功能

    [实例简介] 一个实现可抓取编辑,头像上传功能.只要下载就可以运行,附有源码 [实例截图] [核心代码] 头像上传 └── 头像上传 └── ZoomImageDemo ├── src │   └── ...

最新文章

  1. 进程、线程和协程之间的区别和联系
  2. java内存泄露问题
  3. ftp服务器上传文件权限设置,ftp服务器 上传文件权限设置
  4. 安装Windows7出现:”安装程序无法创建新的系统分区 也无法定位系统分区“ 终极解决方案...
  5. SVN中的trunk branches tags
  6. python读取npy文件的列表_Python,NPY文件,pk3,Python3,读取,h5pklnpznpy,格式,的
  7. win10如何提高电脑画质_win10电脑怎么提高画质 | 手游网游页游攻略大全
  8. .Net·使用ILSpy反编译exe或dll文件保存为项目结构
  9. 修改HBuilder的livereload添加自定义响应模块
  10. 【Cinema 4D】物体路径跟随动画
  11. 斯坦福课程Knowledge Graphs-What is a Knowledge Graph?
  12. 程序员自编 “购房宝典” 火爆 GitHub!
  13. 马踏棋盘问题的程序c语言,C语言马踏棋盘
  14. 小米 admob广告 ID_如何评价即将发布的小米盒子4?
  15. LogMeIn软件介绍
  16. php取FBOX数据,云平台制作(1)-OPC Client取数模块的制作
  17. 互联网日报 | 携程实现疫情以来首季度盈利;360安全浏览器辟谣收费传闻;滴滴再推123全民拼车日...
  18. 问渠那得清如许?为有源头活水来。——java面向对象的思想
  19. 怎么给oracle数据库列转行,oracle数据库 行转列 列转行详解
  20. HTML监测异常退出,HtmlUnit请求页面抛出异常

热门文章

  1. WIN10安装SQL SERVER 2005 服务无法启动
  2. 数据结构 | 单链表SingleList【带你从浅入深真正搞懂链表】
  3. ABBYY FineReader 12 破解版(附注册码)
  4. linux搭建windows无盘系统,linux下无盘系统的安装
  5. Anroid 开发so文件找不到问题-例高德地图SDK提示com.autonavi.amap.mapcore.MapCore.nativeNewInstance问题
  6. MindSpore,易用性提升的思考与实践
  7. Unity 之 自定义编辑器布局
  8. vue 圆形 水波_canvas 水滴图、液体进度条、仿加速球、圆球水波图
  9. 基于Visual studio+Opencv+Python的透视变换、图像处理(灰度化、二值化、Canny边缘检测)模型——以2015数学建模A题太阳影子定位为例
  10. 财经管理中的计算机应用 课后答案,财经管理中的计算机应用