민서네집

[d3] d3 chart 를 png 파일로 저장하기. 본문

Javascript

[d3] d3 chart 를 png 파일로 저장하기.

브라이언7 2014. 8. 7. 04:50

Mac Safari 브라우저에서는 다음과 같은 에러가 나면서 d3 chart가 png 파일로 저장되지 않는다.


Cross-origin image load denied by Cross-Origin Resource Sharing policy.


http://blog.chromium.org/2011/07/using-cross-domain-images-in-webgl-and.html


< 참고한 웹사이트 >


Save SVG as PNG

http://bl.ocks.org/mbostock/6466603

SVG to Canvas

http://svgopen.org/2010/papers/62-From_SVG_to_Canvas_and_Back/


JavaScript Canvas Image Conversion

http://davidwalsh.name/convert-canvas-image


Convert SVG to image (JPEG, PNG, etc.) in the browser

http://stackoverflow.com/questions/3975499/convert-svg-to-image-jpeg-png-etc-in-the-browser


convert svg to png


https://cloudconvert.org/svg-to-png


Save SVG as an Image

http://techslides.com/save-svg-as-an-image/


why is this toDataURL line a security error?

http://stackoverflow.com/questions/7279438/why-is-this-todataurl-line-a-security-error


SVG images on a HTML5 Canvas

http://getcontext.net/read/svg-images-on-a-html5-canvas


How to draw SVG on HTML 5 Canvas and why you might want to


Method 1은 에러가 발생함.


Rasterizing an in-document SVG to Canvas

http://stackoverflow.com/questions/8158312/rasterizing-an-in-document-svg-to-canvas


canvas.toDataURL() throws security exception, despite image being local

http://stackoverflow.com/questions/10187306/canvas-todataurl-throws-security-exception-despite-image-being-local


Using Cross-domain images in WebGL and Chrome 13

http://blog.chromium.org/2011/07/using-cross-domain-images-in-webgl-and.html


<!DOCTYPE HTML>
<html xmlns="http://www.w3.org/1999/xhtml">
	<head>
		<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
		<meta http-equiv="X-UA-Compatible" content="IE=edge" />
		<title>SVG Save</title>
		<script type="text/javascript" src="js/base64.js"></script>
		<script src="https://npmcdn.com/imagesloaded@4.1/imagesloaded.pkgd.js"></script>
		<script>
			// http://stackoverflow.com/questions/11524268/atob-not-working-in-ie
			// ie10 이전 버전에서 필요함.
			if (!window.btoa) window.btoa = base64.encode;
			if (!window.atob) window.atob = base64.decode;

			// [출처] http://nytimes.github.io/svg-crowbar/
			// IE 에서 svg-crowbar.js 에서 다음 에러 발생.
			// SCRIPT5007: 'createObjectURL' 속성 값을 가져올 수 없습니다. 개체가 null이거나 정의되지 않았습니다.
			function saveSvg() {

				(function() {
					var e = document.createElement('script');
					if (window.location.protocol === 'https:') {
						e.setAttribute('src', 'https://raw.github.com/NYTimes/svg-crowbar/gh-pages/svg-crowbar.js');
					} else {
						e.setAttribute('src', 'http://nytimes.github.com/svg-crowbar/svg-crowbar.js');
					}
					e.setAttribute('class', 'svg-crowbar');
					document.body.appendChild(e);
				})();
			}

			function savePng() {
				var svg = document.getElementById("svg");
				var canvas = document.getElementById("canvas");

				importSVG(svg, canvas);
			}

			// [출처] http://svgopen.org/2010/papers/62-From_SVG_to_Canvas_and_Back/
			function importSVG(sourceSVG, canvas) {

				// this is just a JavaScript (HTML) image
				var img = new Image();

				img.crossOrigin = 'anonymous';

				// FireFox 에서는 img.onload = function() { }; 구문이 실행이 안되서
				// imagesloaded 라는 라이브러리를 이용했음.
				// [참고] https://github.com/desandro/imagesloaded

				imagesLoaded( img, function() {

					// canvas의 크기를 image의 크기로 만듦.
					canvas.width = img.width;
					canvas.height = img.height;

					var ctx = canvas.getContext('2d');

					// FireFox 에서는 NS_ERROR_NOT_AVAILABLE:  에러가 발생한다.
					// [참고] https://bugzilla.mozilla.org/show_bug.cgi?id=574330
					ctx.drawImage(img, 0, 0);

					var a = document.createElement("a");
					var fileName = document.getElementsByTagName("title")[0].text;
					a.download = fileName + ".png";
					try {
						// IE 브라우저에서는 다음 에러 발생 - SCRIPT5022: DOM Exception: SECURITY_ERR (18)
						a.href = canvas.toDataURL("image/png");
						a.click();
						console.log("a.click()");
					} catch(error) {
						// 팝업 창을 열고 이미지를 표시하고, 사용자가 이미지를 직접 다운로드 받게 한다.
						openNewWindow(img);
						console.log("openNewWindow()");
					}
				});

				// https://developer.mozilla.org/en/XMLSerializer
				svg_xml = (new XMLSerializer()).serializeToString(sourceSVG);

				// http://en.wikipedia.org/wiki/SVG#Native_support
				// https://developer.mozilla.org/en/DOM/window.btoa
				img.src = "data:image/svg+xml;base64," + btoa(svg_xml);
			}

			// IE9 에서 error는 안 나는데, 생성된 image가 보이지 않음. chrome 에서는 잘됨.
			function buttonConvertCanvasToImage() {
				var canvas = document.getElementById("canvas");
				document.body.appendChild(convertCanvasToImage(canvas));
			}

			// Converts canvas to an image
			function convertCanvasToImage(canvas) {
				var image = new Image();
				image.src = canvas.toDataURL("image/png");
				return image;
			}

			function openNewWindow(img) {
				var d = img.src;
				var w = window.open("","_blank","width=800, height=600, scrollbars=yes");
				w.document.write("<p>이미지를 마우스로 우클릭 해서 '다른 이름으로 사진 저장' 메뉴를 선택해 주세요.</p><img src='"+d+"' alt='from canvas'/>");
			}
		</script>
		<script src="//d3js.org/d3.v3.min.js" charset="utf-8"></script>
		<script>
			/* d3 그리는 스크립트 */
		</script>
		<style>
			rect:hover {
				fill: lime;
				opacity: 0.65;
			}
			#tooltip {
				pointer-event: none;
			}
			.mark {
				pointer-event: none;
			}
		</style>
	</head>
	<body>
		<!--
		정상작동: chrome, Firefox v31.0
		오류: IE9, Safari v5.1.7
		-->
		<button onclick="saveSvg()">
			Save SVG File
		</button>

		<!--
		정상작동: chrome, IE9
		오류: Firefox v31.0, Safari v5.1.7
		-->
		<button onclick="savePng()">
			Save PNG File
		</button>
		<button onclick="buttonConvertCanvasToImage()">
			Convert Canvas To Image
		</button>
		<canvas id="canvas" width="640" height="480" style="display:none;">
		</canvas>
		<svg id="svg" height="100" width="100">
		<circle cx="50" cy="50" r="40" stroke="black" stroke-width="3" fill="red" />
		Sorry, your browser does not support inline SVG.
		</svg>
	</body>
</html>


STS 프로젝트 파일을 첨부합니다.

svg-save.zip


Comments