前段时间,产品和运营整了个非常变态的需求,要求将一个活动页面输出为图片,然后用户进行分享

开始以为是用户自己手动截图分享,没想到后来不是,细思极恐,感叹需求之变态。

从网上找了N个方案,最后确定使用 html2canvas 基本可实现(http://html2canvas.hertzen.com/),下面开始踩坑。

html2canvas 的原理在于利用封装的js将html的显示输出转化为canvas,根据页面的复杂度,可能会遇到一些问题。

截图模糊

解决原理就是讲canvas画布的width和height放大两倍

后来了解canvas的时候,其写法不同于css的宽高设置,因为css里的只是展示画布显示的大小,不像canvas是真正的图画分辨率的大小

 /*图片跨域及截图模糊处理*/
let shareContent = domObj,//需要截图的包裹的(原生的)DOM 对象
width = shareContent.clientWidth,//shareContent.offsetWidth; //获取dom 宽度
height = shareContent.clientHeight,//shareContent.offsetHeight; //获取dom 高度
canvas = document.createElement("canvas"), //创建一个canvas节点
scale = 2; //定义任意放大倍数 支持小数
canvas.width = width * scale; //定义canvas 宽度 * 缩放
canvas.height = height * scale; //定义canvas高度 *缩放
canvas.style.width = shareContent.clientWidth * scale + "px";
canvas.style.height = shareContent.clientHeight * scale + "px";
canvas.getContext("2d").scale(scale, scale); //获取context,设置scale
let opts = {
scale: scale, // 添加的scale 参数
canvas: canvas, //自定义 canvas
logging: false, //日志开关,便于查看html2canvas的内部执行流程
width: width, //dom 原始宽度
height: height,
useCORS: true // 【重要】开启跨域配置
};
html2canvas(shareContent,opts).then()

the operation is insecure

canvas.toDataURL 报错 the operation is insecure

canvas.toDataURL(type, encoderOptions);语法

配置如:canvas.toDataURL("image/png", 0.7);

参数type指定图片类型,如果指定的类型不被支持则以默认值image/png替代;

encoderOptions(第二个参数)可以为image/jpeg或image/webp类型的图片设置图片质量,取值0-1,超出则以默认值0.92替代。

html2canvas在微信中base64码为空

在微信中或者可以说在移动端浏览器里,canvas.toDataURL不成功。canvas.toDataURL(type) 得到空的 data:;

引发这个问题的操作可能有2中,1、canvas被污染,2、生成图片过大,base64码有长度限制

不可见的元素截图后是空白

没法截图看不见的,比如opacity为0的东西,或者visibility为hidden的,更别说display:none了。

解决方法是让canvas部分隐藏到后边。最终选择方案,层级设为-1,上一层的把他盖住。前提是上一层要又一个可以设置的背景色,能把他盖住不被世人看到

html2canvas结合微信里的长按存图功能
先用html2canvas拿到一个html转为canvas的base64码,

再在页面建立一个img元素,src=base64码,插入dom中,盖在所有元素的最上方(或者需要用户长按保存的地方),opacity设置为0。

然后用户就长按保存,存下来的就是事先准备好的覆盖在那里的那个不可见得透明图。

事实证明,图片透明不可见覆盖在页面上边,微信里是可以存图的。

html2canvas 截图跨域

图片跨域时报错现象

这个时候你要去看图片的header头有没有这个:

看图片本身是否允许跨域访问:

 

上边这个是一个允许的图片。下边这个不允许,就截取不到。

  

主要是用于解决了本次问题的地方:useCORS:true 这个参数很重要,没有配置的话,依旧是不能解决问题的;

根据现有的解决方案大致有两种: 
  (1).在跨域的服务器上设置header设置为允许跨域请求。 在服务器上设置header设置允许跨域请求
  (2).借助代理脚本获得外域图片的 base64 编码后的字符串,本文未采用。

作者:旧旧的 <393210556@qq.com> 解决问题的方式,就是解决它一次

web前端生成图片之探索踩坑的更多相关文章

  1. [Web 前端] React Router v4 入坑指南

    cp from : https://www.jianshu.com/p/6a45e2dfc9d9 万恶的根源 距离React Router v4 正式发布也已经过去三个月了,这周把一个React的架子 ...

  2. 【web】docker复现环境踩坑

    在先知看到有师傅发了个学习 P 牛的代码审计的文章,在 github 上下下来复现环境,结果 docker 各种问题,气死 安装 docker-compose:pip install -i https ...

  3. React Native 环境搭建踩坑

    React Native (web Android)环境搭建踩坑(真的是一个艰辛的过程,大概所有坑都被我踩了 官方文档地址 : https://facebook.github.io/react-nat ...

  4. Web前端开发(基础学习+坑)

    0.基本说明 0.内容为课堂所学基本知识,加自己踩过的坑 1.web基本框架:html+css+JavaScript,html为网页骨架,css为网页美化,JavaScript负责页面动态交互,脚本等 ...

  5. vue.js 踩坑第一步 利用vue-cli vue-router搭建一个带有底部导航栏移动前端项目

    vue.js学习 踩坑第一步 1.首先安装vue-cli脚手架 不多赘述,主要参考WiseWrong 的 Vue 爬坑之路(一)-- 使用 vue-cli 搭建项目 2.项目呈现效果 项目呈现网址:w ...

  6. web前端入坑第二篇:web前端到底怎么学?干货资料! 【转】

    http://blog.csdn.net/xllily_11/article/details/52145172 版权声明:本文为博主[小北]原创文章,如要转载请评论回复.个人前端公众号:前端你别闹,J ...

  7. web前端入坑第五篇:秒懂Vuejs、Angular、React原理和前端发展历史

    秒懂Vuejs.Angular.React原理和前端发展历史 2017-04-07 小北哥哥 前端你别闹 今天来说说 "前端发展历史和框架" 「前端程序发展的历史」 「 不学自知, ...

  8. ASP.NET Web 应用 Docker踩坑历程——续

    ASP.NET Web 应用 Docker踩坑历程发表后,也开始使用Docker了,然而发布的过程比较痛苦,经常发生下图的事情: 据说是nuget包还原时发生错误 百度了半天也找不到解决的方法,而发生 ...

  9. react-router 踩坑记

    react-router踩坑分享 背景 辛苦历程 JavaScript动态修改 第一次尝试 第二次尝试 第三次尝试 第四次尝试 总结步骤 其他方案 原理 History 常见的3种History Br ...

随机推荐

  1. 自动发现项目中的URL,django1版本和django2版本

    一.django 1 版本 routers.py import re from collections import OrderedDict from django.conf import setti ...

  2. Diycode开源项目 TopicContentActivity分析

    1.效果预览以及布局分析 1.1.实际效果预览 左侧话题列表的布局是通过TopicProvider来实现的,所以当初分析话题列表就没有看到布局. 这里的话题内容不是一个ListView,故要自己布局. ...

  3. Spring---浅谈AOP

    概念 AOP是Aspect Oriented Programming的缩写,即面向切面的编程.是一种比较新颖的编程思想,也是Spring框架中一个重要的领域. AOP将应用系统分为两个部分:核心业务逻 ...

  4. P3402 最长公共子序列(nlogn)

    P3402 最长公共子序列 题目背景 DJL为了避免成为一只咸鱼,来找Johann学习怎么求最长公共子序列. 题目描述 经过长时间的摸索和练习,DJL终于学会了怎么求LCS.Johann感觉DJL孺子 ...

  5. Spring MVC 使用 HttpServletResponseWrapper 修改返回结果

    HttpServletResponseWrapper 是什么? ServletResponse 的包装类,相关设计模式 装饰者模式. 运行环境 jdk 1.7 spring boot 整合的web环境 ...

  6. loj2045 「CQOI2016」密钥破解

    CQOI 板子大赛之 pollard rho #include <iostream> #include <cstdio> using namespace std; typede ...

  7. ogre3D学习基础19 --- 材质的继承,纹理的滚动与旋转

    以上一节为基础,废话不多说. 首先新增一个节点,用于比较显示 //新增一个节点 ent = mSceneMgr->createEntity("Quad"); ent-> ...

  8. 第一章:前端布局之display属性

    css布局学习网站:http://zh.learnlayout.com

  9. PostgreSQL 数组类型

    PostgreSQL 支持表的字段使用定长或可变长度的一维或多维数组,数组的类型可以是任何数据库内建的类型.用户自定义的类型.枚举类型, 以及组合类型.但目前还不支持 domain 类型. 数组类型的 ...

  10. python中 in, any 和 all用法

    in if x == 1 or y == 1 or z == 1: print('passed') if 1 in (x, y, z): print('passed') any if x or y o ...