【问题标题】:SVG tag convert to PNG image with downloadSVG 标签通过下载转换为 PNG 图像
【发布时间】:2018-11-19 10:20:39
【问题描述】:

我使用 D3 图表来显示树形图,所以现在可以正常工作,但我需要将此 svg 聊天作为图像下载。

图表html如:

<svg width="960" height="30000">
    <g transform="translate(120,20)">
        <path>......</path>
        <path>......</path>
        <path>......</path>
         ......
         ...... 
    </g>
</svg>

我的 svg html 更长,所以我只放代码结构。

我使用此代码进行下载:

d3.select('#saveButton').on('click', function(){
        // alert('test');
        var svgString = getSVGString(svg.node());
        // console.log(svgString);
        svgString2Image( svgString, 2*width, 2*height, 'png', save ); // passes Blob and filesize String to the callback

        function save( dataBlob, filesize ){
            saveAs( dataBlob, 'D3 vis exported to PNG.png' ); // FileSaver.js function
        }
    });

请告诉我如何下载 svg 图表作为图像。

【问题讨论】:

标签: javascript jquery svg canvas


【解决方案1】:

下一个链接可以很好地解决您的问题。 Solution

它包含两个主要功能。

  1. SVG 字符串
  2. 字符串到图像

我认为您使用的是我刚刚添加的相同代码,因为您可以使用保存下载功能。这里的事情是你的代码还有什么。如您所见,此代码实际上下载了 png 最终结果。让我们从这里开始,为您找到解决方案。

// Let's create a mock visualization
var width = 300, height = 300;
var circleSizeMax = 15;
var rMax = Math.min(width,height)/2 - circleSizeMax;

var radius 	= d3.scale.linear().range([0,rMax]);
var angle 	= d3.scale.linear().range([0,2*Math.PI]);
var size 	= d3.scale.linear().range([0,circleSizeMax]);
var color 	= d3.scale.ordinal().range(['#fcfb3c','#fcf900','#ff825a','#ffd2cb','#71d362','#ffd16f','#ff3d5d','#ff7218','#04b3f3','#bce5ac','#6e0215','#69D2E7','#A7DBDB','#E0E4CC','#F38630','#E94C6F','#542733','#5A6A62','#C6D5CD','#DB3340','#E8B71A','#F7EAC8','#1FDA9A','#588C73','#F2E394','#F2AE72','#D96459','#D0C91F','#85C4B9','#008BBA','#DF514C','#00C8F8','#59C4C5','#FFC33C','#FBE2B4','#5E412F','#FCEBB6','#78C0A8','#F07818','#DE4D4E','#DA4624','#DE593A','#FFD041','#B1EB00','#53BBF4','#FF85CB','#FF432E','#354458','#3A9AD9','#29ABA4','#E9E0D6','#4298B5','#ADC4CC','#92B06A','#E19D29','#BCCF02','#5BB12F','#73C5E1','#9B539C','#FFA200','#00A03E','#24A8AC','#0087CB','#260126','#59323C','#F2EEB3','#BFAF80','#BFF073','#0DC9F7','#7F7F7F','#F05B47','#3B3A35','#20457C','#5E3448','#FB6648','#E45F56','#A3D39C','#7ACCC8','#4AAAA5','#DC2742','#AFA577','#ABA918','#8BAD39','#F2671F','#C91B26','#9C0F5F','#60047A','#0F5959','#17A697','#638CA6','#8FD4D9','#83AA30','#1499D3','#4D6684','#3D3D3D','#333333','#424242','#00CCD6','#EFEFEF','#CCC51C','#FFE600','#F05A28','#B9006E','#F17D80','#737495','#68A8AD','#C4D4AF']);
var x = function(d) { return radius( d.r ) * Math.cos( angle( d.angle ) ); };
var y = function(d) { return radius( d.r ) * Math.sin( angle( d.angle ) ); };

var svg = d3.select('body').append('svg')
	.attr('width', width)
	.attr('height',height);

var chart = svg.append('g').attr('transform','translate('+[width/2,height/2]+')');

var data = d3.range(150).map( function(d) { return {r: Math.random(), angle: Math.random(), size: Math.random() }; });

chart.selectAll('cirle')
	.data(data).enter()
	.append('circle')
	.attr('class','blendCircle')
	.attr({
		cx: x,
		cy: y,
		r: function(d) { return size(d.size); },
		fill: function(d,i) { return color(i); }
	});


// Set-up the export button
d3.select('#saveButton').on('click', function(){
	var svgString = getSVGString(svg.node());
	svgString2Image( svgString, 2*width, 2*height, 'png', save ); // passes Blob and filesize String to the callback

	function save( dataBlob, filesize ){
		saveAs( dataBlob, 'D3 vis exported to PNG.png' ); // FileSaver.js function
	}
});

// Below are the functions that handle actual exporting:
// getSVGString ( svgNode ) and svgString2Image( svgString, width, height, format, callback )
function getSVGString( svgNode ) {
	svgNode.setAttribute('xlink', 'http://www.w3.org/1999/xlink');
	var cssStyleText = getCSSStyles( svgNode );
	appendCSS( cssStyleText, svgNode );

	var serializer = new XMLSerializer();
	var svgString = serializer.serializeToString(svgNode);
	svgString = svgString.replace(/(\w+)?:?xlink=/g, 'xmlns:xlink='); // Fix root xlink without namespace
	svgString = svgString.replace(/NS\d+:href/g, 'xlink:href'); // Safari NS namespace fix

	return svgString;

	function getCSSStyles( parentElement ) {
		var selectorTextArr = [];

		// Add Parent element Id and Classes to the list
		selectorTextArr.push( '#'+parentElement.id );
		for (var c = 0; c < parentElement.classList.length; c++)
				if ( !contains('.'+parentElement.classList[c], selectorTextArr) )
					selectorTextArr.push( '.'+parentElement.classList[c] );

		// Add Children element Ids and Classes to the list
		var nodes = parentElement.getElementsByTagName("*");
		for (var i = 0; i < nodes.length; i++) {
			var id = nodes[i].id;
			if ( !contains('#'+id, selectorTextArr) )
				selectorTextArr.push( '#'+id );

			var classes = nodes[i].classList;
			for (var c = 0; c < classes.length; c++)
				if ( !contains('.'+classes[c], selectorTextArr) )
					selectorTextArr.push( '.'+classes[c] );
		}

		// Extract CSS Rules
		var extractedCSSText = "";
		for (var i = 0; i < document.styleSheets.length; i++) {
			var s = document.styleSheets[i];
			
			try {
			    if(!s.cssRules) continue;
			} catch( e ) {
		    		if(e.name !== 'SecurityError') throw e; // for Firefox
		    		continue;
		    	}

			var cssRules = s.cssRules;
			for (var r = 0; r < cssRules.length; r++) {
				if ( contains( cssRules[r].selectorText, selectorTextArr ) )
					extractedCSSText += cssRules[r].cssText;
			}
		}
		

		return extractedCSSText;

		function contains(str,arr) {
			return arr.indexOf( str ) === -1 ? false : true;
		}

	}

	function appendCSS( cssText, element ) {
		var styleElement = document.createElement("style");
		styleElement.setAttribute("type","text/css"); 
		styleElement.innerHTML = cssText;
		var refNode = element.hasChildNodes() ? element.children[0] : null;
		element.insertBefore( styleElement, refNode );
	}
}


function svgString2Image( svgString, width, height, format, callback ) {
	var format = format ? format : 'png';

	var imgsrc = 'data:image/svg+xml;base64,'+ btoa( unescape( encodeURIComponent( svgString ) ) ); // Convert SVG string to data URL

	var canvas = document.createElement("canvas");
	var context = canvas.getContext("2d");

	canvas.width = width;
	canvas.height = height;

	var image = new Image();
	image.onload = function() {
		context.clearRect ( 0, 0, width, height );
		context.drawImage(image, 0, 0, width, height);

		canvas.toBlob( function(blob) {
			var filesize = Math.round( blob.length/1024 ) + ' KB';
			if ( callback ) callback( blob, filesize );
		});

		
	};

	image.src = imgsrc;
}
<!DOCTYPE html>
<html lang="en">

<head>
	<title>How to properly export SVG D3 visualization to PNG or JPEG</title>
  <meta charset="utf-8">
  <script src="https://cdn.rawgit.com/eligrey/canvas-toBlob.js/f1a01896135ab378aa5c0118eadd81da55e698d8/canvas-toBlob.js"></script>
	 <script src="https://cdn.rawgit.com/eligrey/FileSaver.js/e9d941381475b5df8b7d7691013401e171014e89/FileSaver.min.js"></script>
	<script src="https://d3js.org/d3.v3.min.js"></script>
 	<style type="text/css">
 		.blendCircle {
 			mix-blend-mode: multiply;
 		}
 	</style>
 </head>

<body>
<div>
<button id='saveButton'>Export my D3 visualization to PNG</button>
</div>
</body>

</html>

【讨论】:

  • 感谢您的回复。我使用了与您提到的相同的代码,但仍然没有运气。我检查了我的控制台,但在控制台中没有任何错误,但下载文件不起作用。如果您对此有任何想法,请帮助我。
  • 我很乐意为您提供帮助。 Pliss 提供您的代码或实时视图。
  • 对不起,伙计。代码太长,我在本地服务器上工作。如果您想要 html,那么我将添加我的问题。但是,如果您有任何演示链接,请通过我。
  • 你可以上传到小提琴。我可以在没有它的情况下调试你的代码/
  • 这是我的小提琴链接,请检查:jsfiddle.net/insystemgrp/m79xqw6d 我将 svg 代码直接放在 html 中,显示在检查元素中。
猜你喜欢
  • 2022-07-05
  • 1970-01-01
  • 2017-07-09
  • 2020-09-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-10-19
  • 1970-01-01
相关资源
最近更新 更多