当下我们项目中需要一个可自由编辑图片的功能,当图片可能出现需要频繁编辑,同时能满足发现裁剪不满意想要微调的时候,会发现如果我们处理图片按照平常的习惯,如裁剪后上传服务器或者转base64,都是不符合需求的。那么该怎么处理比较好呢?如何以尽量少的网络请求、少占用存储来解决应用场景呢?那么,便想到了只用纯数据来跟我们的功能打交道。
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} height="707" src="https://files.vevb.com/file_images/article/201906/2019621105324051.jpg?201952110543" style="border: 1px solid rgb(204, 204, 204); vertical-align: middle; padding: 1px; overflow: hidden; max-width: 696px; width: 650px; height: auto;" width="1271" /> 所以在这里,为了图片编辑的自由度,建议分开展示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} height="707" src="https://files.vevb.com/file_images/article/201906/2019621105324052.jpg?201952110548" style="border: 1px solid rgb(204, 204, 204); vertical-align: middle; padding: 1px; overflow: hidden; max-width: 696px; width: 650px; height: auto;" width="800" />
重点介绍下我们用到的两个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的定位,才有了以上的计算形式。
此时,基本功能到此结束,如果说是应用在h5编辑中,设计到scale缩放的话,相关的数据计算都要算上scale的缩放值哦,不然就会出现展示图片和编辑图片大小不对等的状况。同时还有许多功能就不做展示了,设置裁剪框比例,编辑缩放等,欢迎尝试。
当然了,如果想要保存图片,也有相应的方法到处裁剪图片的数据
this.myCropper.getCroppedCanvas().toDataURL('image/jpeg')
最后,我们可以看到,在整个功能过程中,我们需要的只是裁剪的数据,读写快,也不需要进行额外的图片存储,减少文件服务器存储的开销与优化。
cropperjs github
感谢大家收看,欢迎讨论和指正。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持VeVb武林网。
注:相关教程知识阅读请移步到JavaScript/Ajax教程频道。