关于canvas.toDataURL 在iOS运行失败的问题

最近做了一个海报生成的组件,需要drawimage到画布上,image来源包括本地和异地的图片src;
首先讲一点,异地图片如果不设置允许跨域访问,canvas.toDataURL是无法画image的,报画布污染的错;首先放一张我要生成的图;


上面加载了两张本地图片,两张异地图片,写了一些文字;在windows谷歌浏览器跑是好的,是吧,图片画出来,感觉无压力;用安卓也是好的,很开心;可是到IOS手机上,我去,怎么图片显示不出来啊,然后
try catch 错误,没啥有用的信息;

 try {// 将canvas对象转化为image/pngvar dataUrl = canvas.toDataURL('image/png')} catch (err) {console.log(err)}

我擦,这怎么办???
然后去cnbing搜,好多相同问题,好多原因,有个老外说动态更改canvas宽高无法再ios画出图片;还有的人说:
图片文件 size 太大,是否图片超过了 3M ? -----------我看了下生成的图片才几百kb PASS

图片的 dimension 太大,是否图片尺寸超过了 1000 x 1000 像素?我的尺寸确实超过了,宽高都超了,然而测试了下小的宽高,照旧ios画不出来啊~~~PASS

你指定的 mime_type 不支持,你用的是哪个 mime type?—canvas的 toDataURL API我看过了,可以支持三个类型,各试了一遍,无果 PASS
先上我的代码:

<template><div id="Poster"><div class="mask" @click="hidePoster()"></div><canvas ref="canvas" width="588" height="1044" style="display:none;"></canvas><div ref="box" id="Poster-box" @click.stop><span class="close"  @click="hidePoster()"></span></div><p class="tip">长安按海报发送给朋友</p></div>
</template>
<script>
export default {data () { // 参数const u = navigator.userAgent // ios终端const isIOS = !!u.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/) // ios终端return { // 返回参数localUrl: isIOS ? location.href.split('#')[0] : location.href, // 当前路径canvas: Object // canvas对象}},mounted () {this.initCanvas()},methods: {/*** 隐藏海报*/hidePoster () {this.$emit('hide')},/*** 加载图片* @param {Object} img 图片地址* @return {Promise} img dom*/loadImage (img) {return new Promise((resolve, reject) => {// image dom 对象const $image = document.createElement('img')if (img.isCross_domain) {console.log(img.url)$image.setAttribute('crossOrigin', 'Anonymous')}$image.onload = () => {resolve($image)}$image.src = img.url$image.onerror = reject})},/*** init初始化canvas函数*/async initCanvas () {// 获取vue实例var vm = thisvm.$indicator.open({text: '加载中...',spinnerType: 'fading-circle'})this.canvas = this.$refs.canvas.getContext('2d')this.canvas.height = 400this.canvas.width = 300this.canvas.fillStyle = '#ffffff'this.canvas.fillRect(0, 0, 588, 1044)// image urlsconst imgArr = [{url: require('../assets/poster-banner.png'),isCross_domain: false},{url: require('../assets/shadow.png'),isCross_domain: false},{url: 'https://s3-011-shinho-syj-uat-bjs.s3.cn-north-1.amazonaws.com.cn/mall/2019_06/border04.png',isCross_domain: true},{url: 'https://s3-011-shinho-syj-uat-bjs.s3.cn-north-1.amazonaws.com.cn/mall/2019_06/132.jpg',isCross_domain: true}]// image domsawait Promise.all(imgArr.map(img => this.loadImage(img))).then((imgs) => {console.log('done')this.canvas.drawImage(imgs[0], 0, 0, 588, 216 * 2)this.canvas.drawImage(imgs[1], 97 * 2, 166 * 2, 100 * 2, 100 * 2)this.canvas.save()this.canvas.beginPath()this.canvas.arc(147 * 2, 214 * 2, 34 * 2, 0, 2 * Math.PI, false)this.canvas.clip()this.canvas.drawImage(imgs[2], 113 * 2, 180 * 2, 68 * 2, 68 * 2)this.canvas.restore()this.canvas.drawImage(imgs[3], 189 * 2, 409 * 2, 88 * 2, 88 * 2)// 绘制文字this.drawText('我就是个我就账号账号', 147 * 2, 278 * 2, 290 * 2, '#333333', '32px PingFangSC-Regular ')this.drawText('荣誉称号是我', 147 * 2, 300 * 2, 290 * 2, '#999999', '26px PingFangSC-Regular ')this.drawText('距离冲榜还差10人', 147 * 2, 340 * 2, 290 * 2, '#FA6F5B', 'bold 36px arial')this.drawText('快来助我冲榜赢红烧酱油吧', 147 * 2, 370 * 2, 290 * 2, '#FA6F5B', 'bold 36px arial ')this.drawText('扫描二维码', 180 * 2, 443 * 2, 172 * 2, '#333333', '28px PingFangSC-Regular ', 'right')this.drawText('直达冲榜活动', 180 * 2, 463 * 2, 172 * 2, '#333333', '28px PingFangSC-Regular ', 'right')this.drawText('邀请好友跟你一起冲大奖', 180 * 2, 483 * 2, 172 * 2, '#333333', '28px PingFangSC-Regular ', 'right')this.showPic()vm.$indicator.close()})},/*** 绘制文字* @param {String} title  文字名称* @param {Number} x  x轴坐标* @param {Number} y  y轴坐标* @param {Number} maxwidth  最大宽度* @param {String} color  颜色* @param {String} font  字体样式* @param {String} textalign  文字排版*/drawText (title, x, y, maxwidth, color, font, textalign = 'center') {this.canvas.font = fontthis.canvas.textAlign = textalignthis.canvas.fillStyle = colorthis.canvas.fillText(title, x, y, maxwidth)},/*** 显示图片*/showPic () {// 获取canvas对象let canvas = this.$refs.canvastry {// 将canvas对象转化为image/pngvar dataUrl = canvas.toDataURL('image/png')} catch (err) {console.log(err)}// 创建img 元素var newImg = document.createElement('img')newImg.src = dataUrlnewImg.style.width = '100%'newImg.style.height = '100%'newImg.className = 'img-poster'newImg.style.borderRadius = '8px'this.$refs.box.appendChild(newImg)}}
}
</script>

盘查了好久,最后找到bug,就是下面这个function

 /*** 加载图片* @param {Object} img 图片地址* @return {Promise} img dom*/loadImage (img) {return new Promise((resolve, reject) => {// image dom 对象const $image = document.createElement('img')$image.src = img.urlif (img.isCross_domain) {console.log(img.url)$image.setAttribute('crossOrigin', 'Anonymous')}$image.onload = () => {resolve($image)}$image.onerror = reject})},

有没有注意到crossOrigin属性是在src属性之后赋值的;/(ㄒoㄒ)/~~
crossOrigin属性必须在src属性之前赋值
crossOrigin属性必须在src属性之前赋值
crossOrigin属性必须在src属性之前赋值
尽管没有找到准确的文档明确指定crossOrigin属性必须在src属性之前赋值,但是要适配IOS确实要这么做;
大家如果对 crossorigin 有疑问可以看一下MDN对crossorigin的解释:
https://developer.mozilla.org/zh-CN/docs/Web/HTML/CORS_enabled_image

里面讲了画布的污染和解决方法,就是设置 crossorigin = “Anonymous”;里面的方法也是先设置crossorigin在图片加载完后设置 src;
如下

var img = new Image,canvas = document.createElement("canvas"),ctx = canvas.getContext("2d"),src = "http://example.com/image"; // insert image url hereimg.crossOrigin = "Anonymous";img.onload = function() {canvas.width = img.width;canvas.height = img.height;ctx.drawImage( img, 0, 0 );localStorage.setItem( "savedImageData", canvas.toDataURL("image/png") );
}
img.src = src;
// make sure the load event fires for cached images too
if ( img.complete || img.complete === undefined ) {img.src = "data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///ywAAAAAAQABAAACAUwAOw==";img.src = src;
}

一切搞定

LOVE  & PEACE

关于canvas.toDataURL 在iOS运行失败的问题相关推荐

  1. iOS子构建Debug运行正常Release运行失败,提示证书问题

    iOS子构建Debug运行正常Release运行失败,提示证书问题 在老版本的Xcode上创建子构建时会自动创建对应的证书和描述文件,但是在Xcode12上不会自动创建Release对应的证书和描述文 ...

  2. ios html字符串 h5,javascript – iOS HTML5 Canvas toDataURL

    我需要一些帮助.对于通过 HTML 5 / Canvas获取图像的base64,我们似乎遇到了iOS问题.如果我们使用画布的默认高度/宽度或硬编码高度和宽度,一切正常.但是,如果我们将画布高度/宽度设 ...

  3. base64压缩/canvas.toDataURL

    "jpg和jpeg没有区别,是缩写的程度不同.jpeg文件扩展名应该为.jpeg,dos 时代的8.3文件规定扩展名不能超过3个字符,就使用了.jpg. canvas.toDataURL(t ...

  4. 前端 canvas toDataURL() 转图片生成空白图片问题

    这里写自定义目录标题 前端 canvas toDataUrl() 转图片生成空白图片问题 感谢大神 解决方法 问题发生 解决办法原理 vue项目中的使用 总结 2022-05-17追加修改 前端 ca ...

  5. wmp流代理服务器设置为空,wmp服务器运行失败

    wmp服务器运行失败 内容精选 换一换 备份option-http_proxy.cfg文件.mv /usr/local/haproxy/conf/option-http_proxy.cfg /usr/ ...

  6. Xamarin Android项目运行失败

    Xamarin Android项目运行失败 错误信息:Build Failed: MonoDroid does not support running the previous version.  P ...

  7. 解决Canvas.toDataURL 图片跨域问题

    解决Canvas.toDataURL 图片跨域问题 参考文章: (1)解决Canvas.toDataURL 图片跨域问题 (2)https://www.cnblogs.com/ajg016/p/547 ...

  8. python gui打包exe pyinstaller打包运行失败 Failed to execute script pyi_rth_multiprocessing

    python 通过pyinstaller打包后,在别的电脑运行失败 Failed to execute script pyi_rth_multiprocessing 在低版本windows7上运行会出 ...

  9. c# 再次尝试 连接失败_和平精英ios充值失败该怎么办

    和平精英ios充值失败该怎么办?近期有小伙伴说自己用苹果手机充值却显示充值失败,这种情况该怎么解决呢?其实这不是大问题,看看下面的解决办法. 和平精英ios充值失败 和平精英ios充值失败只需要重新填 ...

最新文章

  1. NOI2012 美食节
  2. linux shell ls 输出存进数组变量
  3. php和python区别-编程语言之PHP与Python之间的差异
  4. The 2016 ACM-ICPC Asia China-Final Contest Promblem D
  5. 让你的PHP也能执行JS并获得JS函数的返回值
  6. 一行SQL代码能做什么?
  7. MS SqlServer中少用但是好用的SQL语句
  8. powerbuilder提示不是下拉窗口_为什么过去状态管理不是问题?
  9. mit数据集_DriveSeg:动态驾驶场景分割数据集
  10. 洛谷找最小值c语言,洛谷 P1478 陶陶摘苹果(升级版) C语言实现
  11. 从入门到精通:卷积神经网络初学者指南
  12. Iterables和迭代器
  13. 英特尔® 实感™ SDK 架构
  14. 英伟达显卡gtx和gt的区别
  15. conan入门(六):conanfile.txt conanfile.py的区别
  16. 如何自制自平衡云台基于mpu6050,arduino输出三维倾斜角度的方法(含源码,库)
  17. GIS应用技巧之数据结构(栅格与矢量)
  18. 笔记本wife功能丢失,网络适配器代码56错误
  19. 困难模式60级斗士双持武器(一手一把)技能点加发!--个人意见!
  20. Hadoop3.3.3完全分布式安装(Centos7.x)(保姆教程)

热门文章

  1. STM32--USART详解
  2. 《Structure-Invariant Testing for Machine Translation》笔记
  3. Hector、Gmapping、Karto、CoreSLAM、LagoSLAM
  4. int转String
  5. 创业,不能兼职(转载篇)-- 创业公司应该如何给员工期权
  6. 实战Vue:Mint UI移动端购物商城
  7. Google Gears
  8. Visual Studio 2013 MFC 编程
  9. 中国无车承运人行业需求前景与投资战略研究报告2022-2027年
  10. 云贝餐饮外卖020v2版v1.7.7 O2O新零售 外卖/店内/预定/排号 同城便民分类信息