forked from mbostock's block: Wrapping Long Labels
forked from f94f's block: Barras Estado
license: gpl-3.0 | |
scrolling: |
forked from mbostock's block: Wrapping Long Labels
forked from f94f's block: Barras Estado
function createDownloader(){ | |
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" | |
} | |
function exports(_selection) { | |
var svg = _selection.node() | |
var w = svg.clientWidth, h = svg.clientHeight | |
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.innerHTML) | |
.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) { | |
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 downloadSVG(source) { | |
var filename = "chart.svg"; | |
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" }) | |
if (navigator.appVersion.toString().indexOf('.NET') > 0){ //IE hack | |
window.navigator.msSaveBlob(blobObject, filename) | |
}else { | |
var url = window.URL.createObjectURL(blobObject) | |
var a = d3.select("body").append("a") | |
a.attr("class", "downloadLink") | |
.attr("download", "chart.svg") | |
.attr("href", url) | |
.text("test") | |
.style("display", "none") | |
a.node().click() | |
setTimeout(function() { | |
window.URL.revokeObjectURL(url) | |
a.remove() | |
}, 10); | |
} | |
} | |
function downloadPNG(source) { | |
var filename = "chart.png"; | |
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", w) | |
.attr("height", h) | |
.style("display", "none") | |
var context = canvas.node().getContext("2d") | |
var download = function() { | |
if (navigator.appVersion.toString().indexOf('.NET') > 0){ | |
canvg(document.getElementById('drawingArea'), (new XMLSerializer()).serializeToString(svg)) | |
var dataURI2Blob = function(dataURI, dataTYPE) { | |
var binary = atob(dataURI.split(',')[1]), array = []; | |
for(var i = 0; i < binary.length; i++) array.push(binary.charCodeAt(i)); | |
return new Blob([new Uint8Array(array)], {type: dataTYPE}); | |
} | |
var data_uri = canvas.node().toDataURL("image/png") | |
var blobObject = dataURI2Blob(data_uri, "image/png") | |
window.navigator.msSaveBlob(blobObject, filename) | |
}else { | |
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) | |
.attr("href", url) | |
.text("test") | |
.style("display", "none") | |
a.node().click() | |
setTimeout(function() { | |
window.URL.revokeObjectURL(url) | |
canvas.remove() | |
a.remove() | |
}, 10); | |
} | |
} | |
var img = new Image(); | |
img.src = data_uri | |
if (navigator.appVersion.toString().indexOf('.NET') > 0){ //IE hack | |
d3.select(img).attr("onload", download) | |
}else{ | |
img.addEventListener('load', download, false) | |
} | |
} | |
/** | |
* @callback downloadSVG | |
* @desc svgをダウンロードする | |
*/ | |
_selection.downloadSVG = function(){ | |
createEmptySVG() | |
createCopySVG() | |
var allElements = traverse(_copyChart) | |
var i = allElements.length; | |
while (i--){ | |
explicitlySetStyle(allElements[i]); | |
} | |
downloadSVG(_copyChart) | |
d3.select(_copyChart).remove() | |
d3.select(_emptySvg).remove() | |
} | |
/** | |
* @callback downloadPNG | |
* @desc pngをダウンロードする | |
*/ | |
_selection.downloadPNG = function(){ | |
createEmptySVG() | |
createCopySVG() | |
var allElements = traverse(_copyChart) | |
var i = allElements.length; | |
while (i--){ | |
explicitlySetStyle(allElements[i]); | |
} | |
downloadPNG(_copyChart) | |
d3.select(_copyChart).remove() | |
d3.select(_emptySvg).remove() | |
} | |
} | |
return exports | |
} |
<!DOCTYPE html> | |
<meta charset="utf-8"> | |
<style> | |
.bar-pe { | |
fill: #0075ea; | |
} | |
.bar-to { | |
fill: #008e2d; | |
} | |
.bar-pa { | |
fill: #ffa500; | |
} | |
.bar-re { | |
fill: #FF0000; | |
} | |
.bar-pe:hover { | |
fill: #56aafe; | |
} | |
.bar-to:hover { | |
fill: #00BC3C; | |
} | |
.bar-pa:hover { | |
fill: #ffbb3d; | |
} | |
.bar-re:hover { | |
fill: #ff1e1e; | |
} | |
/*tooltip*/ | |
.show { | |
display: block; | |
} | |
.hidden { | |
display: none; | |
} | |
.tooltip { | |
background-color: #333; | |
padding: 4px 8px; | |
position: absolute; | |
color: #fff; | |
opacity: 0.8; | |
z-index: 100; | |
} | |
.title { | |
font: bold 14px "Helvetica Neue", Helvetica, Arial, sans-serif; | |
} | |
.axis { | |
font: 10px sans-serif; | |
} | |
.axis path, | |
.axis line { | |
fill: none; | |
stroke: #000; | |
stroke-dasharray: 2px 2px; | |
} | |
.x.axis path { | |
display: none; | |
} | |
</style> | |
<body> | |
<div id="chart"></div> | |
<button id="downloadSVG">SVG Download</button> | |
<button id="downloadPNG">PNG Download</button> | |
<script src="//cdnjs.cloudflare.com/ajax/libs/d3/4.3.0/d3.min.js"></script> | |
<script src="//bl.ocks.org/shimizu/raw/0b526eab82263c8443108c33e454d221/nChart.js"></script> | |
<script src="createDownloader.js"></script> | |
<script src="//d3js.org/d3.v4.min.js"></script> | |
<script> | |
var puntos = [ | |
{name: "Pendientes", value: 0.40}, | |
{name: "Totales", value: 0.0667}, | |
{name: "Parciales", value: 0.0667}, | |
{name: "Rechazados", value: 0.0} | |
]; | |
var margin = {top: 80, right: 180, bottom: 80, left: 180}, | |
width = 960 - margin.left - margin.right, | |
height = 500 - margin.top - margin.bottom; | |
var x = d3.scaleBand().rangeRound([0, width], 0.1, 0.3); | |
var y = d3.scaleLinear() | |
.range([height, 0]); | |
var xAxis = d3.axisBottom() | |
.scale(x); | |
var yAxis = d3.axisLeft() | |
.scale(y) | |
.ticks(8, "%"); | |
var tooltip = d3.select("body").append("div") | |
.attr("class", "tooltip"); | |
var svg = d3.select("body").append("svg") | |
.attr("width", width + margin.left + margin.right) | |
.attr("height", height + margin.top + margin.bottom) | |
.append("g") | |
.attr("transform", "translate(" + margin.left + "," + margin.top + ")"); | |
//EL GRÁFICO | |
x.domain(puntos.map(function(d) { return d.name; })); | |
y.domain([0, d3.max(puntos, function(d) { return d.value; })]); | |
svg.append("text") | |
.attr("class", "title") | |
.attr("x", (150)) | |
.attr("y", -30) | |
.text("Porcentaje de las entregas según su estado"); | |
svg.append("g") | |
.attr("class", "x axis") | |
.attr("transform", "translate(0," + height + ")") | |
.call(xAxis) | |
.selectAll(".tick text") | |
.call(wrap, x.bandwidth()); | |
svg.append("g") | |
.attr("class", "y axis") | |
.call(yAxis); | |
svg.selectAll(".bar") | |
.data(puntos) | |
.enter().append("rect") | |
.attr("class", function(d) { | |
if(d.name == "Pendientes") { return "bar-pe";} | |
else if(d.name == "Totales") { return "bar-to";} | |
else if(d.name == "Parciales") { return "bar-pa";} | |
else if(d.name == "Rechazados") { return "bar-re";} | |
}) | |
.attr("x", function(d) { return x(d.name); }) | |
.attr("width", x.bandwidth()) | |
.attr("y", function(d) { return y(d.value); }) | |
.attr("height", function(d) { return height - y(d.value); }) | |
.on('mouseover', function(d){ | |
d3.select("#major").text(d.key); | |
tooltip.transition() | |
.duration(500) | |
.style("opacity", 1); | |
tooltip.html((d.value * 100) + "%") | |
.style("left", (d3.event.pageX - 25) + "px") | |
.style("top", (d3.event.pageY - 50) + "px"); | |
}) | |
.on('mousemove', function (d) { | |
tooltip.style("top", (d3.event.pageY - 50) + 'px'); | |
tooltip.style("left", (d3.event.pageX - 25) + 'px'); | |
}) | |
.on('mouseout', function(d){ | |
d3.select("#major").text("Mouse over"); | |
tooltip.transition() | |
.duration(500) | |
.style("opacity", 0); | |
}) | |
var downloader = createDownloader(); | |
var selector = d3.selectAll("#chart") | |
.datum(puntos) | |
.call(yAxis) | |
.call(xAxis) | |
.call(downloader); | |
d3.select("#downloadSVG").on("click", selector.downloadSVG ) | |
d3.select("#downloadPNG").on("click", selector.downloadPNG ) | |
function wrap(text, width) { | |
text.each(function() { | |
var text = d3.select(this), | |
words = text.text().split(/\s+/).reverse(), | |
word, | |
line = [], | |
lineNumber = 0, | |
lineHeight = 1.1, // ems | |
y = text.attr("y"), | |
dy = parseFloat(text.attr("dy")), | |
tspan = text.text(null).append("tspan").attr("x", 0).attr("y", y).attr("dy", dy + "em"); | |
while (word = words.pop()) { | |
line.push(word); | |
tspan.text(line.join(" ")); | |
if (tspan.node().getComputedTextLength() > width) { | |
line.pop(); | |
tspan.text(line.join(" ")); | |
line = [word]; | |
tspan = text.append("tspan").attr("x", 0).attr("y", y).attr("dy", ++lineNumber * lineHeight + dy + "em").text(word); | |
} | |
} | |
}); | |
} | |
function type(d) { | |
d.value = +d.value; | |
return d; | |
} | |
// 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 | |
} | |
}); | |
</script> | |
<div> | |
<button id='saveButton'>Export my D3 visualization to PNG</button> | |
</div> | |
</body> |