html2canvas生成海报的各种问题

html2canvas

  • (一)官网下载安装
  • (二)基础用法
  • (三)生成海报问题
    • canvas高分屏下的模糊问题
    • html2canvas图片模糊问题
    • canvas图片getImageData,toDataURL跨域问题
        • 1) 首先,图片服务器需要配置Access-Control-Allow-Origin
        • 2) canvas图片getImageData cross-origin跨域问题
    • 图片加载导致海报生成不了
    • ios的兼容性问题
    • ios 生成图片时显示时不显的,大图几乎不显示

(一)官网下载安装

下载:https://html2canvas.hertzen.com/
vue 安装:npm install html2canvas

(二)基础用法

以vue为例子

<div @click="handlePoster()" class="btn">生成海报</div>
<div id="weeklyPoster" ref="weeklyPoster" class="poster"><h1>poster content</h1><img class="poster__logo" src="./assets/img/share-logo.png" alt="" crossOrigin="anonymous">
</div>
<div v-if="sharePoster.show" class="poster__save"><img class="poster__logo" :src="sharePoster.url" alt="">
</div>
<script>
import html2canvas from 'html2canvas';
data () {return {sharePoster: { // 海报内容show: false,url: '',height: 0,width: 0},}
}
methods: {handlePoster() {this.getWeeklyWxCode(()=>{ // 向获取二维码接口发起请求if(!this.sharePoster.url) { // 第一次生成海报// 提示海报生成中...this.$nextTick(() => {setTimeout(()=>{html2canvas(document.querySelector('#myPoster'), {scrollX: 0,scrollY: 0,allowTaint: true,useCORS: true,backgroundColor: null // 解决生成的图片有白边}).then((canvas) => {// 隐藏提示海报生成中let dataURL = canvas.toDataURL('image/jpeg');this.sharePoster.url = dataURL;this.sharePoster.show = true;this.sharePoster.height = canvas.height / 100; // 单位remthis.sharePoster.width = canvas.width / 100;});},600)});} else {this.sharePoster.show = true;}})},
}
</script>

(三)生成海报问题

canvas高分屏下的模糊问题

介绍:
开发手机 canvas 应用,在高分屏下,尤其是手持设备,如搭载高分屏的手机平板等,其显示效果会变得模糊,带给用户的体验很不好。

问题分析:

解决方案:

  1. 首先我们计算 webkitBackingStorePixelRatio / devicePixelRatio 的比值,这里为了方便称之为倍率 ratio
  2. 把 canvas 的 width 和 height 设置为 ratio 倍,这样浏览器便会按照 ratio * ratio 倍像素去渲染该 canvas
  3. 我们在用 CSS 把 canvas 的大小强制再调节为原始大小
  4. 使用 canvas 画布 context 的 scale 方法把渲染区域扩大 ratio 倍以填充屏幕 ( 后面会有解释 )
// 获取 ratio 比例
function getPixelRatio(context) {// 获取 canvas 的 backingStorePixelRatio 值var backingStore = context.backingStorePixelRatio ||context.webkitBackingStorePixelRatio ||context.mozBackingStorePixelRatio ||context.msBackingStorePixelRatio ||context.oBackingStorePixelRatio ||context.backingStorePixelRatio || 1;// 若 devicePixelRatio 不存在,默认为 1return (window.devicePixelRatio || 1) / backingStore;
}
// 调整 canvas
function adjustCanvas(canvas, context) {var ratio = getPixelRatio(context);// 获取 canvas 的原始大小var oldWidth = canvas.width;var oldHeight = canvas.height;// 按照比例放大 canvascanvas.width = oldWidth * ratio;canvas.height = oldHeight * ratio;// 用 css 将 canvas 再调整成原来大小canvas.style.width = oldWidth + 'px';canvas.style.height = oldHeight + 'px';// 按照比率把 context 再缩放回来context.scale(ratio, ratio);
}// 调用
// 此处默认你的 canvas 已经是你要的实际尺寸
var canvas = document.getElementById('myCanvas');
var ctx = canvas.getContext('2d');
adjustCanvas(canvas, ctx);

转载链接

html2canvas图片模糊问题

问题: html2canvas 渲染背景图片 background-image 会不清晰。
解决方法:使用 Img 标签。

canvas图片getImageData,toDataURL跨域问题

1) 首先,图片服务器需要配置Access-Control-Allow-Origin

一般团队都会有一个专门域名放置静态资源,例如腾讯是gtimg.com,百度是bdimg.com;或者很多团队使用的是腾讯云或者阿里云的服务。
而主页面所在域名往往不一样,当需要需要对canvas图片进行getImageData()或toDataURL()操作的时候,跨域问题就出来了,而且跨域问题还不止一层。
eg:PHP添加响应头信息

// *通配符表示允许任意域名
header("Access-Control-Allow-Origin: *");// 指定域名
header("Access-Control-Allow-Origin: www.zhangxinxu.com");

此时,Chrome浏览器就不会有Access-Control-Allow-Origin相关的错误信息了,但是,还会有其他的跨域错误信息。

2) canvas图片getImageData cross-origin跨域问题

对于跨域的图片,只要能够在网页中正常显示出来,就可以使用canvas的drawImage() API绘制出来。但是如果你想更进一步,通过getImageData()方法获取图片的完整的像素信息,则多半会出错。

var canvas = document.createElement('canvas');
var context = canvas.getContext('2d');var img = new Image();
img.onload = function () {context.drawImage(this, 0, 0);context.getImageData(0, 0, this.width, this.height);
};
img.src = 'https://avatars3.githubusercontent.com/u/496048?s=120&v=4';';

解决方案:可以试试crossOrigin属性

1)HTML5中,有些元素提供了支持CORS(Cross-Origin Resource Sharing)(跨域资源共享)的属性,这些元素包括<img>,<video>,<script>等。

<img src="img/png" alt=""  crossorigin="anonymous">
  1. 增加一个img.crossOrigin = ''即可,虽然JS代码这里设置的是空字符串,实际上起作用的属性值是anonymous。
var canvas = document.createElement('canvas');
var context = canvas.getContext('2d');var img = new Image();
img.crossOrigin = '';
img.onload = function () {context.drawImage(this, 0, 0);context.getImageData(0, 0, this.width, this.height);
};
img.src = 'https://avatars3.githubusercontent.com/u/496048?s=120&v=4';';

或者这样写:

drawCanvas() {if (!this.isLoadImg) {Promise.all([new Promise((resolve, reject) => {this.saveImgObj = new Image();this.saveImgObj.onload = () => {resolve();};this.saveImgObj.src = this.saveImg;this.saveImgObj.setAttribute("crossOrigin","Anonymous");}),new Promise((resolve, reject) => {this.codeImgObj = new Image();this.codeImgObj.onload = () => {resolve();};this.codeImgObj.src = this.codeImg;this.codeImgObj.setAttribute("crossOrigin","Anonymous");})]).then(() => {this.isLoadImg = true;this.drawHandler();this.posterImg = this.$refs.canvasPad.toDataURL();});} else {this.drawHandler();this.posterImg = this.$refs.canvasPad.toDataURL();}
},
drawHandler () {let canvas= this.$refs.canvasPad;let ctx= cav.getContext("2d");adjustCanvas(canvas, ctx);
}

注意:
crossOrigin兼容性:IE11+(IE Edge),Safari,Chrome,Firefox浏览器均支持,IE9和IE10会报SecurityError安全错误

图片加载导致海报生成不了

用原生的方法等待所有图片加载完成后,在执行绘制
解决方法:

function imgLoad(imgArr, ck) { let imgs = imgArr Promise.all(imgs.map((src, index) => { return new Promise((resolve, reject) => { let img = new Image() img.onload = () => { resolve(img)}img.onerror = () => { reject(src, index) } img.crossOrigin = 'anonymous' img.src = src }) })).then(arr => { ck(arr) }).catch(e => { console.log(e) }) 
},

ios的兼容性问题

html2canvas: "1.0.0-rc. 5"版本在运行在苹果13.4 系统 iphone7 iphonex iPhone11下都生成不了的时候,安卓没问题,微信内置浏览器不行(真机);
请看看html2canvas的版本,只有1.0.0-rc.4这个版本是可行的,如果你指定下载这个版本在package.json中看到是 ^ 1.0.0-rc.4,则不一定就是1.0.0-rc.4版本,它是指1.0.0-rc.4以上的版本,把^去掉再重新安装依赖就可以了

解决办法:
卸载npm uninstall html2canvas
重新npm i html2canvas@1.0.0-rc.4;
package.json中看到是 ^ 1.0.0-rc.4,^去掉再重新安装依赖

ios 生成图片时显示时不显的,大图几乎不显示

猜测是图片渲染的原因,为了确保能够生成图片
html2canvas库的工作原理:需要我们先提供一段DOM节点,然后它再读取并解析这一段DOM节点生成canvas对象。如果DOM节点中已经使用了<img>标签的话,它也会解析这个<img>标签的src属性,然后重新创建一个Image对象,给它添加crossOrigin="anonymous"属性后尝试以跨域的方式重新读取图片数据。需要注意的是,一般CDN上的图片都是带有缓存响应头并且会在浏览器端缓存的,而且缓存的不仅仅是图片数据,还有HTTP响应头。所以问题的根本原因我们就找到了,当html2canvas尝试以跨域的方式去读取图片数据时,它读取到的是浏览器的缓存数据,而且因为我们没有给DOM节点中的<img>标签添加crossOrigin="anonymous"属性,所以缓存数据是不带Access-Control-Allow-Origin响应头的,进而导致html2canvas库读取到的图片数据污染了生成的canvas对象,最终致使canvas导出数据报错
解决方法:
给DOM节点中的每一个<img>标签都加上crossOrigin="anonymous"属性就可以了

https://segmentfault.com/a/1190000017086056
https://blog.csdn.net/qq_41227106/article/details/106764421

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/401453.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Bootstrap中DropDown插件显示下拉列表,点击下拉列表区域,不会再自动关闭。

目标&#xff1a; Bootstrap中DropDown插件显示下拉列表&#xff0c;点击下拉列表区域&#xff0c;不会再自动关闭。 参考&#xff1a;http://v3.bootcss.com/javascript/#dropdowns // http://stackoverflow.com/questions/19740121/keep-bootstrap-dropdown-open-when-cl…

前端字符串内HTML标签无效的处理方式

1&#xff09;将元素的innerText 赋值成 元素的 innerHTML。即可避免转义的问题&#xff0c;将字符串中包含的 HTML标签生效。 <div ref"introContent" class"intro__content">{{intro}}</div>mounted() {// let text this.$refs.introConte…

获取当前目录绝对路径

echo offecho 当前盘符&#xff1a;%~d0echo 当前盘符和路径&#xff1a;%~dp0echo 当前批处理全路径&#xff1a;%~f0echo 当前盘符和路径的短文件名格式&#xff1a;%~sdp0echo 当前CMD默认目录&#xff1a;%cd%echo 目录中有空格也可以加入""避免找不到路径echo 当…

【CSS】css特殊性-优先级-权重

注&#xff1a;文章来源&#xff1a;《css权威指南》 第三章。 部分未予记录css选择器可以用多种方式去选择元素&#xff0c;实际上一个元素可以由使用两个或者多个规则来匹配&#xff0c;每个规则都有各自的选择器。请看例子CSS:h1 {color: red;}body h1 {color: green;}h2.gr…

vue开发问题积累

mounted钩子中使用$refs出现undefined 原因&#xff1a;如果在DOM结构中的某个DOM节点使用了v-if、v-show或者v-for&#xff08;即根据获得的后台数据来动态操作DOM&#xff0c;即响应式&#xff09;&#xff0c;那么这些DOM是不会再mounted阶段找到的。 **解决方法&#xff1…

动态规划0—1背包问题

动态规划0-1背包问题 问题描写叙述&#xff1a;给定n种物品和一背包。物品i的重量是wi&#xff0c;其价值为vi&#xff0c;背包的容量为C。问应怎样选择装入背包的物品&#xff0c;使得装入背包中物品的总价值最大?对于一种物品&#xff0c;要么装入背包&#xff0c;要么不装。…

Android Intent.FLAG_NEW_TASK详解,包括其他的标记的一些解释

本文大部分参考自 http://blog.csdn.net/mayingcai1987/article/details/6200909 &#xff0c;对原文中的讲解FLAG_NEW_TASK地方加了一些自己的观点&#xff0c;用红色标记 1. Task是包含一系列Activity的堆栈, 遵循先进后出原则. 2. Task默认行为: (1) 前提: Activity A和Ac…

vmstat命令详解

参数详情&#xff1a; r runingb blockswpd 虚拟内存使用时间free 物理free内存buff 从硬盘--->内存的 缓冲cache 从内存--->硬盘的 缓存si 从磁盘写入swap的大小/sso 从swap写入磁盘的大小/sbi 块设备每秒接收的块数量bo 块设备每秒发送的块数量cs 每秒上下文切换次数us…

CSharp设计模式读书笔记(22):策略模式(学习难度:★☆☆☆☆,使用频率:★★★★☆)...

策略模式(Strategy Pattern)&#xff1a;定义一系列算法类&#xff0c;将每一个算法封装起来&#xff0c;并让它们可以相互替换&#xff0c;策略模式让算法独立于使用它的客户而变化&#xff0c;也称为政策模式(Policy)。 模式角色与结构&#xff1a; 示例代码&#xff1a; usi…

评论 展开|收起

场景&#xff1a; 列表中文本最多三行&#xff0c;超出部分省略&#xff0c;并显示展开收起按钮&#xff0c;如果文本没有超出三行则不显示展开收起按钮 方案&#xff1a; 1&#xff09;在div 中添加一个span 然后给div设置超出三行省略&#xff0c;这时候就可以获取到文本高…

【原创】linux 下远程连接windows桌面

一、安装过程 首先到http://www.rdesktop.org下载rdesktop 解压后进入rdesktop文件夹 执行命令&#xff1a; [rootmaster swxing]#./configure [rootmaster swxing]#make ; make install 提示没有安装openssl-devel 执行命令安装openssl-devel&#xff08;以下是在centos下用yu…

什么是.NET

Microsoft.NET 是Microsoft XML Web Service平台。 平台包含4个主要部分1.底层操作系统--Windows。 2.辅助产品--.NET企业服务器。 3.Microsoft XML Web服务--.NET My Servers。 4.开发平台--.NET框架。 CLR和FCL提供的部分服务转载于:https://www.cnblogs.com/dongdongguo/arc…

springboot + ApplicationListener

ApplicationListener自定义侦听器类 Component public class InstantiationTracingBeanPostProcessor implementsApplicationListener<ContextRefreshedEvent> {private static final Logger LOG Logger.getLogger(InstantiationTracingBeanPostProcessor.class);privat…

c语言使用小结

mallocfree typedef struct{   int a;   int b;}HA; cpp是C的扩展在大多数CPP的头文件里 CPP用到的关键字都会被条件编译扩起来以方便C的使用 当C用时CPP用到的关键字不会被编译。本质上CPP是兼容C的。 .lib .o 是程序编译时要使用的己经编译的函数库。 minGW环境可以使用.…

JAVA学习之动态代理

JDK1.6中的动态代理 在Java中Java.lang.reflect包下提供了一个Proxy类和一个InvocationHandler接口&#xff0c;通过使用这个类和接口可以生成一个动态代理对象。JDK提供的代理只能针对接口做代理 java.lang.reflect.Proxy 提供用于创建动态代理类和实例的静态方法&#xff0c;…

net开源项目

1 以色列 特思开源软件 http://cn.tersus.com/#Id3924 2 开源社区 http://www.ctochina.net/ .NET开源项目链接 http://www.cnblogs.com/dustinyang/articles/361479.html项目网址简介Rainbowhttp://www.rainbowportal.net/ http://sourceforge.net/projects/rainbowportal/The…

screen状态变Attached连接会话失败

使用xshell远程登录主机&#xff0c;使用screen命令启动程序运行至后台&#xff0c;意外发现screen session的状态为Attached&#xff0c;使用命令screen -r &#xff1c;session-id>,提示失败信息&#xff0c;重复多次无果。 解决方法&#xff1a;把自己踢掉&#xff0c;然…

引用类型赋值

转载于:https://www.cnblogs.com/dongyuhan/p/6519711.html

poj2624 4th Point

纯水题&#xff0c;注意交点不一定是第二个点和第三个点 #include<stdio.h>#include<string.h>#include<stdlib.h>#include<math.h>#include<algorithm>using namespace std;struct Vector{ double x; double y;};struct point{ double…

Windows Phone开发(30):图形 转:http://blog.csdn.net/tcjiaan/article/details/7453028

图形如矩形、椭圆、路径等都从Shape类派生&#xff0c;它们一般表示规则或不规则图形&#xff0c;这些图形都是简单的二维图形&#xff0c;我相信大家都能理解的。 例一&#xff1a;矩形。 请看下面的XAML代码。 [html] view plaincopyprint? <Rectangle RadiusX"20&q…