请教前端实现获取dom元素快照的方法

sicun
  • 69

我在做自定义大屏, 一个大屏是有若干个iframe构成, 大屏列表展示的时候想显示下每一个大屏的缩略图, 所以我就想在大屏编辑预览时获取大屏dom元素的快照, 作为这条数据的缩略图显示.

试过了html2canvas和domtoimage, 对于有iframe的都处理不好.

又网上找到了这个rasterizeHTML.js, 据说可以解决iframe的问题, 但是用的时候老是提示我
Blocked script execution in 'about:srcdoc' because the document's frame is sandboxed and the 'allow-scripts' permission is not set.. 我每个iframe都配置的有allow-scripts的:

  <iframe
    id={iframe_${payload.name}}
    title={iframe_${payload.name}}
    height="100%"
    width="100%"
    sandbox="allow-scripts allow-same-origin allow-popups"
    frameBorder="0"
    srcDoc={html}
  />
  
  

有没有大佬做过类似的功能, 请给我点思路或者建议.

回复
阅读 1.7k
4 个回答

我确实做过,不过一言难尽。

方法是:每个DOM转存为JSON,iframe中的DOM也转为JSON,通过postMessage发送到外层页面,外层页面进行数据收集。
得到JSON列表再在一个新的iframe中渲染出来


DOM转JSON可以参考:https://www.npmjs.com/package...

iframe url 响应头部增加下面的配置试试,参考文章

X-Content-Security-Policy: sandbox; default-src 'none'; img-src 'self'; style-src 'self';

大屏可以考虑针对性地开发浏览器插件进行增强.

谢谢各位热心的大佬, 昨天我摸索的解决方案是:
逐个把每一个iframe(一个iframe是一个大屏的组件)用html2canvas转成图片, 然后用这个图片替换掉这个组件的Html代码, 这样可以保持这个组件大屏的位置不变. 最后把含有多个组件图片的大屏转成一张图.
具体代码是:

snapshot = () => {
 const {changeSnapshot} = this.props;
 const {components=[]} = this.state;
 const names = components.map(i => i.name);
 const name = names.shift();
 function generateImage(item){
 const domId = `#iframe_${item}`;
 const dom = document.querySelector(domId).contentWindow.document.querySelector('html')
 html2canvas(dom, {allowTaint: true, taintTest: false}).then(canvas=>{
 const parent = $(domId).parent();
 const width = parent.width();
 const height = parent.height();
 const image = canvas.toDataURL('image/png');
 const imgTag = document.createElement('img');
 imgTag.src = image;
 imgTag.style.width = `${width}px`;
 imgTag.style.height = `${height}px`;
 
 parent.html('').append(imgTag);
 const nextName = names.shift();
 if(nextName) generateImage(nextName);
 else{
 const box = document.querySelector('#dashboardContainer');
 const canvas1 = document.createElement('canvas');
 canvas1.width = `${box.offsetWidth}`;
 canvas1.height = `${box.offsetHeight}`;
 canvas1.getContext("2d").clearRect(0, 0, box.offsetWidth, box.offsetHeight);
 rasterizeHTML.drawHTML(box.innerHTML, canvas1).then( ()=> {
 const image1 = canvas1.toDataURL('image/png');
 const imgTag1 = document.createElement('img');
 imgTag1.src = image1;
 box.innerHTML = '';
 // box.appendChild(canvas1)
 box.appendChild(imgTag1)
 changeSnapshot(image1);
 }, (e) => {
 console.log(e);
 });
 }
 })
 }
 if(name) generateImage(name);
 }
你知道吗?

宣传栏