Using HTML to realize screenshot - html2canvas usage record

JavaScript language 2020-11-13 05:03:51
using html realize screenshot html2canvas


Recently, project requirements always have HTML Page generation image function , So I want to record my problems in the process , And deepen the impression , In the future, if you forget, you can also review . Our project uses html2canvas plug-in unit , There are other plug-ins , for example dom-to-image、rasterizehtml, It can be used according to the demand .

html2canvas Use problem summary

What was introduced into the project was 0.5.0-beta4 Version of cdn link , Direct call method html2canvas(dom,options); The first parameter is what you want to draw dom object , The second parameter is some of the configuration parameters drawn , I've tried some parameters, but I haven't figured out the specific function. I can see it by myself html2canvas file , For the code I use directly :

// Generate pictures
function generateImg() {
var shareContent = document.body;// The part that needs to be drawn ( Native )dom object , Pay attention to the width of the container, don't use percentage , Use a fixed width , Avoid scaling problems
var width = shareContent.offsetWidth; // obtain ( Native )dom Width
var height = shareContent.offsetHeight;
var offsetTop = shareContent.offsetTop; // The offset of the element from the top
// var rect = shareContent.getBoundingClientRect();
var canvas = document.createElement('canvas'); // establish canvas object
var context = canvas.getContext('2d');
var scaleBy = 3; // Pixel density ( You can also use custom scaling )
canvas.width = width * scaleBy; // here Because of the drawing dom For a fixed width , In the middle , So there's no offset
canvas.height = (height + offsetTop) * scaleBy; // Pay attention to height , Because there is a distance at the top, add the distance from the top , Solve the image height offset problem
canvas.height = height * scaleBy;
// context.translate(0, -offsetTop); // Canvas offset
context.scale(scaleBy, scaleBy);
html2canvas(shareContent, {
logging: true, // Whether to print the log , Default false
taintTest: true, // Check that each image has been loaded
scale: scaleBy, // Added scale Parameters
canvas: canvas, // Customize canvas
width: width, //dom Original width
height: height, //dom Original height
useCORS: true, // Allow cross-domain
onrendered: function(canvas) { // Callback after successful page drawing
var url = canvas.toDataURL("image/png");
// The operation after the image is generated

Image blur resolution

  • Because of the pixel ratio (DPR = Device pixel /CSS Pixels ) The problem of , The screenshot on the computer looks ok , It will be very fuzzy on the mobile phone . When drawing an image, you can enlarge the picture according to the pixel ratio , Define the width of the picture when using , You can also customize the zoom ratio . The bigger the zoom ratio is, the better , Too big can cause problems . The code to calculate the pixel ratio :
function getPixelRatio(context){
var backingStore = context.backingStorePixelRatio ||
context.webkitBackingStorePixelRatio ||
context.mozBackingStorePixelRatio ||
context.msBackingStorePixelRatio ||
context.oBackingStorePixelRatio ||
context.backingStorePixelRatio || 1;
return (window.devicePixelRatio || 1) / backingStore;
  • Try not to use background pictures when drawing , Use it directly img It will be clearer

Picture cross domain problem

Once, wechat avatars were used in the page , Set up useCORS: true Can't show the head image , Set up allowTaint:true You can't use it toDataURL Contaminated canvases may not be exported ;web Front end development resources Q-q-u-n: 767273102 , There are free development tools , Zero basis , Advanced video tutorial , I hope novices don't take detours

  • modify Nginx The configuration file , Because we use it in other parts of the project , So it's inconvenient to modify , References that can be modified :
location ^~ /wechat_image/ {
add_header 'Access-Control-Allow-Origin' "$http_origin" always;
add_header 'Access-Control-Allow-Credentials' 'true' always;
add_header 'Access-Control-Allow-Methods' 'GET, OPTIONS' always;
add_header 'Access-Control-Allow-Headers' 'Accept,Authorization,Cache-Control,Content-Type,DNT,If-Modified-Since,Keep-Alive,Origin,User-Agent,X-Requested-With' always;
  • Turn the picture into base64 Format and set CrossOrigin=“anonymous”, If there is a cache after the attempt, the image still can't be generated normally , We need to splice a random parameter to solve the cache problem ,Android All right , but ios I still can't .
  • Later, I found that it was directly on the wechat avatar img On the label CrossOrigin="anonymous" namely <img class="user-img" th:src="${wxUser.headImgUrl}" alt="" crossOrigin="anonymous" />, The request header of wechat avatar comes with access-control-allow-origin: *,Android and ios It's all right , If you've tried other methods before , You may need to clear the cache , Otherwise Android Will mislead you not to display normally .
  • Recently we found another html2canvas Of options Internal configuration proxy For cross domain url.

Flash problem when generating image replacement page

The first few times generated images , There is no such problem , The last time there was a replacement, the page flashed , Think the picture is too big , I save and compare the pictures of the two activities. It's not , I still don't know exactly , But by first in dom Write an empty img The tag then generates src Replace with img, Judge that the picture will be drawn after loading dom It solved the problem .

css The ellipsis is out of style

html2canvas I won't support it css Style generation ellipsis , Baidu has found a solution , adopt js Replace the ellipsis when judging the height of the parent box

$(".info_text_box").each(function () {
var divH = $(this).height();
var $p = $("p", $(this)).eq(0);
while ($p.outerHeight() > divH) {
$p.html($p.html().replace(/(\s)*([a-zA-Z0-9]+|\W)(\.\.\.)?$/, "..."));

introduce web When the font is not displayed, a picture is generated before the font is displayed

window.onload=function(){} Wait until the page resource is loaded , But in ios China does not support , It turns out that when the font size is larger than 300px The width of different fonts varies greatly , Through the timer to determine the font size to determine whether the font loaded successfully , But most of all because the font file is too slow to load , I gave up using special Fonts

// By judging the width of the font content to judge the completion of the font loading
function fn_fontWatch(fontFamily, cb) {
function fn_gen_span_with_font(font) {
var span=document.createElement('span'); = "display:block;position:absolute;top:-9999px;left:-9999px;font-size:300px;width:auto;height:auto;line-height:normal;margin:0;padding:0;font-variant:normal;white-space:nowrap;font-family:" + font;
span.innerHTML = 'BESbswy';
return span;
var span_default = fn_gen_span_with_font('serif');
var span_default_width = span_default.offsetWidth;
var span_font = fn_gen_span_with_font(fontFamily + ',serif');
var fn_check_loop = function() {
if(span_default_width !== span_font.offsetWidth){
} else {

Other questions

  • An activity needs to judge the order of entering the page ,html2canvas By traversing dom Drawing pictures , When generating images, in addition to js It's going to be done again , Causes a similar refresh page record order , The last order is through ajax Request acquisition solves the problem ;
  • html2canvas Only the visible content in the page will be intercepted , Set up display: nonevisibility:hidden The element of is not intercepted
  • There are a few changes in the text when the image is generated , Like Android numbers 1 The change is especially obvious , And the position of the text is a little bit down , The reason I didn't find , The impact is not big , I haven't solved it yet ;
本文为[JavaScript language]所创,转载请带上原文链接,感谢

  1. [front end -- JavaScript] knowledge point (IV) -- memory leakage in the project (I)
  2. This mechanism in JS
  3. Vue 3.0 source code learning 1 --- rendering process of components
  4. Learning the realization of canvas and simple drawing
  5. gin里获取http请求过来的参数
  6. vue3的新特性
  7. Get the parameters from HTTP request in gin
  8. New features of vue3
  9. vue-cli 引入腾讯地图(最新 api,rocketmq原理面试
  10. Vue 学习笔记(3,免费Java高级工程师学习资源
  11. Vue 学习笔记(2,Java编程视频教程
  12. Vue cli introduces Tencent maps (the latest API, rocketmq)
  13. Vue learning notes (3, free Java senior engineer learning resources)
  14. Vue learning notes (2, Java programming video tutorial)
  15. 【Vue】—props属性
  16. 【Vue】—创建组件
  17. [Vue] - props attribute
  18. [Vue] - create component
  19. 浅谈vue响应式原理及发布订阅模式和观察者模式
  20. On Vue responsive principle, publish subscribe mode and observer mode
  21. 浅谈vue响应式原理及发布订阅模式和观察者模式
  22. On Vue responsive principle, publish subscribe mode and observer mode
  23. Xiaobai can understand it. It only takes 4 steps to solve the problem of Vue keep alive cache component
  24. Publish, subscribe and observer of design patterns
  25. Summary of common content added in ES6 + (II)
  26. No.8 Vue element admin learning (III) vuex learning and login method analysis
  27. Write a mini webpack project construction tool
  28. Shopping cart (front-end static page preparation)
  29. Introduction to the fluent platform
  30. Webpack5 cache
  31. The difference between drop-down box select option and datalist
  32. CSS review (III)
  33. Node.js学习笔记【七】
  34. Node.js learning notes [VII]
  35. Vue Router根据后台数据加载不同的组件(思考-&gt;实现-&gt;不止于实现)
  36. Vue router loads different components according to background data (thinking - & gt; Implementation - & gt; (more than implementation)
  37. 【JQuery框架,Java编程教程视频下载
  38. [jQuery framework, Java programming tutorial video download
  39. Vue Router根据后台数据加载不同的组件(思考-&gt;实现-&gt;不止于实现)
  40. Vue router loads different components according to background data (thinking - & gt; Implementation - & gt; (more than implementation)
  41. 【Vue,阿里P8大佬亲自教你
  42. 【Vue基础知识总结 5,字节跳动算法工程师面试经验
  43. [Vue, Ali P8 teaches you personally
  44. [Vue basic knowledge summary 5. Interview experience of byte beating Algorithm Engineer
  45. 【问题记录】- 谷歌浏览器 Html生成PDF
  46. [problem record] - PDF generated by Google browser HTML
  47. 【问题记录】- 谷歌浏览器 Html生成PDF
  48. [problem record] - PDF generated by Google browser HTML
  49. 【JavaScript】查漏补缺 —数组中reduce()方法
  50. [JavaScript] leak checking and defect filling - reduce() method in array
  51. 【重识 HTML (3),350道Java面试真题分享
  52. 【重识 HTML (2),Java并发编程必会的多线程你竟然还不会
  53. 【重识 HTML (1),二本Java小菜鸟4面字节跳动被秒成渣渣
  54. [re recognize HTML (3) and share 350 real Java interview questions
  55. [re recognize HTML (2). Multithreading is a must for Java Concurrent Programming. How dare you not
  56. [re recognize HTML (1), two Java rookies' 4-sided bytes beat and become slag in seconds
  57. 【重识 HTML ,nginx面试题阿里
  58. 【重识 HTML (4),ELK原来这么简单
  59. [re recognize HTML, nginx interview questions]
  60. [re recognize HTML (4). Elk is so simple