function onDownload (data, type, name ) {
const blob = new Blob ([data], { type });
const url = window .URL .createObjectURL (blob);
const link = document .createElement ('a' );
link.href = url;
link.style .display = 'none' ;
link.setAttribute ('download' , name);
document .body .appendChild (link);
link.click ();
URL .revokeObjectURL (url);
document .body .removeChild (link);
Blob 对象表示一个不可变、原始数据的类文件对象。它的数据可以按文本或二进制的格式进行读取,也可以转换成 ReadableStream 来用于数据操作。
准备基础的图形绘制
准备基础的图形绘制,绘制出来几个小方块(不了解的可以往前面几篇文章翻翻)
<!DOCTYPE html >
<html lang ="en" >
<meta charset ="UTF-8" >
<meta http-equiv ="X-UA-Compatible" content ="IE=edge" >
<meta name ="viewport" content ="width=device-width, initial-scale=1.0" >
<title > Document</title >
<style >
#container {
width : 500px ;
margin : 50px auto 0 ;
</style >
</head >
<div id ="container" >
</div >
</body >
</html >
<script src ="https://d3js.org/d3.v5.min.js" > </script >
<script >
const width = 500 ;
const height = 500 ;
const svg = d3.select ('#container' )
.append ('svg' )
.attr ('width' , width)
.attr ('height' , width);
const container = svg.append ('g' );
const data = [
{ id : 1 , fill : 'black' , x : 10 , y : 10 },
{ id : 2 , fill : 'black' , x : 50 , y : 50 },
{ id : 3 , fill : 'black' , x : 100 , y : 70 },
{ id : 4 , fill : 'black' , x : 20 , y : 100 }
draw ();
function draw () {
const update = container.selectAll ('rect' )
.data (data, d => d.id );
update.attr ('x' , (d, idx ) => d.x )
.attr ('y' , (d, idx ) => d.y )
.attr ('fill' , (d ) => d.fill )
const enter = update.enter ();
const exit = update.exit ();
enter.append ('rect' )
.attr ('width' , 20 )
.attr ('height' , 20 )
.attr ('id' , d => d.id )
.attr ('x' , (d, idx ) => d.x )
.attr ('y' , (d, idx ) => d.y )
.attr ('fill' , (d ) => d.fill )
.attr ('stroke' , 'blue' )
.attr ('strokeWidth' , 1 )
exit.remove ()
</script >
导出svg图片
用d3js
绘制的svg导出后缀名是.svg
的, 需要怎么做呢?
使用XMLSerializer 的serializeToString()
方法返回 DOM 子树序列化后的字符串。
用法示例(MDN):
var s = new XMLSerializer ();
var d = document ;
var str = s.serializeToString (d);
saveXML (str);
咱们也只需要把svg放进serializeToString
是不是就行了呢?
代码如下:
function onDownload (data, type, name ) {
const blob = new Blob ([data], { type });
const url = window .URL .createObjectURL (blob);
const link = document .createElement ('a' );
link.href = url;
link.style .display = 'none' ;
link.setAttribute ('download' , name);
document .body .appendChild (link);
link.click ();
URL .revokeObjectURL (url);
document .body .removeChild (link);
function onSaveSvg () {
const svg = document .querySelector ('svg' );
const source = new XMLSerializer ().serializeToString (svg);
onDownload (source, 'text/xml' , 'test.svg' );
效果图如下:
解释下为啥type类型会传text/xml
SVG 是使用 XML 来描述二维图形和绘图程序的语言。
导出除了svg外的格式
.svg
导出可以看到还是蛮省劲的, 那么非.svg
得格式图片该怎么导出? 可以不可以使用相同得方法呢?显然是不可以得,咱们借助canvas
得toDataURL
进行导出。
文件类型 常见MIME 类型列表 developer.mozilla.org/zh-CN/docs/…
function getPixelRatio (context ) {
const backingStore = context.backingStorePixelRatio
|| context.webkitBackingStorePixelRatio
|| context.mozBackingStorePixelRatio
|| context.msBackingStorePixelRatio
|| context.oBackingStorePixelRatio
|| context.backingStorePixelRatio || 1 ;
return (window .devicePixelRatio || 1 ) / backingStore;
function onSavePng () {
const svgDom = document .querySelector ('svg' );
const format = 'png'
const svgString = new XMLSerializer ().serializeToString (svgDom);
const canvas = document .createElement ('canvas' );
const ctx = canvas.getContext ('2d' );
const ratio = getPixelRatio (ctx);
const w = window .innerWidth ;
const h = window .innerHeight ;
const ratioW = canvas.width || w * ratio;
const ratioH = canvas.height || h * ratio;
const domURL = this .URL || this .webkitURL || this ;
const img = new Image (ratioW, ratioH);
const svg = new Blob ([svgString], { type : 'image/svg+xml;charset=utf-8' });
const url = domURL.createObjectURL (svg);
img.src = url;
img.onload = function on () {
ctx.drawImage (img, 0 , 0 );
const png = canvas.toDataURL (`image/${format} ` );
domURL.revokeObjectURL (png);
const a = document .createElement ('a' );
a.setAttribute ('download' , `test.${format} ` );
a.setAttribute ('href' , png);
a.style .display = 'none' ;
document .body .appendChild (a);
a.click ();
a.remove ();
包含导出svg、png、jpg
<!DOCTYPE html >
<html lang ="en" >
<meta charset ="UTF-8" >
<meta http-equiv ="X-UA-Compatible" content ="IE=edge" >
<meta name ="viewport" content ="width=device-width, initial-scale=1.0" >
<title > Document</title >
<style >
#container {
width : 500px ;
margin : 50px auto 0 ;
</style >
</head >
<div id ="container" >
<button onclick ="onSaveSvg()" > 保存svg图片 </button >
<button onclick ="onSaveImage('png')" > 保存png图片 </button >
<button onclick ="onSaveImage('jpg')" > 保存jpg图片 </button >
</div >
</body >
</html >
<script src ="https://d3js.org/d3.v5.min.js" > </script >
<script >
const width = 500 ;
const height = 500 ;
const svg = d3.select ('#container' )
.append ('svg' )
.attr ('width' , width)
.attr ('height' , width);
const container = svg.append ('g' );
const data = [
{ id : 1 , fill : 'black' , x : 10 , y : 10 },
{ id : 2 , fill : 'black' , x : 50 , y : 50 },
{ id : 3 , fill : 'black' , x : 100 , y : 70 },
{ id : 4 , fill : 'black' , x : 20 , y : 100 }
draw ();
function draw () {
const update = container.selectAll ('rect' )
.data (data, d => d.id );
update.attr ('x' , (d, idx ) => d.x )
.attr ('y' , (d, idx ) => d.y )
.attr ('fill' , (d ) => d.fill )
const enter = update.enter ();
const exit = update.exit ();
enter.append ('rect' )
.attr ('width' , 20 )
.attr ('height' , 20 )
.attr ('id' , d => d.id )
.attr ('x' , (d, idx ) => d.x )
.attr ('y' , (d, idx ) => d.y )
.attr ('fill' , (d ) => d.fill )
.attr ('stroke' , 'blue' )
.attr ('strokeWidth' , 1 )
exit.remove ()
function onDownload (data, type, name ) {
const blob = new Blob ([data], { type });
const url = window .URL .createObjectURL (blob);
const link = document .createElement ('a' );
link.href = url;
link.style .display = 'none' ;
link.setAttribute ('download' , name);
document .body .appendChild (link);
link.click ();
URL .revokeObjectURL (url);
document .body .removeChild (link);
function onSaveSvg () {
const svg = document .querySelector ('svg' );
const source = new XMLSerializer ().serializeToString (svg);
onDownload (source, 'text/xml' , 'test.svg' );
function getPixelRatio (context ) {
const backingStore = context.backingStorePixelRatio
|| context.webkitBackingStorePixelRatio
|| context.mozBackingStorePixelRatio
|| context.msBackingStorePixelRatio
|| context.oBackingStorePixelRatio
|| context.backingStorePixelRatio || 1 ;
return (window .devicePixelRatio || 1 ) / backingStore;
function onSaveImage (format ) {
const svgDom = document .querySelector ('svg' );
const svgString = new XMLSerializer ().serializeToString (svgDom);
const canvas = document .createElement ('canvas' );
const ctx = canvas.getContext ('2d' );
const ratio = getPixelRatio (ctx);
const w = window .innerWidth ;
const h = window .innerHeight ;
const ratioW = canvas.width || w * ratio;
const ratioH = canvas.height || h * ratio;
const domURL = this .URL || this .webkitURL || this ;
const img = new Image (ratioW, ratioH);
const svg = new Blob ([svgString], { type : 'image/svg+xml;charset=utf-8' });
const url = domURL.createObjectURL (svg);
img.src = url;
img.onload = function on () {
ctx.drawImage (img, 0 , 0 );
const png = canvas.toDataURL (`image/${format} ` );
domURL.revokeObjectURL (png);
const a = document .createElement ('a' );
a.setAttribute ('download' , `test.${format} ` );
a.setAttribute ('href' , png);
a.style .display = 'none' ;
document .body .appendChild (a);
a.click ();
a.remove ();
</script >
通过这篇文章, 相信尼对导出有了一个新得认识。
BigYe程普
React.js
d3.js
1.0w
Benbinbin
数据可视化
d3.js
1.0w
ssthouse
数据可视化
d3.js
1022
ssthouse
Canvas
d3.js