贴出本作者处理的具体代码如下:
/* 判断是否是isIE11或isEdge或isLessIE11 */
function isIE11Fn() {
var userAgent = navigator.userAgent; //取得浏览器的userAgent字符串
var isLessIE11 = userAgent.indexOf("compatible") > -1 && userAgent.indexOf("MSIE") > -1;
// 判断是否为IE的Edge浏览器
var isEdge = userAgent.indexOf("Edge") > -1 && !isLessIE11;
// 判断是否为IE11浏览器
var isIE11 = userAgent.indexOf("Trident") > -1 && userAgent.indexOf("rv:11.0") > -1;
return isLessIE11 || isIE11 || isEdge;
};
// 请求接口,举例子:
var api = "xxx接口url地址"; // 返回
if (isLessIE11 || isIE11 || isEdge) {
api += "&is_base64image=1"; // 返回base64格式图片
}
// 请求接口
jqueryAjaxGet(api, null, function (res) {
// 里边进行相关的逻辑处理等
if (res.status == 1) {
_this.poster = res.data;
var imgarr = [_this.poster.background_img];
if(_this.poster.goods_list.length) {
$.each(_this.poster.goods_list, function(i, item){
imgarr.push(item.goods_image);
})
}
downloadImg(".poster_con", 'poster', imgarr);
}
});
一、安装
script形式引入“html2canvas.min.js
”,实际路径按项目的来(记得修改路径~)
script src="xxx/..../common/html2canvas.min.js"></script>
二、使用
封装成公共的方法进行使用
/**
* @Author: acaiEncode
* @File: 保存图片or保存海报
* @param {*} canvasImgClass 截图的包裹的dom对象(原生)
* @param {*} imgName 图片名称
* @param {*} imgArr dom图片数组
* 提示:前提需要先引入html2canvas.js,版本号:1.0.0-rc.7
* 使用:downloadImg(".poster_con", 'poster', imgarr);
*/
function downloadImg(canvasImgClass, imgName, imgArr) {
loading.showloading();
var canEle = $(canvasImgClass)[0]; // 获取截图的包裹的dom对象(原生)
var width = canEle.offsetWidth; // 获取dom宽
var height = canEle.offsetHeight; // 获取dom高
var canvas = document.createElement('canvas'); // 创建一个canvas节点
// var scale = height / (height * window.devicePixelRatio); // 定义任意放大倍数 支持小数
var scale = window.devicePixelRatio; // 定义任意放大倍数 支持小数
canvas.width = width * scale; // 定义canvas 宽度 * 缩放
canvas.height = height * scale; // 定义canvas高度 *缩放
var content = canvas.getContext("2d");
content.scale(scale, scale); //获取context,设置scale
// var rect = canEle.getBoundingClientRect(); //获取元素相对于视察的偏移量
// content.translate(-rect.left, -rect.top); //设置context位置,值为相对于视窗的偏移量负值,让图片复位
var options = {
scale: scale, // 添加的scale 参数
canvas: canvas, // 自定义 canvas
width: width, // dom 原始宽度
height: height,
x: window.pageXOffset, // 裁剪画布X坐标
y: window.pageYOffset,
// foreignObjectRendering: true, // 最主要是这句话,官方给出解释是否在浏览器支持的情况下使用ForeignObject渲染,
// scrollX: 0, // 渲染元素时要使用的x滚动位置(例如,如果Element使用position: fixed)
// scrollY: 0,
tainttest: true, // 检测每张图片都已经加载完成
useCORS: true // 【重要】开启跨域配置
};
// 重点:接口图片返回较多时需等图片加载完成才进行截图描绘
if(imgArr && imgArr.length) {
var img = [],
flag = 0,
mulitImg = imgArr;
var imgTotal = mulitImg.length;
for (var i = 0; i < imgTotal; i++) {
img[i] = new Image()
img[i].onload = function () {
//第i张图片加载完成
flag++
if (flag == imgTotal) {
// 全部加载完成,进行画布的裁剪
getCanvas(canvas,canEle,options,imgName)
}
}
img[i].src = mulitImg[i];
}
} else {
// 画布的裁剪
getCanvas(canvas,canEle,options,imgName)
}
};
/**
* 画布生成后下载图片
*
* @param {*} canvas 画布
* @param {*} canEle dom对象
* @param {*} options 配置项
* @param {*} imgName 图片名称
*/
function getCanvas(canvas, canEle, options, imgName) {
var canvas = canvas;
html2canvas(canEle,options).then(function(canvas) {
var context = canvas.getContext('2d');
// 关闭抗锯齿 保证生成的分享图是清晰的
context.mozImageSmoothingEnabled = false;
context.webkitImageSmoothingEnabled = false;
context.msImageSmoothingEnabled = false;
context.imageSmoothingEnabled = false;
var imgDataUrl = canvas
.toDataURL("image/" + ".jpg")
.replace("image/" + ".jpg", "image/octet-stream"); // 得到图片base64编码数据
if (window.navigator.msSaveOrOpenBlob) {
// 允许用户在客户端上保存文件
var bstr = atob(imgDataUrl.split(",")[1]);
var n = bstr.length;
var u8arr = new Uint8Array(n);
while (n--) {
u8arr[n] = bstr.charCodeAt(n);
}
var blob = new Blob([u8arr]);
window.navigator.msSaveOrOpenBlob(blob, imgName + "." + "jpg");
} else {
// 这里就按照chrome等新版浏览器来处理保存图片
var a = document.createElement("a");
a.href = imgDataUrl;
// a.id = 'imgDownBtn';
a.setAttribute("download", imgName+".jpg");
a.click();
$().remove(a);
// document.remove($('#imgDownBtn'));
}
loading.hideloading();
});
}
// loading
var loading = {
showloading: function (msg) {
var hadMask = $("body div").hasClass(".win-mask");
if (hadMask) {
$(".win-mask").show();
} else {
loading.innerloading(msg);
}
},
hideloading: function () {
$(".win-mask").remove();
},
innerloading: function (msg) {
var def_msg = "";
def_msg = msg ? msg : '正在加载中...';
$("body").append('<div class="win-mask">\
<div class="loading-box">\
<div class="loadings"></div> ' + def_msg + '\
</div>\
</div>');
}
}
具体页面上的详细使用
// html
<section id="liveShareWin">
<div class="commonPopup" style="z-index: 999; display: none"></div>
<div class="commonPopup-container" style="z-index: 8000; position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%); display: none; margin-left: -500px; margin-top: -296.5px;">
<div class="commonPopup-header">
<h3>分享</h3>
<div class="close-img commonPopup-close-js"></div>
</div>
<div class="commonPopup-body">
<div class="row">
<div class="col-md-6 leftBox">
<h4>直播间小程序码</h4>
<div class="liveCodeImg">
<img src="" >
</div>
<div>
<!-- <button class="saaveCodeBtn imgSaveBtn">保存图片</button> -->
<a class="saveCodeBtn imgSaveBtn" download="直播间小程序码.jpg">保存图片</a>
</div>
</div>
<div class="col-md-6 rightBox">
<h4>直播间分享海报</h4>
<div class="posterShare">
<div class="bannerImg">
<img src="" >
</div>
<h6></h6>
<div class="footerContent row">
<div class="col-md-8">
<p class="timesBox"></p>
<p class="tips">长按识别小程序码,观看直播</p>
</div>
<div class="col-md-4">
<div class="miniCode">
<img src="" >
</div>
</div>
</div>
</div>
<div>
<button class="savePosterBtn imgSaveBtn">保存图片</button>
</div>
</div>
</div>
</div>
</div>
</section>
// css
#liveShareWin .row>div {
text-align: center;
}
#liveShareWin .row>.rightBox::after {
content: '';
display: inline-block;
border-right: 1px dashed #ccc;
height: 50%;
position: absolute;
top: 94px;
left: 0;
}
#liveShareWin h4 {
font-size: 18px;
color: #333;
font-weight: bold;
padding-top: 40px;
}
.liveCodeImg {
width: 180px;
height: 180px;
margin: 0 auto;
margin-top: 40px;
}
.liveCodeImg>img {
width: 100%;
height: 100%;
}
#beginnerGuide .openQuliyBtn,
#liveShareWin .imgSaveBtn {
display: inline-block;
width: 160px;
height: 40px;
font-size: 16px;
color: #fff;
background-color: #fe5043;
border-radius: 5px;
}
.saveCodeBtn {
margin-top: 60px;
line-height: 40px;
}
.posterShare {
width: 300px;
/* height: 395px; */
box-shadow: rgba(0, 0, 0, .13) 0px 0px 13px 1px;
margin: 0 auto;
margin-top: 20px;
}
.bannerImg {
width: 300px;
height: 240px;
}
.bannerImg>img {
width: 100%;
height: 100%;
}
.savePosterBtn {
margin-top: 30px;
}
.posterShare h6 {
margin: 20px 10px;
font-size: 16px;
text-align: left;
height: 40px; /* 一定要固定高度,火狐和ie浏览器超过省略,但是点点不会出来 */
line-height: 20px;
word-break: break-all;
/* white-space: nowrap; */
overflow: hidden;
/* text-overflow: ellipsis; */
}
.footerContent {
padding: 20px 10px;
}
.footerContent>div {
padding: 0;
}
.footerContent p {
text-align: left;
font-size: 14px;
padding-top: 20px
}
.footerContent p.tips {
font-size: 12px;
padding-top: 10px
}
.footerContent p.tips::after {
content: '';
display: block;
width: 12px;
height: 2px;
background-color: red;
margin-top: 5px;
}
/* .col-md-8 {
border-right: 1px dashed #fedada;
} */
.miniCode {
width: 62px;
height: 62px;
margin: 6px auto;
margin-left: 20px;
}
.miniCode>img {
width: 100%;
height: 100%;
}
// js
var room_mini_code = '';
var miniCodeArr,
poseterBannerArr = [];
$('.liveManage .tbody').on('click', '.shareBtn', function() {
var room_id = $(this).data('roomid');
jqueryAjaxPost(api.shareLive, {room_id: room_id}, function (res) {
miniCodeArr,
poseterBannerArr = [];
if(res.status) {
var res = res.data;
miniCodeArr = [res.room_mini_code];
poseterBannerArr = [res.room_mini_code, res.share_img];
room_mini_code = res.room_mini_code;
$('#liveShareWin .liveCodeImg>img').prop('src', res.room_mini_code);
// $('#liveShareWin .saveCodeBtn').prop('href', res.room_mini_code); // 直播间小程序码
$('#liveShareWin .miniCode>img').prop('src', res.room_mini_code);
$('#liveShareWin .bannerImg>img').prop('src', res.share_img);
$('#liveShareWin .posterShare>h6').html(res.name);
var times = res.start_time + ' - ' + res.end_time;
$('#liveShareWin .footerContent .timesBox').html(times);
liveShareWin.show();
} else {
alert(res.msg);
}
});
});
// 保存图片-download
$('#liveShareWin .saveCodeBtn').on('click', function() {
// (-html2canvas实现方式)
// downloadImg('#liveShareWin .liveCodeImg', '小程序码', miniCodeArr);
if(room_mini_code) {
init.compADown(room_mini_code, '直播间小程序码');
}
})
$('#liveShareWin .savePosterBtn').on('click', function() {
downloadImg('#liveShareWin .posterShare', '海报', poseterBannerArr);
// liveShareWin.hide();
})
效果图:
三、遇到bug及对策
1、在jQuery中引入使用html2vanvas.js
,在IE浏览器会有出现一个报错:SCRIPT5009: “Promise”
未定义
解决方案:引入es6-promise.auto.min.js
插件进行处理。
2、jQuery配合html2canvas 使用时 报错 Uncaught (in promise) Provided element is not within a Document
原因是:html2canvas接收的是 一个 js DOM 元素而不是 一个 jQuery DOM对象。
var canEle = $(canvasImgClass); // jquery 获取元素
解决思路:
var canEle = $(canvasImgClass)[0]; // 获取截图的包裹的dom对象(原生)
3、使用img = new Image(); img.onload = function() {}
后html2canvas出现以下报错:
配置项加入:
foreignObjectRendering: true, // 最主要是这句话,官方给出解释是否在浏览器支持的情况下使用ForeignObject渲染,
报错虽然解决,但是出现另外的问题:图片无法显示,绘图错乱。
经过排查,发现主要原因是:由如下代码导致图片还在onload,而画布还没有开始画,就隐藏了,因此画布就没有高度/宽度,以至于报错,注释后,则没有报错了。
$("#poster_body").attr("style", "display:none;");
因此得出结论:必须是dom可视才能很好的进行使用html2canvas截图生成海报!
4、html2canvas对两行省略不识别,会直接丢弃,出来空白的结果;而一行省略的话,点点也是不识别的,会直接切掉文字
5、html2canvas对虚线无效,会把虚线识别为实线展示出来
解决方案(本文采用的方案):不用虚线或者改为实线!(一定要使用需要用虚线的客官,可以尝试贴出来解决的方案)。
6、弹窗使用html2canvas后一直都是空白的!
原因是:截取区域在弹窗
解决方案:
番外:移动端使用html2canvas进行生成海报并下载图片
1、pc端所使用的方式在移动端在使用时,出现不适配兼容所有移动端的各个浏览器的问题。
目前qq打开h5页面,则前提需要安装qq浏览器,则可以进行下载,UC等类型的浏览器可以下载;
微信内置浏览器不兼容,原因其不支持下载文件的原因,要解决此问题。
具体的解决方案可参考以下:(主要是通过跳转第三方浏览器即可使用)
(1)微信内置浏览器不支持下载文件应用的解决方法
(2)微信内置浏览器不支持下载的解决方案 微信点击链接直接下载app安装包功能实现方式
(3)使用h5 标签 href='url' download 下载踩过的坑
其次,h5内嵌到自己的app上也有问题:安卓能够进行下载图片,前提是要传生成好的图片过去,但是安卓是不能够下载的,只能长按保存图片!总结如下:
2、因此鉴于以上所描述的种种问题,若移动端想要实现海报的下载图片功能,又能够友好的兼容移动端端各个端,采用的最佳方案就是把html2canvas生成的海报图片,展示在页面上,引导用户进行长按保存图片。
效果案例图:
具体代码参考: [html2canvas在vue2中的应用-移动端](html2canvas在vue2中的应用-移动端 #掘金文章# juejin.cn/post/698387…)
常见问题FAQ
- 免费下载或者VIP会员专享资源能否直接商用?
- 本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
- 提示下载完但解压或打开不了?
- 找不到素材资源介绍文章里的示例图片?
- 模板不会安装或需要功能定制以及二次开发?
发表评论
还没有评论,快来抢沙发吧!