马上就要“十一”国庆节了,又恰逢公司已经三周岁了,所以市场部和产品共同策划了一个“正青春,共成长”的主题代言活动,准备在国庆节以及中秋节期间让公司员工和用户为公司代言,于是就有了技术部前端开发人员即本人为公司来开发这个主题代言活动页面。
开发要求:
1、用户可以从手机相册上传图片或拍照上传图片;
2、用户可以输入为公司代言的地点,如:我在:上海;
3、将用户输入的代言地点及活动二维码生成一张图片供用户保存到手机,以方便发送朋友圈或好友。
功能实现:
1、使用H5的input[type="file"]标签来上传图片,并使用其原生的js代码将其转换成base64字符串的图片;
2、使用canvas将用户上传的图片和输入的代言地点及活动二维码生成一张图片;
3、记录用户生成的图片信息。
看似简单的功能实现,实则麻烦多多。首先,自己本身对canvas不熟悉,平时基本不用,做的时候算是现学现用;其次,在使用canvas画图时,在IOS上竖拍的图片会被自动旋转90度,导致出来的图片不是用户拍时的效果,具体原因请参考iOS手机竖着拍的照片经过前端处理之后被旋转了90°的原因以及解决方案,这里才是本次开发的难点所在,这个问题折腾了我两三天的时间啊,不知道IOS为何要这么做,我也是查了好多资料,最终才得以解决。

代码实现:
1、上传代码使用到了H5的input[type="file"]:

<input type="file" class="uploadfile" accept="image/*">

2、生成base64字符串的图片:

/图片上传
var file = {    upload: function (e) {        var file = e.target.files[0];
        var type = file.type.split('/')[0];if (type != 'image') {alert('请上传图片');return;}//var size = Math.floor(file.size / 1024 / 1024);//if (size > 3) {//    alert('图片大小不得超过3M');//    return;//};var reader = new FileReader();reader.readAsDataURL(file);var orientation = null;//获取照片方向角属性,用户旋转控制  EXIF.getData(file, function () { EXIF.getAllTags(this);  orientation = EXIF.getTag(this, 'Orientation');  });reader.onloadstart = function () {$(".ajaxLoading").show();};reader.onloadend = function (e) {var dataURL = reader.result;var imaged = new Image();imaged.src = dataURL;imaged.onload = function () {               var canvas = document.createElement('canvas');var ctx = canvas.getContext('2d');//普通环境下设置canvas的宽高var w = 0,h = 0;if (this.width < 750) {w = this.width;h = this.height;canvas.width = w;canvas.height = h;} else {w = 750;canvas.width = w;var scale = this.width / this.height;w = w > this.width ? this.width : wh = w / scale;canvas.height = h;}                if (navigator.userAgent.match(/iphone/i)) {if (orientation != "") {switch (orientation) {case 3:ctx.rotate(180 * Math.PI / 180);ctx.drawImage(this, -w, -h, w, h);break;case 6://这里由于将图片纠正了回来,所以也要重新设置canvas的高已达到高度自适应canvas.width = 750;var scale = this.height / this.width;canvas.height = canvas.width / scale;h = 750 > this.height ? this.height : 750;w = h / scale;ctx.rotate(90 * Math.PI / 180);                                ctx.drawImage(this, 0, -h, w, h);break;case 8:ctx.rotate(270 * Math.PI / 180);ctx.drawImage(this, -h, 0, h, w);break;case 2:ctx.translate(w, 0);ctx.scale(-1, 1);ctx.drawImage(this, 0, 0, w, h);break;case 4:ctx.translate(w, 0);ctx.scale(-1, 1);ctx.rotate(180 * Math.PI / 180);ctx.drawImage(this, -w, -h, w, h);break;case 5:ctx.translate(w, 0);ctx.scale(-1, 1);ctx.rotate(90 * Math.PI / 180);ctx.drawImage(this, 0, -w, h, w);break;case 7:ctx.translate(w, 0);ctx.scale(-1, 1);ctx.rotate(270 * Math.PI / 180);ctx.drawImage(this, -h, 0, h, w);break;default:ctx.drawImage(this, 0, 0, w, h);}}} else {ctx.drawImage(this, 0, 0, w, h);}           $.post(ulr, { base64_string: canvas.toDataURL('image/jpeg') }, function (res) {if (res.success) {$("#daiyan_bg").attr("src", res.message);$(".ajaxLoading").hide();var qrCodeH = 0;if (navigator.userAgent.match(/iphone/i)) {if (orientation != "") {switch (orientation) {case 6:qrCodeH = w / 2 - $(".qrcode").height() - 105;break;default:qrCodeH = h / 2 - $(".qrcode").height() - 105;}}} else {var qrCodeH = h / 2 - $(".qrcode").height() - 105;}$(".qrcode").css("top", qrCodeH);$(".page1").hide().siblings(".page2").show();}}, "json");};          };},event: function () {$(".uploadfile").change(function (e) {file.upload(e);});},init: function () {this.event();}
};
file.init();

以上js代码中就解决了IOS将图片旋转90度的问题,使用到了exif.js,解决代码如下:

首先获取照片方向角属性orientation :

var orientation = null;
//获取照片方向角属性,用户旋转控制
EXIF.getData(file, function () { EXIF.getAllTags(this);  orientation = EXIF.getTag(this, 'Orientation') ;
});

其次根据orientation来旋转图片即可得到正确的图片:

if (navigator.userAgent.match(/iphone/i)) {if (orientation != "") {switch (orientation) {case 3:ctx.rotate(180 * Math.PI / 180);ctx.drawImage(this, -w, -h, w, h);break;case 6:canvas.width = 750;var scale = this.height / this.width;canvas.height = canvas.width / scale;h = 750 > this.height ? this.height : 750;w = h / scale;ctx.rotate(90 * Math.PI / 180);                                ctx.drawImage(this, 0, -h, w, h);break;case 8:ctx.rotate(270 * Math.PI / 180);ctx.drawImage(this, -h, 0, h, w);break;case 2:ctx.translate(w, 0);ctx.scale(-1, 1);ctx.drawImage(this, 0, 0, w, h);break;case 4:ctx.translate(w, 0);ctx.scale(-1, 1);ctx.rotate(180 * Math.PI / 180);ctx.drawImage(this, -w, -h, w, h);break;case 5:ctx.translate(w, 0);ctx.scale(-1, 1);ctx.rotate(90 * Math.PI / 180);ctx.drawImage(this, 0, -w, h, w);break;case 7:ctx.translate(w, 0);ctx.scale(-1, 1);ctx.rotate(270 * Math.PI / 180);ctx.drawImage(this, -h, 0, h, w);break;default:ctx.drawImage(this, 0, 0, w, h);}}} else {ctx.drawImage(this, 0, 0, w, h);}

最后,由于已经使用exif.js来对图片进行了纠正的处理,已经不再是iphone手机拍完照上传时的图片信息了,所以在第二次利用canvas将其生成海报时,就不会再被旋转了,至于第一次用canvas将拍的照片画成750px的图片是不想用户上传到图片服务器的图片过大从而导致加载过慢的问题,再者,如果不考虑上传到图片服务器的图片过大,那么将会生成base64格式的图片字符串,其宽高也是图片本来的宽高,但这里也还有一个隐藏的问题就是在有些iphone手机(我当时测的是iphone 6 plus)上不支持直接将base64格式的图片通过canvas画出来,所以为了兼容性,也只能通过后台将base64字符串格式的图片转换为普通的图片格式再来为最后的生成海报服务。
3、生成海报的代码如下:

var pointMsg = $(".pointtxt").val(),daiyanMsg = $(".daiyan_msg").html();var imgbox = document.getElementById("daiyan_bg"),canvas = document.getElementById("myCanvas");var ctx = canvas.getContext("2d");canvas.width = 750;            var imgUrl = new Image,qrCodeUrl = new Image,point = new Image;imgUrl.crossOrigin = "anonymous";imgUrl.src = imgbox.src;qrCodeUrl.src = "/Resource/4.0/images/201709daiyan/qrcode.jpg";point.src = "/Resource/4.0/images/201709daiyan/point.png";var daiyan_text = "我要代颜";            var btm = document.getElementById("bottom");                imgUrl.onload = function () {canvas.height = this.height + 50;ctx.fillStyle = "#fff";ctx.fillRect(0, 0, 750, 1334);var erWeiMaY = this.height - qrCodeUrl.height - 70;var wyDyY = this.height - 57;if (ctx.drawImage(imgUrl, 0, 0, 750, this.height), ctx.beginPath(), ctx.beginPath(), ctx.font = "normal 44px PingFangSC-Medium", ctx.textAlign = "start", ctx.textBaseline = "hanging", ctx.shadowOffsetX = 0, ctx.shadowOffsetY = 5, ctx.shadowColor = "rgba(0, 0, 0, 0.3)", ctx.shadowBlur = 5, "" != pointMsg && void 0 != pointMsg && null != pointMsg) {var pTxt = "我在:" + pointMsg;ctx.fillText(pTxt, 95, offy * 2 + 55);ctx.drawImage(point, 0, 0, 42, 55, 40, offy * 2 + 55, 42, 55);}ctx.beginPath();ctx.drawImage(qrCodeUrl, 0, 0, 140, 140, 570, erWeiMaY, 140, 140);ctx.drawImage(btm, 0, 0, 750, 50, 0, this.height, 750, 50);if (ctx.beginPath(), ctx.font = "normal 22px PingFangSC-Medium") {ctx.fillText(daiyan_text, 595, wyDyY);}
![](http://images2017.cnblogs.com/blog/688074/201709/688074-20170930143321965-1499864646.jpg)if (ctx.beginPath(), ctx.font = "normal 30px PingFangSC-Medium", ctx.shadowOffsetX = 0, ctx.shadowOffsetY = 5, ctx.shadowColor = "rgba(0, 0, 0, 0.3)", ctx.shadowBlur = 5) {ctx.fillText(daiyanMsg, 95, offy * 2 + 130);}document.getElementById("daiyan_bg1").src = canvas.toDataURL('image/jpeg');$(".page2").hide().siblings(".page3").show();$.post(url, { base64_string: canvas.toDataURL('image/jpeg') }, function (res) { }, "json");    //记录用户生成的海报信息var tipTop = this.height / 4 - 47;$(".save_tip").show().css("top", tipTop);setTimeout(function () {$(".save_tip").hide();}, 3000);               };

在这一步生成的海报其实也是base64字符串格式的图片,此时就可以用微信浏览器的长按保存功能将图片保存至手机上。至此,完成全部的开发。

案例代码下载:
H5上传图片并使用canvas制作海报

本案例中由于是纯静态页面,所以去掉了上传图片至图片服务器的代码,但在本博文贴出来的代码中加入了上传图片至图片服务器的代码,最后在案例代码中也加入了可以拖动用户输入文字那块的效果,那块的效果在做的时候其实也是折腾了两三个小时。原因如下:
产品要求用户可以输入文字,所以就加了一个input文本表单,但是又要求输入文字那里可以拖动,因此出现了新的问题:在拖动的touchstart事件里加入了ev.preventDefault()来禁止浏览器的默认行为,那么在触摸input文本表单时,input就无法获取焦点。
解决思路及办法:
刚开始想的是能不能在touchend的时候释放前边禁止的浏览器默认行为,结果就是然并卵,因为即使你在触摸结束时释放浏览器的默认行为,但触摸时又给禁止了,真该打自己。接着又想着能不能在页面加载完成后就禁止,结果还是然并卵,然后想到的是在触摸时就让input获取焦点focus,但是如果input中已经输入了文字,那么触摸时焦点就位于文字的最后而无法将焦点具体定位在文字中的某个地方,而且此时如果关闭了弹出来的软键盘,想要再次触摸获取焦点时,软键盘就弹不出来了,因为关闭软键盘时,input中的焦点依然存在,而不是你触摸时它获取的焦点,如果我们能获取到软键盘的抬起行为就好了,但也只是想想而已,还是然并卵,于是就各种上网查资料也还是没有解决。最后想到的是获取手指触摸的元素,如果触摸的是input表单,那么就不禁止浏览器的默认行为,否则就禁止,这样带来的结果是虽然在触摸input时也可以拖动,但浏览器的默认行为没有被禁止,在微信中,如果向下拖动,浏览器的上边就会出现那个显示浏览器内核信息的黑底,不过在触摸input表单边上的其他区域时是可以禁止浏览器的默认行为并拖动的,虽不完美,但实在是没有找到其他的解决办法了,如果有大神知道完美解决的办法,请及时告知,先在此谢过!!!

作者:小坏

H5上传图片并使用canvas制作海报相关推荐

  1. 在uniapp中使用canvas制作海报(二)

    项目场景: 提项目场景:在uniapp中制作分享海报,使用canvas制作并保存到本地,做了好久终于做完了! 解决方案: 第一步:制作页面: <view class="popup&qu ...

  2. canvas制作的海报在app上变形

    canvas制作的海报在app上变形 canvas海报在小程序上没有问题,但是app上变形. 直接将这些参数注掉,就可以了

  3. uniapp项目中使用canvas生成海报并保存、微信分享、发送至朋友圈

    uniapp项目中使用canvas生成海报并保存.微信分享.发送至朋友圈 1.html <!-- 分享模态框 --><canvas canvas-id="poster&qu ...

  4. canvas合成海报所遇问题及解决方案总结

    最近做了一个用canvas合成海报图片的移动端项目,由于一点canvas基础都没有,所以去网上搜了一位前辈的demo,但是开发过程中遇到了很多问题,现将所遇问题及解决方法总结如下: 1.移动端canv ...

  5. h5文字垂直居中_基于两款开源 h5 媒体编辑器定制一套海报系统

    收到一份需求,是要制作一套在线海报系统,系统的参考样例如下图所示 分为资源展示站 海报的设计工具 这种平台现在市场上成功的有好多家,功能都较为完备并且模板十分丰富.这种需求往大了做可以称之为 DaaS ...

  6. uniapp中使用canvas生成海报

    如下图,是在H5中测试,canvas生成后需要保存图片,使用uni.canvasToTempFilePath(官方文档API支持H5的)拿到绘制海报的base64,保存图片,如果提示画布被污染,看看是 ...

  7. html5的canvas制作口红机闯关游戏(一)

    目的 最近实践课让随便做小项目,准备学习下h5的canvas画布功能,参考canvas实现的见缝插针游戏,来制作一个口红机闯关小游戏,学习实践过程问题记录和canvas功能学习整理. 什么是canva ...

  8. Java5分钟制作海报

    一.需求背景 我们经常在多终端应用开发中会遇到这样的需求:用户在浏览商品时觉得不错,希望分享给朋友.此时终端(安卓.苹果.H5等)生成一张精美的商品海报,通过微信或者其他途径分享给他人.也可能会遇到需 ...

  9. 移动端手机h5上传图片旋转90度

    移动端手机h5上传图片会旋转90度的问题 h5页面调用相机正常情况下都是正常的,但是有些手机横着照相的时候就会正常的,iphone正确的拍照方式是横屏的,而用户往往是竖屏拍照上传的,就相当于照相机反转 ...

最新文章

  1. html中的盒子设置时间设置,CSS中的间距设置与盒子模型
  2. mysql装完后navicat无法连接_重装mysql后导致Navicat连接失败
  3. linux之拷贝文件/备份文件;按照原来的权限和日期拷贝.
  4. PyCharm 设置背景图片
  5. maven(11)-聚合多模块
  6. 2012.02.13(rtsp)
  7. Spring IOC基础概念总结:何为控制?何为反转?控制了什么?反转了哪里?
  8. Java菜鸟的初次实习经历
  9. iphone通讯录导入excel
  10. c语言源代码下载TGAM,2018年江西理工大学C语言程序设计竞赛(初级组)一
  11. win10 管理员权限运行
  12. adprw指令教程_三菱adprw指令图文详解
  13. 弱网测试工具以及模拟真实的网络环境
  14. Symantec云备份
  15. keil下C与汇编语言混合编程
  16. Apache使用mod_deflate模块启用gzip功能
  17. 2021秋季学期总结
  18. 微信小程序反编译wxss文件缺失_微信小程序反编译~2020年
  19. html表格中加按钮,表单中的按钮有三种
  20. R语言导出图片为png、jpg、tiff、pdf、ppt格式

热门文章

  1. 关于UGUI的Image,Text (转雨凇momo)
  2. eclipse调试错误No source available for _dl_debug_state() 解决方案
  3. SecureCRT sftp上传文件报错:put: failed to upload xxx 拒绝访问
  4. 【室内温度+树莓派性能监控】树莓派+DS18B20温度传感器+0.96寸OLED显示屏使用及安装经验分享
  5. WebApi路由机制详解
  6. 东半球空间环境地基综合监测子午链——子午工程
  7. 计算机应用的高级职称,职称计算机应用能力要求相关政策规定
  8. 搜狐邮箱打开第三方邮件客户端登录功能及设置独立密码方法
  9. 国内外开源商城系统盘点
  10. Github页面图片无法显示Github页面访问不了