Skip to content

Latest commit

 

History

History
108 lines (83 loc) · 3.59 KB

实战:将DOM节点转换为图片.md

File metadata and controls

108 lines (83 loc) · 3.59 KB

将DOM节点转换为图片

在这个案例里我们会实现将页面中的一部分DOM节点转换为图片并下载到本地的效果,原理如下:

1.利用SVGforeignObject元素能嵌入html元素的特性,将要导出的DOM节点嵌入到SVG中;

2.通过img元素渲染svg

3.通过canvas绘制img,调用导出方法导出为blobdata:url数据;

4.通过a标签下载到本地;

首先来一段简单的DOM结构作为要导出的节点:

<div
     id="el"
     style="
            border: 1px solid lightcoral;
            padding: 10px;
            width: 250px;
            height: 250px;
            background-color: #fff;
            "
     >
    <h1>foreignObject</h1>
    <p>
        SVG中的<span style="font-weight: bold; color: lightblue"
                   >foreignObject</span
        >元素允许包含来自不同的 XML 命名空间的元素。在浏览器的上下文中,很可能是
        <span style="background-color: lightseagreen; color: #fff"
              >XHTML / HTML</span
            ></p>
</div>

image-20231027171305068

然后我们将这个节点克隆一下,并拼接成SVG字符串:

const el = document.getElementById('el')
// 获取节点大小
const rect = el.getBoundingClientRect()
// 克隆一份
const clone = el.cloneNode(true)
// 添加xhtml命名空间
clone.setAttribute('xmlns', 'http://www.w3.org/1999/xhtml')
// 拼接svg字符串
const svgStr = `<svg xmlns="http://www.w3.org/2000/svg" width="${rect.width}" height="${rect.height}">
	<foreignObject width="${rect.width}" height="${rect.height}">${clone.outerHTML}</foreignObject>
</svg>`

首先获取了一下要导出节点的大小,然后设置到svg节点上,接下来我们还给克隆的节点添加了命名空间的属性,这个是必要的,否则最后导出将是空白的,最后我们将被导出的DOM节点的html字符串拼接到foreignObject标签中即可。

接下来使用Blob对象将svg字符串转换为blob数据:

const blob = new Blob([svgStr], {
    type: 'image/svg+xml'
})

因为img标签并不能直接渲染blob数据,所以我们还要把blob转换为data:url数据:

const reader = new FileReader()
reader.onload = evt => {
    // evt.target.result
}
reader.readAsDataURL(blob)

现在就可以像渲染一张普通的图片到canvas上一样:

const img = new Image()
img.onload = () => {
    ctx.drawImage(img, 0, 0)
}
img.src = svgUrl

image-20231110095045837

可以看到已经在canvas中把DOM节点绘制出来了,最后让我们调用canvas的导出方法导出再下载就行了:

const imgData = canvas.toDataURL()
downloadFile(imgData, '图片.png')

const downloadFile = (file, fileName) => {
    const a = document.createElement('a')
    a.href = file
    a.download = fileName
    a.click()
}

image-20231110095200431

总结

本节介绍了一种非常简单的方式来将DOM节点转换为图片,当然,以上实现是非常粗糙的,实际情况中的DOM节点可能非常复杂,有各种情况需要处理,比如存在外联样式、伪元素、字体文件、图片等等,所以最好选择使用html2canvasdom-to-image-more等库来实现。

本节示例地址:domToImg