找回密码
 立即注册

QQ登录

只需一步,快速开始

KevinChen 讲师达人认证 悬赏达人认证 SpreadJS 开发认证
论坛元老   /  发表于:2020-11-23 17:43  /   查看:3992  /  回复:1
本教程是基于原Demo:【HTML元素单元格】修改而来,原Demo演示了讲一个HTML片段渲染到SpreadJS单元格中,有兴趣的小伙伴可以先参考原Demo:https://demo.grapecity.com.cn/Sp ... le/#/demos/htmlCell

之前的Demo中采用了在自定义单元格的paint方法中生成图片,然后调用SpreadJS原生的canvas渲染图片的方式来实现在单元格中显示image,效果如图:
image.png814828185.png
(图中html片段可以通过设置allowCellOverflow = false 来关闭显示)

这个示例的确能解决HTML渲染的问题,但是如果需要打印或者导出PDF时就没办法把渲染的内容导出来了。先说一个前提,SpreadJS的打印和导出PDF,都是“所见即所得”的,也就是说页面上的可视化元素都可以被导出PDF或输送给打印接口。这是SpreadJS的强大的渲染机制支撑起来的功能。
但这里为什么就不灵了呢?

关键问题出在image的渲染机制上。HTML为保证页面渲染的性能,对image元素的加载都是异步的,而输出()结果时SpreadJS会调用相关区域的paint方法,对这一区域执行重绘(这是canvas的机制)。而在重绘期间,image还在等待,这样就会导致输出的结果中看不到image。

那么我们干脆这样改进一下思路:
1、得到HTML片段后,在合适的时间(只要在需要显示到单元格之前)将它转为图片,并完成加载。
2、在图片加载完成的回调中,给单元格设置背景图。
3、通过自定义单元格,让单元格中的value(这里是html片段)不要显示出来。

这里利用了SpreadJS会缓存单元格背景图的机制,让我们的图片在导出时不再丢失。

关键代码如下:

  1. function _html2img(value, style, cell){
  2.                         var svgPattern = '<svg xmlns="http://www.w3.org/2000/svg" width="{0}" height="{1}">' +
  3.                                 '<foreignObject width="100%" height="100%"><div xmlns="http://www.w3.org/1999/xhtml" style="font:{2}">{3}</div></foreignObject></svg>';
  4.                        
  5.                         var w = cell.sheet.getCellRect(cell.row, cell.col).width;
  6.                         var h = cell.sheet.getCellRect(cell.row, cell.col).height;
  7.                         var data = svgPattern.replace("{0}", w).replace("{1}", h).replace("{2}", style.font).replace("{3}", value);
  8.                         var doc = document.implementation.createHTMLDocument("");
  9.                         doc.write(data);
  10.                         // Get well-formed markup
  11.                         data = (new XMLSerializer()).serializeToString(doc.body.children[0]);
  12.                        
  13.                         img = new Image();
  14.                         img.src = 'data:image/svg+xml;base64,'+window.btoa(unescape(encodeURIComponent(data))); // 涉及中文时的转码
  15.                         cell.tag(img);
  16.                         img.onload = function () {
  17.                                 cell.cellType(new RenderHTMLTagCellType());
  18.                                 cell.value(value);
  19.                                 cell.backgroundImageLayout(GC.Spread.Sheets.ImageLayout.center);
  20.                                 cell.backgroundImage(img.src);
  21.                         }
  22.                 }
复制代码
完整实例参考附件。

单元格渲染HTML片段,带打印导出PDF.html

5.81 KB, 下载次数: 221

1 个回复

倒序浏览
KevinChen讲师达人认证 悬赏达人认证 SpreadJS 开发认证
论坛元老   /  发表于:2020-11-24 17:07:42
沙发
补充:
fix了一个小问题,img是异步加载的,所以需要给onload函数加个闭包,以免多次调用时后加载的图片覆盖先加载的。
参考附件Demo。

单元格渲染HTML片段,带打印导出PDF.html

13.96 KB, 下载次数: 248

回复 使用道具 举报
您需要登录后才可以回帖 登录 | 立即注册
返回顶部