之前做了一个h5项目,核心功能是上传图片,进行裁剪后与其他页面部分合成到一个图片作为海报进行保存。实际做出来的功能如下所示,这里我是用pc浏览器的移动端页面模拟进行录制的,实际上在手机上的效果会更好一点:

这个需求的要点主要在以下几点:

  1. 图片上传后的裁剪,这个需要找到合适的第三方工具,并且支持移动端
  2. 裁剪完的图片,会作为页面一个img标签进行显示,但还要与其他部分合成为新的图片,这个要借助第三方合成工具
  3. 图片支持添加文字描述,合成到最后的海报中,同时合成包含若干个区域,需要合理的进行布局以裁剪到正确的部分

框架使用vue,经过前期调研,图片的裁剪可以通过vue-cropper来实现,并且可以完美支持移动端;图片合成,这个因为之前pc端的项目也有用到类似的,通过html2canvas可以截取dom中的某一区域以生成图片,经过调研,也是可以支持移动端的;剩下的布局与区域问题,分析都可以通过代码解决,ok开搞

裁剪功能vue-cropper

关于vue-cropper不必详细介绍了,百度可以查到其用法,设置属性绑定到一个option对象中:

option: {img: '',  //  裁剪图片的地址。可以有三种形式:url 地址 || base64 || blobsize: 1, // 裁剪生成图片的质量,    默认:1, 参数范围:0.1 - 1。outputType: 'png', // 裁剪生成图片的格式   默认: jpg (jpg 需要传入jpeg)  可选参数:jpeg || png || webpautoCrop: true, //  是否默认生成截图框.默认为: falsecanScale: true, //  图片是否允许滚轮缩放   默认;true  可选:true || falsehigh: true, //  是否按照设备的dpr 输出等比例图片fixed: true, // 是否开启截图框宽高固定比例。默认:truefixedNumber: [224, 242], // 截图框的宽高比例full: true, //  是否输出原图比例的截图(决定了裁剪图片的画面质量)。
}

这里几乎都是默认值,只有fixedNumber长宽比设置的为裁剪后填入容器的实际长宽比,这样裁剪区域的大小就会根据这个等比例缩放,从而避免图片出现被拉伸变形的情况

截取完毕后,当点击ok按钮时,需要将vue-cropper截取后的图片填充到img中,大部分百度查到的vue-cropper是直接上传到服务器的,实际上也可以将获取到的blob数据填充到容器中,如下:

ok () {this.showIndex = 0this.isShowCutReult = truethis.isGenerateAllowed = truethis.$nextTick(() => {this.$refs.cropper.getCropBlob(async (data) => {var a = new FileReader();a.readAsDataURL(data);//读取文件保存在result中a.onload = function (e) {var getRes = e.target.result;//读取的结果在result中var img = document.getElementsByClassName('cut-img-detail')[0]img.src = getRes}});})
}
合成海报功能html2canvas

之前在pc项目上用过html2canvas,将dom某一个部分合成为一张图片,进行下载。这里我们合成图片后,则需要导出到最终海报img中,先来看看我们页面的整体结构思路:

<template><div class="create"><div class="main" v-show="showIndex===0"> <!-- 海报创建页面 --></div><div class="popper" v-show="showIndex===1"><!-- 图片裁剪页面 --></div><div class="finish" v-show="showIndex===2"><!-- 海报呈现页面 --></div></div>
</template>

三个页面同一时间只会呈现一个,在海报创建页面点击Upload进行图片上传,上传成功后自动跳到图片裁剪页面,裁剪完成后回到海报创建页面,可以增加描述,最后点击生成海报,进入第三个海报呈现页面。
可以看出,当点击生成海报时,generate方法中使用html2canvas将海报创建页面中的对应我们想要的部分生成图片,并且输出到海报呈现页面中的相应img,同时展示海报呈现页面

generate () {if (this.isGenerateAllowed) {// 比较方的屏幕会出现最下面两个按钮需要向下滚动才能按的情况,这时候要先把滚动条重新置为最上部,不然截屏会错位if (document.body.scrollTop) {document.body.scrollTop = 0}if (document.documentElement.scrollTop) {document.documentElement.scrollTop = 0}this.$nextTick(() => {html2canvas(this.$refs.innerWrapper, {backgroundColor: null}).then((canvas) => {let imgData = canvas.toDataURL("image/png")this.showIndex = 2this.$nextTick(() => {var resultImg = document.getElementsByClassName('export-image')[0]resultImg.src = imgData})})})}
}

这里需要注意两点:

  1. 方法上部注释中描述所述,当手机比较方,尤其在iphone手机,也就是我们的纵向内容无法一屏呈现时,可能需要向下滚动页面,才能点击生成图片按钮,这时候实测发现截图内容会错位,猜测是在绝对定位元素中进行了截取,解决办法是html2canvas截取前将页面滚动到顶部
  2. 被截取的部分中包含图片时,尽量将图片放入img中而不是div中;截完填充的目标容器,也需要为img,这样都是为了避免影响图片的清晰度,尤其我们这个是生成的海报,不能因为截取而导致清晰度下降太多
合理布局/拆分容器以实现精准截取

简单从界面上来分解一下我们的布局部分:

1:海报背景;2:截取后的图片;3:上传图片按钮;4:占位符以及其外围虚线框;5:添加的描述以及背景黑色透明块
显见以下几点:

  1. 识别出我们需要截取的部分为1、2、5
  2. 3始终存在于页面,但是并不会被截取,所以他应该不属于截取的div,即1、2、5有一个外部容器,其与3是并列的,3可以用绝对定位固定在页面这个位置
  3. 4虽然可以在我们输入文字后将其切换为隐藏从而不被截取,但是我们的功能,是可以不添加描述直接生成海报的,这时候它还显示,所以方便起见它也是与3和整体容器并列的,通过绝对定位在这里

按照这个思路去布局,以下是我实际项目的html,我已添加好对应的1-5的注释

<div class="wrapper" ref="wrapper"><!-- innerWrapper为html2canvas截取的div --><div class="inner-wrapper" ref="innerWrapper"><!-- 1 业务为六种海报背景中的一种 --><img src="../../static/poster_01.png" class="post" v-show="postIndex===1" /><img src="../../static/poster_02.png" class="post" v-show="postIndex===2" /><img src="../../static/poster_03.png" class="post" v-show="postIndex===3" /><img src="../../static/poster_04.png" class="post" v-show="postIndex===4" /><img src="../../static/poster_05.png" class="post" v-show="postIndex===5" /><img src="../../static/poster_06.png" class="post" v-show="postIndex===6" /><!-- 2 裁剪后的图片 --><div v-show="isShowCutReult" class="cut-img"><img class="cut-img-detail" style="width:100%;height:100%;"></div><!-- 5 背景黑色透明块与添加的描述 --><div class="cut-text-back"></div><textarea class="des" rows="2" cols="30" v-model="textContent" placeholder=""></textarea></div>
</div>
<!-- 3 上传图片按钮 -->
<div class="upload" @click="triggerOpenFile"><div class="upload-top">UPLOAD</div><div class="upload-bottom">上传图片</div>
</div>
<input class="file-upload" type="file" :value="imgFile" ref="selectImg" style="display: none" accept="image/png, image/jpeg, image/jpg" @change="uploadImg($event)">
<!-- 4 占位符与外围虚线白框 -->
<div class="for-border" v-show="textContent===''"><div class="for-border-above">Add Description ( max 100 characters )</div><div class="for-border-below">添加文字描述(最多五十个字符)</div>
</div>
文件上传到vue-cropper

last but not least,上传文件到vue-cropper,这个无需多言,上传采用标准h5文件读取方式,上传后通过FileReader读取blob给到option的img属性,这个几乎任何vue-cropper的文章都会提到,尽管不尽相同

uploadImg (e) {this.option.img = '';//  上传图片const file = e.target.files[0];this.fullFile = file;if (!/\.(jpg|jpeg|png|JPG|PNG)$/.test(e.target.value)) {this.$message.error('图片类型必须是.jpeg、jpg、png中的一种');return false;} else if (this.fullFile.size / 1024 / 1024 > 10) {this.$message.error('图片大小不得超过10MB');return false;}const reader = new FileReader();reader.onload = e => {let data;if (typeof e.target.result === 'object') {// 把Array Buffer转化为blob 如果是base64不需要 data = window.URL.createObjectURL(new Blob([e.target.result]));} else {data = e.target.result;}this.option.img = data;};// 转化为blob reader.readAsArrayBuffer(file);//  打开图片处理弹窗this.showIndex = 1;
},

H5移动端记一次图片裁剪合成功能相关推荐

  1. 模拟系统照相机图片裁剪的功能

    模拟系统照相机图片裁剪的功能 效果如下: 源码: // // RootViewController.m // ScrollView // // Copyright (c) 2014年 Y.X. All ...

  2. 如何在H5移动端页面中调起手机拨打电话功能?

    文章目录 一.如何在H5移动端页面中调起手机拨打电话功能? 二.Vant搭建页面js函数调用弹窗,如何实现对应点击功能? 一.如何在H5移动端页面中调起手机拨打电话功能? <a href=&qu ...

  3. 网页端基于js的图片裁剪

    效果预览 点击下载前往码云下载相应js 使用说明 CDN 使用 <script src="croptool.min.js"></script> <sc ...

  4. H5 移动端 保存图片到本地 + 图片预览

    图片下载: 动态创建A链接,添加download属性和href属性,并触发点击事件 let alink = document.createElement('a'); alink.href = Url; ...

  5. 移动端照片上传、头像裁剪完整功能,兼容iphone,android (一)

    第一步:照片上传 <input class="js_upFile" type="file" name="cover" accept=& ...

  6. H5移动端css实现向右横向滚动功能

    移动端屏幕很小,为了呈现更多的内容,并占用更小的空间,但是又不能影响正常阅读,就出现了现在潮流的设计手法:十字交互法则,卡片横向无限滚动就是其诞生的排版布局之一,不过十字交互最初是在大屏端(电视UI) ...

  7. 图片裁剪功能学习小结

    图片裁剪功能学习小结 近期有需要使用图片裁剪的功能,在使用插件和自己写裁剪组件之间犹豫了很久,后来根据需求经过反复的考虑,还是自己封装吧,毕竟自己动手,丰衣足食,对吧?嗯,??????是的!最后生成裁 ...

  8. 微信小程序图片裁剪功能的实现

    文章目录 图片上传与处理 图片尺寸适配 图片显示与裁剪框 裁剪框的拖动与缩放 增加canvas并裁剪图片 保存图片到相册 总结 在之前的博文中,已经介绍了如何使用在前端开发中,实现较方便自由的图片裁剪 ...

  9. android 壁纸 裁剪,Android图片裁剪之自由裁剪

    客户的需求都是非常怪的.我有时候在给客户做项目的时候就想骂客户是sb.可是请你相信我,等你有需求,自己变成客户的时候,给你做项目的哥哥肯定也会骂你是sb. 是这种,客户须要做一个图片上传的功能,这个图 ...

最新文章

  1. ATS 6.2.1中缓存文件过期并不回源校验的“坑”
  2. poj3581Sequence(后缀数组)
  3. 如何提高代码质量:代码复查
  4. 基于Extjs的OPOA
  5. 成为奥运冠军需要天赋和努力
  6. Java程序员---技能树
  7. 小学生计算机课堂实践的重要性,小学《信息技术》有效课堂教学的实践与研究课题方案...
  8. Java 图片处理解决方案:ImageMagick 快速入门教程
  9. 【毕业设计】基于树莓派的指纹识别与RFID考勤系统 - 嵌入式 单片机 物联网
  10. light动名词_英语语法大全之动名词
  11. python并行编程 - 分布式篇
  12. java maven项目导入本地jar包
  13. selenium自动化测试-鼠标键盘操作
  14. ArduinoMega2560 引脚表
  15. android国外网站
  16. 关于灰色软件(Grayware)及其危害你了解多少?
  17. 1.1 显函数的图形
  18. 简单实用的Mac视频转换软件:UniConverter mac中文版
  19. java find()_java 之 find 命令
  20. Cows and Cars

热门文章

  1. sql注入关于waf的绕过
  2. 根据CAD文件的坐标信息给矢量图设置正确的投影坐标
  3. 2021-12-09 股票模拟交易心得6
  4. threejs加载三维模型
  5. 流畅度游戏60帧,视频24帧的原因
  6. 电脑蓝屏怎么办?一招教你修好
  7. javascript输出数据在控制台中console的常用方法(上)
  8. Openstack day6 理解 virbr0
  9. 王者荣耀服务器维护S19,王者荣耀:S19官宣31日更新,国服玩家集体声讨天美:1个月白打了...
  10. Python 窗体美化,背景图片,字体样式