VIP用户交流群:462197261 收藏本站北冥有鱼 互联网前沿资源第一站 助力全行业互联网+
在线客服:78895949
tonglan
  • 当前位置:
  • 详解vue项目中实现图片裁剪功能

    建站教程 2019年11月09日 关键词:,,,

    演示地址

    https://my729.github.io/picture-crop-demo/dist/#/

    前言

    • vue版本:3.6.3 https://cli.vuejs.org/zh/
    • cropperjs: 1.5.1 https://github.com/fengyuanchen/cropperjs
    • elementUI https://element.eleme.io/#/zh-CN

    使用 cropperjs插件 和 原生canvas 两种方式实现图片裁剪功能

    使用cropperjs插件

    安装cropperjs

    yarn install cropperjs
    

    初始化一个canvas元素,并在上面绘制图片

    <canvas :id="data.src" ref="canvas"></canvas>
    // 在canvas上绘制图片
    drawImg () {
     this.$nextTick(() => {
     // 获取canvas节点
     let canvas = document.getElementById(this.data.src)
     if (canvas) {
     // 设置canvas的宽为canvas的父元素宽度,宽高比3:2
     let parentEle = canvas.parentElement
     canvas.width = parentEle.offsetWidth
     canvas.height = 2 * parentEle.offsetWidth / 3
     let ctx = canvas.getContext('2d')
     ctx.clearRect(0, 0, canvas.width, canvas.height)
     let img = new Image()
     img.crossOrigin = 'Anonymous'
     img.src = this.data.src
     img.onload = function () {
     ctx.drawImage(img, 0, 0, canvas.width, canvas.height)
     }
     }
     })
    }
    

    如果遇到canvas跨域绘制图片报错,设置图片img.crossOrigin = 'Anonymous',并且服务器响应头设置Access-Control-Allow-Origin:*

    创建cropperjs

    // 引入
    import Cropper from 'cropperjs'
    
    // 显示裁剪框
    initCropper () {
     let cropper = new Cropper(this.$refs.canvas, {
     checkCrossOrigin: true,
     viewMode: 2,
     aspectRatio: 3 / 2
     })
    }
    
    

    更多方法和属性,参考官网: https://github.com/fengyuanchen/cropperjs

    具体实现,可以查看源码的cropper.vue 或 cropper.one.vue组件:

    cropper.vue组件:https://github.com/MY729/picture-crop-demo/blob/master/src/components/cropper.vue
    cropper.one.vue组件:https://github.com/MY729/picture-crop-demo/blob/master/src/components/cropper.one.vue

    使用canvas实现图片裁剪

    支持鼠标绘制裁剪框,并移动裁剪框

    思路:

    • 在canvas上绘制图片为背景
    • 监听鼠标点击、移动、松开事件

    canvas的isPointInPath()方法: 如果给定的点的坐标位于路径之内的话(包括路径的边),否则返回 false

    具体实现可查看源码cropper.canvas.vue组件: https://github.com/MY729/picture-crop-demo/blob/master/src/components/cropper.canvas.vue

    cropImg () {
     let canvas = document.getElementById(this.data.img_url)
     let ctx = canvas.getContext('2d')
     let img = new Image()
     img.onload = function () {
     ctx.drawImage(img, 0, 0, canvas.width, canvas.height)
     }
     img.src = this.data.src
     let drag = false // 是否拖动矩形
     let flag = false // 是否绘制矩形
     let rectWidth = 0 // 绘制矩形的宽
     let rectHeight = 0 // 绘制矩形的高
     let clickX = 0 // 矩形开始绘制X坐标
     let clickY = 0 // 矩形开始绘制Y坐标
     let dragX = 0 // 当要拖动矩形点击时X坐标
     let dragY = 0 // 当要拖动矩形点击时Y坐标
     let newRectX = 0 // 拖动变化后矩形开始绘制的X坐标
     let newRectY = 0 // 拖动变化后矩形开始绘制的Y坐标
     // 鼠标按下
     canvas.onmousedown = e => {
     // 每次点击前如果有绘制好的矩形框,通过路径绘制出来,用于下面的判断
     ctx.beginPath()
     ctx.setLineDash([6, 6])
     ctx.moveTo(newRectX, newRectY)
     ctx.lineTo(newRectX + rectWidth, newRectY)
     ctx.lineTo(newRectX + rectWidth, newRectY + rectHeight)
     ctx.lineTo(newRectX, newRectY + rectHeight)
     ctx.lineTo(newRectX, newRectY)
     ctx.strokeStyle = 'green'
     ctx.stroke()
     // 每次点击,通过判断鼠标点击的点在矩形框内还是外,来决定重新绘制还是移动矩形框
     if (ctx.isPointInPath(e.offsetX, e.offsetY)) {
     drag = true
     dragX = e.offsetX
     dragY = e.offsetY
     clickX = newRectX
     clickY = newRectY
     } else {
     ctx.clearRect(0, 0, canvas.width, canvas.height)
     ctx.drawImage(img, 0, 0, canvas.width, canvas.height)
     flag = true
     clickX = e.offsetX
     clickY = e.offsetY
     newRectX = e.offsetX
     newRectY = e.offsetY
     }
     }
     // 鼠标抬起
     canvas.onmouseup = () => {
     if (flag) {
     flag = false
     this.sureCrop(clickX, clickY, rectWidth, rectHeight)
     }
     if (drag) {
     drag = false
     this.sureCrop(newRectX, newRectY, rectWidth, rectHeight)
     }
     }
     // 鼠标移动
     canvas.onmousemove = (e) => {
     if (flag) {
     ctx.clearRect(0, 0, canvas.width, canvas.height)
     ctx.drawImage(img, 0, 0, canvas.width, canvas.height)
     rectWidth = e.offsetX - clickX
     rectHeight = e.offsetY - clickY
    
     ctx.beginPath()
     ctx.strokeStyle = '#FF0000'
     ctx.strokeRect(clickX, clickY, rectWidth, rectHeight)
     ctx.closePath()
     }
     if (drag) {
     ctx.clearRect(0, 0, canvas.width, canvas.height)
     ctx.drawImage(img, 0, 0, canvas.width, canvas.height)
     ctx.beginPath()
     newRectX = clickX + e.offsetX - dragX
     newRectY = clickY + e.offsetY - dragY
     ctx.strokeStyle = 'yellow'
     ctx.strokeRect(newRectX, newRectY, rectWidth, rectHeight)
     ctx.closePath()
     }
     }
    },
    // 拿到裁剪后的参数,可自行处理图片
    sureCrop (x, y, width, height) {
     let canvas = document.getElementById(this.data.img_url + 'after')
     // 设置canvas的宽为canvas的父元素宽度,宽高比3:2
     let parentEle = canvas.parentElement
     canvas.width = parentEle.offsetWidth
     canvas.height = 2 * parentEle.offsetWidth / 3
     let ctx = canvas.getContext('2d')
     let img = new Image()
     img.src = this.data.src
     img.onload = function () {
     ctx.beginPath()
     ctx.moveTo(x, y)
     ctx.lineTo(x + width, y)
     ctx.lineTo(x + width, y + height)
     ctx.lineTo(x, y + height)
     ctx.clip()
     ctx.drawImage(img, 0, 0, canvas.width, canvas.height)
     }
     ctx.stroke()
    }
    
    

    源码地址

    https://github.com/MY729/picture-crop-demo

    可以直接clone项目,本地运行查看代码和效果

    以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对北冥有鱼的支持。

    您可能感兴趣的文章:

    • vue-image-crop基于Vue的移动端图片裁剪组件示例
    • Vue-cropper 图片裁剪的基本原理及思路讲解
    • 基于cropper.js封装vue实现在线图片裁剪组件功能
    • vue-cli结合Element-ui基于cropper.js封装vue实现图片裁剪组件功能
    • cropper js基于vue的图片裁剪上传功能的实现代码
    • 基于Vue的移动端图片裁剪组件功能
    • vue实现移动端图片裁剪上传功能

    广而告之:
    热门推荐:
    详解react-router 4.0 下服务器如何配合BrowserRouter

    react-router作为react框架路由解决方案在react项目中举足轻重。 在react-router 4.0版本中,API与先前版本相比有了很大的修改,在2.0、3.0中常用的<Router>组件作为路由底层配置组件不再常用,取而代之的是四个各有不同的路由组件: <BrowserRouter>, <HashRou···

    h5网页水印SDK的实现代码示例

    在网站浏览中,常常需要网页水印,以便防止用户截图或录屏暴露敏感信息后,追踪用户来源。如我们常用的钉钉软件,聊天背景就会有你的名字。那么如何实现网页水印效果呢? 网页水印SDK,实现思路 1.能更具获取到的当前用户信息,如名字,昵称,ID等,生成水印 2.生成一个Canvas···

    详解PHP对象的串行化与反串行化

    什么时候使用串行化? 在网络中传输对象的时候 向数据库中保存文件的时候 今天我们要提到四个函数 全部串行化 1.serialize(对象名) 将指定的类对象串行化 $str=serialize($per) //将per对象串行化,结果返回给$str 2.unserialize(串行化后的返回值) 返回结果是对象 $per=unser···

    PHP面向对象之旅:深入理解static变量与方法

    static关键字声明一个属性或方法是和类相关的,而不是和类的某个特定的实例相关,因此,这类属性或方法也称为“类属性”或“类方法”。 如果访问控制权限允许,可不必创建该类对象而直接使用类名加两个冒号“::”调用。 static关键字可以用来修饰变量、方法。 不经过实例化,就···

    微信小程序使用modal组件弹出对话框功能示例

    本文实例讲述了微信小程序使用modal组件弹出对话框功能。分享给大家供大家参考,具体如下: 1、效果展示 2、关键代码 ①、index.wxml <view>提示:{{tip}}</view> <button type="default" bindtap="showModal">点击我弹出modal对话框</button> <vi···

    CSS3改变浏览器滚动条样式

    注:该方法只适用于 -webkit- 内核浏览器 浏览器滚动条太宽,太丑,影响日常开发怎么办,改TA 滚动条外观由2部分组成:1.滚动条整体滑轨 2.滚动条滑轨内滑块 在CSS中滚动条由3部分组成 name::-webkit-scrollbar //滚动条整体样式 name::-webkit-scrollbar-track //滚动条滑···

    php数组查找函数in

    php在数组中查找指定值是否存在的方法有很多,记得很久以前我一直都是傻傻的用foreach循环来查找的,下面我主要分享一下用php内置的三个数组函数来查找指定值是否存在于数组中,这三个数组分别是 in_array(),array_search(),array_key_exists()。 首先分别介绍一下各自的···

    Vue多系统切换实现方案

    前言 公司分好几个后台模块,统一使用vue+elementUi框架开发,每一个后台模块都是单独团队开发的。并且几个系统整体的风格、布局一样的,包括左侧边栏,上方的面包屑等 用户在使用的时候,可能要切换别的系统就要在浏览器里,新打开窗口,再输入网址,回车。 总结来说,低效,···

    织梦dedecms系统生成漂亮整齐的缩略图

    修改文件:inc_photograph.php  代码如下:  复制代码 if($toWH<=$srcWH){ $ftoW=$toW; $ftoH=$ftoW*($srcH/$srcW); } else{ $ftoH=$toH; $ftoW=$ftoH*($srcW/$srcH); } 更改为  代码如下:  复制代码 $ftoH=$toH; $ftoW=$toW; if···

    PHP数据库表操作的封装类及用法实例详解

    本文实例讲述了PHP数据库表操作的封装类及用法。分享给大家供大家参考,具体如下: 数据库表结构: CREATE TABLE `test_user` ( `id` int(11) NOT NULL AUTO_INCREMENT, `username` varchar(45) NOT NULL, `password` varchar(45) NOT NULL, `nickname` varchar(45) NOT NULL,···