面试官:请用纯 JS 实现,将 HTML 网页转换为图像

简介: 在工作时,需要实现一个功能:把一个HTML网页的转换为图像。我想到的第一个想法是使用第三方库,但像dom-to-image或使用Chrome Headless,如Puppeteer。那如何使用纯Javascript解决这种需求呢?

在工作时,需要实现一个功能:把一个HTML网页的转换为图像。我想到的第一个想法是使用第三方库,但像dom-to-image或使用Chrome Headless,如Puppeteer。那如何使用纯Javascript解决这种需求呢?

让我们尝试在不使用任何库的情况下实现这一点。

使用Canvas将HTML网页转换为图像

由于安全原因,我们不能直接将HTML绘制到Canvas中。我们将采用另一种更安全的方法。

  1. 创建包含渲染内容的SVG图像
<svg xmlns="http://www.w3.org/2000/svg" width="200" height="200">
</svg>
  1. 在SVG中插入一个<foreignObject>元素,它将包含HTML
<svg xmlns="http://www.w3.org/2000/svg" width="200" height="200">
    <foreignObject width="100%" height="100%">
    </foreignObject>
</svg>
  1. <foreignObject>节点内添加XHTML内容
<svg xmlns="http://www.w3.org/2000/svg" width="200" height="200">
    <foreignObject width="100%" height="100%">
        <div xmlns="http://www.w3.org/1999/xhtml">. 
          <style>em{color:red;}</style>
             Hey there...
        </div>
    </foreignObject>
</svg>
  1. 创建 img 对象,并将 img 的src 属性设置为该图像的data url:
const tempImg = document.createElement('img')
tempImg.src = 'data:image/svg+xml,' + encodeURIComponent('<svg xmlns="http://www.w3.org/2000/svg" width="100" height="100"><foreignObject width="100%" height="100%"><div xmlns="http://www.w3.org/1999/xhtml">Hey there...</div></foreignObject></svg>')
  1. 将此图像绘制到画布上,并设置画布为img 对象的src属性值:
const newImg = document.createElement('img')
newImg.src = 'data:image/svg+xml,' + encodeURIComponent('<svg xmlns="http://www.w3.org/2000/svg" width="100" height="100"><foreignObject width="100%" height="100%"><div xmlns="http://www.w3.org/1999/xhtml">Hey there...</div></foreignObject></svg>')

// 对图像添加事件监听
newImg.addEventListener('load', onNewImageLoad)
// 将图像绘制到画布并设置img.src
function onNewImageLoad(e){
  ctx.drawImage(e.target, 0, 0)
  targetImg.src = canvas.toDataURL()
}

完整代码

<html>
<head>
    <meta charset="UTF-8" />
    <style>
    body {
        display: flex;
        flex-flow: column wrap;
        align-items: center;
        justify-content: flex-start;

        background-image: linear-gradient(0, rgb(169, 144, 177), rgb(205, 169, 223));
    }

    h1 {
        margin-top: 5vh;
        margin-bottom: 1vh;

        color: white;
    }

    p {
        margin: 0;
        color: white;
    }
    </style>
</head>

<body>
    <h1>Convert HTML into Image!<h1 />
   <script>
        const { body } = document;
        const canvas = document.createElement("canvas");
        const ctx = canvas.getContext("2d");
        canvas.width = canvas.height = 100;

        const newImg = document.createElement("img");
        newImg.addEventListener("load", onNewImageLoad);
        newImg.src =
            "data:image/svg+xml," +
            encodeURIComponent(
                '<svg xmlns="http://www.w3.org/2000/svg" width="100" height="100"><foreignObject width="100%" height="100%"><div xmlns="http://www.w3.org/1999/xhtml"> Hey there...</div></foreignObject></svg>'
            );

        const targetImg = document.createElement("img");
        body.appendChild(targetImg);

        function onNewImageLoad(e) {
            ctx.drawImage(e.target, 0, 0);
            targetImg.src = canvas.toDataURL();
        }
  </script>
</body>

</html>

为什么使用SVG和Canvas是安全的?

SVG图像的实现有很大的限制,因为我们不允许SVG图像加载外部资源,即使是出现在同一个域上的资源。不允许在SVG图像中编写脚本,无法从其他脚本访问SVG图像的DOM, SVG图像中的DOM元素不能接收输入事件。因此,无法将特权信息加载到表单控件中(例如<input type="file">中的完整路径)并呈现它。

从安全性的角度来看,脚本不能直接接触渲染到画布的DOM节点,这一限制非常重要。

相关文章
|
25天前
|
存储 移动开发 前端开发
HTML基础知识:构建网页的基石
【10月更文挑战第11天】HTML基础知识:构建网页的基石
55 0
|
2天前
|
前端开发 JavaScript 安全
HTML+CSS+JS密码灯登录表单
通过结合使用HTML、CSS和JavaScript,我们创建了一个带有密码强度指示器的登录表单。这不仅提高了用户体验,还帮助用户创建更安全的密码。希望本文的详细介绍和代码示例能帮助您在实际项目中实现类似功能,提升网站的安全性和用户友好性。
8 3
|
5天前
|
JavaScript
JS鼠标框选并删除HTML源码
这是一个js鼠标框选效果,可实现鼠标右击出现框选效果的功能。右击鼠标可拖拽框选元素,向下拖拽可实现删除效果,简单实用,欢迎下载
13 4
|
4天前
|
移动开发 HTML5
html5+three.js公路开车小游戏源码
html5公路开车小游戏是一款html5基于three.js制作的汽车开车小游戏源代码,在公路上开车网页小游戏源代码。
18 0
html5+three.js公路开车小游戏源码
|
28天前
|
数据安全/隐私保护 C++
【HTML】构建网页的基石
本文介绍了HTML的基本概念和常用标签,包括HTML文件的基本结构、常见标签(如标题、段落、换行、图片、超链接等)、表格与表单的使用方法,以及无语义标签div和span的特性。通过具体示例展示了如何在VS Code中快速生成HTML框架及各标签的应用场景,帮助初学者快速掌握HTML的基础知识。
45 1
【HTML】构建网页的基石
|
12天前
|
JSON 移动开发 数据格式
html5+css3+js移动端带歌词音乐播放器代码
音乐播放器特效是一款html5+css3+js制作的手机移动端音乐播放器代码,带歌词显示。包括支持单曲循环,歌词显示,歌曲搜索,音量控制,列表循环等功能。利用json获取音乐歌单和歌词,基于html5 audio属性手机音乐播放器代码。
62 6
|
27天前
|
XML 前端开发 JavaScript
前端开发进阶:从HTML到React.js
【10月更文挑战第9天】前端开发进阶:从HTML到React.js
|
1月前
|
JavaScript 前端开发
电话号码正则表达式 代码 javascript+html,JS正则表达式判断11位手机号码
电话号码正则表达式 代码 javascript+html,JS正则表达式判断11位手机号码
82 1
|
27天前
|
JavaScript 前端开发
JavaScript 与 HTML 的结合
JavaScript 与 HTML 的结合
15 0
|
3月前
|
存储 Java
【IO面试题 四】、介绍一下Java的序列化与反序列化
Java的序列化与反序列化允许对象通过实现Serializable接口转换成字节序列并存储或传输,之后可以通过ObjectInputStream和ObjectOutputStream的方法将这些字节序列恢复成对象。