Last active
February 17, 2023 12:52
-
-
Save shimizu/eb8829e8e35216d890c501bd698e87ce to your computer and use it in GitHub Desktop.
download.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
export defaul function() { | |
var doctype = | |
'<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">'; | |
var prefix = { | |
xmlns: "http://www.w3.org/2000/xmlns/", | |
xlink: "http://www.w3.org/1999/xlink", | |
svg: "http://www.w3.org/2000/svg" | |
}; | |
var _debug = false; | |
var _fileName = "chart"; | |
function instance(_selection) { | |
var svg = _selection.node(); | |
var _emptySvg, _emptySvgDeclarationComputed; | |
var _copyChart; | |
function createEmptySVG() { | |
_emptySvg = window.document.createElementNS(prefix.svg, "svg"); | |
window.document.body.appendChild(_emptySvg); | |
_emptySvgDeclarationComputed = getComputedStyle(_emptySvg); | |
} | |
function createCopySVG() { | |
_copyChart = d3 | |
.select("body") | |
.append("div") | |
.html(svg.outerHTML) | |
.node(); | |
} | |
function traverse(obj) { | |
var tree = []; | |
tree.push(obj); | |
visit(obj); | |
function visit(node) { | |
if (node && node.hasChildNodes()) { | |
var child = node.firstChild; | |
while (child) { | |
if (child.nodeType === 1 && child.nodeName != "SCRIPT") { | |
tree.push(child); | |
visit(child); | |
} | |
child = child.nextSibling; | |
} | |
} | |
} | |
return tree; | |
} | |
function explicitlySetStyle(element) { | |
if (element.nodeName == "image") convertDataURIs(element); | |
var cSSStyleDeclarationComputed = getComputedStyle(element); | |
var attributes = Object.keys(element.attributes).map(function(i) { | |
return element.attributes[i].name; | |
}); | |
var i, len; | |
var computedStyleStr = ""; | |
for (i = 0, len = cSSStyleDeclarationComputed.length; i < len; i++) { | |
var key = cSSStyleDeclarationComputed[i]; | |
var value = cSSStyleDeclarationComputed.getPropertyValue(key); | |
if ( | |
!attributes.some(function(k) { | |
return k === key; | |
}) && | |
value !== _emptySvgDeclarationComputed.getPropertyValue(key) | |
) { | |
computedStyleStr += key + ":" + value + ";"; | |
} | |
} | |
element.setAttribute("style", computedStyleStr); | |
} | |
function convertDataURIs(imgElement) { | |
var canvas = document.createElement("canvas"); | |
canvas.width = | |
imgElement.farthestViewportElement.attributes.width.nodeValue; | |
canvas.height = | |
imgElement.farthestViewportElement.attributes.height.nodeValue; | |
canvas.getContext("2d").drawImage(imgElement, 0, 0); | |
var dataURI = canvas.toDataURL("image/png"); | |
imgElement.setAttribute("xlink:href", dataURI); | |
} | |
function downloadingSVG(source) { | |
var svg = d3 | |
.select(source) | |
.select("svg") | |
.attr("xmlns", prefix.svg) | |
.attr("version", "1.1") | |
.node(); | |
var blobObject = new Blob( | |
[doctype + new XMLSerializer().serializeToString(svg)], | |
{ type: "text/xml" } | |
); | |
var url = window.URL.createObjectURL(blobObject); | |
var a = d3.select("body").append("a"); | |
a.attr("class", "downloadLink") | |
.attr("download", _fileName + ".svg") | |
.attr("href", url) | |
.text("test") | |
.style("display", "none"); | |
a.node().click(); | |
setTimeout(function() { | |
window.URL.revokeObjectURL(url); | |
a.remove(); | |
}, 10); | |
} | |
function downloadingPNG(source) { | |
var svg = d3 | |
.select(source) | |
.select("svg") | |
.attr("xmlns", prefix.svg) | |
.attr("version", "1.1") | |
.node(); | |
var data_uri = | |
"data:image/svg+xml;utf8," + | |
encodeURIComponent(new XMLSerializer().serializeToString(svg)); | |
var canvas = d3 | |
.select("body") | |
.append("canvas") | |
.attr("id", "drawingArea") | |
.attr("width", svg.clientWidth) | |
.attr("height", svg.clientHeight); | |
if (!_debug) canvas.style("display", "none"); | |
var context = canvas.node().getContext("2d"); | |
var img = new Image(); | |
img.src = data_uri; | |
img.addEventListener("load", downloaded, false); | |
function downloaded() { | |
context.drawImage(img, 0, 0); | |
var url = canvas.node().toDataURL("image/png"); | |
var a = d3 | |
.select("body") | |
.append("a") | |
.attr("id", "downloadLink"); | |
a.attr("class", "downloadLink") | |
.attr("download", _fileName + ".png") | |
.attr("href", url) | |
.text("test") | |
.style("display", "none"); | |
a.node().click(); | |
if (!_debug) | |
setTimeout(function() { | |
window.URL.revokeObjectURL(url); | |
canvas.remove(); | |
a.remove(); | |
}, 10); | |
} | |
} | |
/** | |
* @callback downloadSVG | |
* @desc svgをダウンロードする | |
*/ | |
_selection.downloadSVG = function(fileName) { | |
if (fileName) _fileName = fileName; | |
createEmptySVG(); | |
createCopySVG(); | |
var allElements = traverse(_copyChart); | |
var i = allElements.length; | |
while (i--) { | |
explicitlySetStyle(allElements[i]); | |
} | |
downloadingSVG(_copyChart); | |
if (!_debug) { | |
d3.select(_copyChart).remove(); | |
d3.select(_emptySvg).remove(); | |
} | |
}; | |
/** | |
* @callback downloadPNG | |
* @desc pngをダウンロードする | |
*/ | |
_selection.downloadPNG = function(fileName) { | |
if (fileName) _fileName = fileName; | |
createEmptySVG(); | |
createCopySVG(); | |
var allElements = traverse(_copyChart); | |
var i = allElements.length; | |
while (i--) { | |
explicitlySetStyle(allElements[i]); | |
} | |
downloadingPNG(_copyChart); | |
if (!_debug) { | |
d3.select(_copyChart).remove(); | |
d3.select(_emptySvg).remove(); | |
} | |
}; | |
} | |
/** | |
* デバッグ機能の有効・無効を設定する | |
* @param {Boolean} flag 有効, 無効を渡す | |
*/ | |
instance.debug = function(_arg) { | |
if (!arguments.length) return _debug; | |
_debug = _arg; | |
return this; | |
}; | |
return instance; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment