javascript实现自由编辑图片代码详解


Posted in Javascript onJune 21, 2019

当下我们项目中需要一个可自由编辑图片的功能,当图片可能出现需要频繁编辑,同时能满足发现裁剪不满意想要微调的时候,会发现如果我们处理图片按照平常的习惯,如裁剪后上传服务器或者转base64,都是不符合需求的。那么该怎么处理比较好呢?如何以尽量少的网络请求、少占用存储来解决应用场景呢?那么,便想到了只用纯数据来跟我们的功能打交道。

先安利个裁图神器cropperjs,个人认为是个易上手,配置和api方法蛮齐全的一个组件库。

项目内引入,一定不要漏了引用样式

import Cropper from 'cropperjs';
import 'cropperjs/dist/cropper.css';

这里我们以react为例

this.state = {
width: 640, //图片展示宽
height: 360, //图片展示高 
imgWidth: 640, //图片实际宽
imgHeight: 360, //图片实际高
imgLeft: 0, //图片左偏移
imgTop: 0, //图片上偏移
editing: false //是否编辑中
}
//展示图片的基本dom结构,我们使用外div内img的形式,来跟数据结合控制裁剪图片的展示
const { width, height, imgWidth, imgHeight, imgLeft, imgTop, editing } = this.state;
const containerStyle = {
width: `${width}px`,
height: `${height}px`
}
const imgStyle = {
width: `${imgWidth}px`,
height: `${imgHeight}px`,
left: `${imgLeft}px`,
top: `${imgTop}px`
}
.img-container {
overflow: hidden;
position: relative;
}
.crop-img {
position: absolute;
left: 0;
top: 0;
}
<div 
className="img-container" 
style={containerStyle}
>
<img 
className="crop-img"
src={picture} 
style={imgStyle} 
alt="pic"
></img>
</div>

简单来说就是外层元素控制裁剪展示的宽高,同时根据项目需求的元素定位也挂在这,内部img挂载图片实际大小和偏移。

cropperjs初始化后的元素,是会与初始化对象img处在同一dom层级,也就是说如果我们直接对展示img进行初始化的话,编辑区域展示将会受父元素,如图,放大图片时候会不方查看超出部分

javascript实现自由编辑图片代码详解

所以在这里,为了图片编辑的自由度,建议分开展示dom与用以初始化cropper对象的dom,在这里编辑区域为全屏幕为例,根据项目实际功能区域进行调整

.edit-container {
position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 0;
}
<div 
className="img-container" 
style={containerStyle}
>
<img 
className="crop-img"
src={picture} 
style={imgStyle} 
alt="pic"
></img>
</div>
//cropper初始化
this.myRef = React.createRef();
this.myCropper = new Cropper(this.myRef.current, options);
//options配置
const options = {
dragMode: 'move', //使裁剪时图片可拖动
background: false, //因为我们现在是全屏可编辑,需要隐藏掉默认的背景
}
//当然还有许多常见的配置项,如编辑框尺寸比例等,大家可自行查看api
//裁剪保存
save() {
const cropBoxData = this.myCropper.getCropBoxData(); //获取裁剪框数据
const canvasData = this.myCropper.getCanvasData(); //获取图片数据
this.setState({
width: cropBoxData.width,
height: cropBoxData.height,
imgLeft: canvasData.left - cropBoxData.left,
imgTop: canvasData.top - cropBoxData.top,
imgWidth: canvasData.width,
imgHeight: canvasData.height
})
}

这样的话 我们就可以完全在自定义的全屏内编辑,保存效果如下,到这里我们就完成了第一部分功能,裁剪并保存数据和展示

javascript实现自由编辑图片代码详解

javascript实现自由编辑图片代码详解

重点介绍下我们用到的两个api方法getCropBoxData和getCanvasData,getCanvasData是用来获取图片的实际数据的(当前的宽高,和相对于父元素可视区域的位移偏移量),getCropBoxData则是获取相对于图片区域的裁剪区相关数据。

那么后续的需求接着来了,我们怎么做到二次编辑的时候,能还原效果呢,嗯,其实在前面我们记录裁图数据的时候,把相应的数据关系再计算一遍就好了,在初始化cropper的options中增加配置

const options = {
dragMode: 'move',
background: false,
//控件初始化后重置相应配置
ready: () => {
const { width, height, imgWidth, imgHeight, imgLeft, imgTop } = this.state;
//根据实际需要出现裁图功能进行定位,此处left和top仅为测试暂时默认值定义
const left = 50; 
const top = 50;
this.myCropper.setCanvasData({
width: imgWidth,
height: imgHeight,
left: left,
top: top
});
this.myCropper.setCropBoxData({
left: left - imgLeft,
top: top - imgTop,
width: width,
height: height
})
}
}
this.myCropper = new Cropper(this.myRef.current, options);

这时候我们再点击裁图,就完美还原了,左边和上边的间隙就是setCanvasData的top和left,根据实际项目进行调整,setCropBoxData的left和top是相对于cropper-canvas的定位,才有了以上的计算形式。

javascript实现自由编辑图片代码详解

此时,基本功能到此结束,如果说是应用在h5编辑中,设计到scale缩放的话,相关的数据计算都要算上scale的缩放值哦,不然就会出现展示图片和编辑图片大小不对等的状况。同时还有许多功能就不做展示了,设置裁剪框比例,编辑缩放等,欢迎尝试。

当然了,如果想要保存图片,也有相应的方法到处裁剪图片的数据

this.myCropper.getCroppedCanvas().toDataURL('image/jpeg')

最后,我们可以看到,在整个功能过程中,我们需要的只是裁剪的数据,读写快,也不需要进行额外的图片存储,减少文件服务器存储的开销与优化。

cropperjs github

感谢大家收看,欢迎讨论和指正。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
js跨域和ajax 跨域问题的实现思路
Sep 05 Javascript
JavaScript 语言的递归编程
May 18 Javascript
javascript实现 百度翻译 可折叠的分享按钮列表
Mar 12 Javascript
javascript日期格式化方法汇总
Oct 04 Javascript
深入浅析JavaScript字符串操作方法 slice、substr、substring及其IE兼容性
Dec 16 Javascript
Zero Clipboard实现浏览器复制到剪贴板的方法(多个复制按钮)
Mar 24 Javascript
jQuery ztree实现动态树形多选菜单
Aug 12 Javascript
jQuery获取this当前对象子元素对象的方法
Nov 29 Javascript
jQuery对table表格进行增删改查
Dec 22 Javascript
详解VueJS 数据驱动和依赖追踪分析
Jul 26 Javascript
JS动态添加元素及绑定事件造成程序重复执行解决
Dec 07 Javascript
JavaScript实现一键复制内容剪贴板
Jul 23 Javascript
JS中超越现实的匿名函数用法实例分析
Jun 21 #Javascript
微信小程序实现圆形进度条动画
Nov 18 #Javascript
JavaScript迭代器的含义及用法
Jun 21 #Javascript
js事件触发操作实例分析
Jun 21 #Javascript
微信小程序实现下拉刷新动画
Jun 21 #Javascript
vue elementUI使用tabs与导航栏联动
Jun 21 #Javascript
Ajax请求时无法重定向的问题解决代码详解
Jun 21 #Javascript
You might like
ThinkPHP实例化模型的四种方法概述
2014/08/22 PHP
php格式化时间戳显示友好的时间实现思路及代码
2014/10/23 PHP
php数组去除空值函数分享
2015/02/02 PHP
php定期拉取数据对比方法实例
2019/09/22 PHP
php设计模式之模板模式实例分析【星际争霸游戏案例】
2020/03/24 PHP
动态修改DOM 里面的 id 属性的弊端分析
2008/09/03 Javascript
javascript学习笔记(五)正则表达式
2011/04/08 Javascript
用js正确判断用户名cookie是否存在的方法
2014/01/28 Javascript
JS的事件绑定深入认识
2014/06/26 Javascript
javascript中setTimeout和setInterval的unref()和ref()用法示例
2014/11/26 Javascript
SeaJS 与 RequireJS 的差异对比
2014/12/08 Javascript
js控制网页背景音乐播放与停止的方法
2015/02/06 Javascript
教你使用javascript简单写一个页面模板引擎
2015/05/05 Javascript
Jquery和angularjs获取check框选中的值的方法汇总
2016/01/17 Javascript
AngularJS 表达式详细讲解及实例代码
2016/07/26 Javascript
概述如何实现一个简单的浏览器端js模块加载器
2016/12/07 Javascript
bootstrap常用组件之头部导航实现代码
2017/04/20 Javascript
jQuery鼠标悬停内容动画切换效果
2017/04/27 jQuery
JS实现颜色的10进制转化成rgba格式的方法
2017/09/04 Javascript
微信小程序实现多个按钮的颜色状态转换
2019/02/15 Javascript
jQuery属性选择器用法实例分析
2019/06/28 jQuery
解决在Vue中使用axios POST请求变成OPTIONS的问题
2020/08/14 Javascript
在Python中编写数据库模块的教程
2015/04/29 Python
使用Python神器对付12306变态验证码
2016/01/05 Python
pytorch实现从本地加载 .pth 格式模型
2020/02/14 Python
Python破解BiliBili滑块验证码的思路详解(完美避开人机识别)
2020/02/17 Python
基于CSS3实现的几个小loading效果
2018/09/27 HTML / CSS
下面关于"联合"的题目的输出是什么
2013/08/06 面试题
什么是规则表达式
2012/05/03 面试题
你在项目中用到了xml技术的哪些方面?如何实现的?
2014/01/26 面试题
应届护士推荐信
2013/11/16 职场文书
2014年扶贫工作总结
2014/11/18 职场文书
模范教师材料大全
2014/12/16 职场文书
浅谈Mysql多表连接查询的执行细节
2021/04/24 MySQL
使用python绘制横竖条形图
2022/04/21 Python
什么是css原子化,有什么用?
2022/04/24 HTML / CSS