xxxxxxxxxx
<html lang="en">
<head>
<link href='https://fonts.googleapis.com/css?family=Open+Sans:400,700' rel='stylesheet' type='text/css'>
<title></title>
<meta name="description" content="">
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1, maximum-scale=1, user-scalable=no" />
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<link rel="stylesheet" href="../lib/globalStyle.css" />
<style type="text/css">
</style>
</head>
<body>
<div id="graphic">
<img src="fallback.png" alt="[Chart]" />
</div>
<div id="keypoints">
<p></p>
</div>
<div class="footer">
</div>
<div id="footer"></div>
<script src="https://cdn.ons.gov.uk/vendor/d3/4.2.7/d3.min.js" type="text/javascript"></script>
<script src="modernizr.svg.min.js" type="text/javascript"></script>
<script src="pym.js" type="text/javascript"></script>
<script>
var graphic = d3.select('#graphic');
var keypoints = d3.select('#keypoints');
var footer = d3.select(".footer");
var pymChild = null;
function drawGraphic(width) {
var threshold_md = 788;
var threshold_sm = dvc.optional.mobileBreakpoint;
//set variables for chart dimensions dependent on width of #graphic
if (parseInt(graphic.style("width")) < threshold_sm) {
var margin = {
top: dvc.optional.margin_sm[0],
right: dvc.optional.margin_sm[1],
bottom: dvc.optional.margin_sm[2],
left: dvc.optional.margin_sm[3]
};
var chart_width = parseInt(graphic.style("width")) - margin.left - margin.right;
var height = dvc.essential.barHeight_sm_md_lg[0] * graphic_data.length - margin.top - margin.bottom;
} else if (parseInt(graphic.style("width")) < threshold_md) {
var margin = {
top: dvc.optional.margin_md[0],
right: dvc.optional.margin_md[1],
bottom: dvc.optional.margin_md[2],
left: dvc.optional.margin_md[3]
};
var chart_width = parseInt(graphic.style("width")) - margin.left - margin.right;
var height = dvc.essential.barHeight_sm_md_lg[1] * graphic_data.length - margin.top - margin.bottom;
} else {
var margin = {
top: dvc.optional.margin_lg[0],
right: dvc.optional.margin_lg[1],
bottom: dvc.optional.margin_lg[2],
left: dvc.optional.margin_lg[3]
}
var chart_width = parseInt(graphic.style("width")) - margin.left - margin.right;
var height = dvc.essential.barHeight_sm_md_lg[2] * graphic_data.length - margin.top - margin.bottom;
}
// clear out existing graphics
graphic.selectAll("*").remove();
keypoints.selectAll("*").remove();
footer.selectAll("*").remove();
var x = d3.scaleOrdinal()
.range([0, 1*chart_width/5, 2*chart_width/5,3*chart_width/5,4*chart_width/5, chart_width])
var x2 = d3.scaleLog()
.range([0,chart_width])
.domain([0.125,4])
var y = d3.scaleBand()
.rangeRound([0, height])
.paddingInner(0.1);
y.domain(graphic_data.map(function(d) {
return d.name;
}));
var yAxis = d3.axisLeft(y)
var xAxis = d3.axisBottom(x)
.tickSize(-height, 0, 0);
//specify number or ticks on x axis
if (parseInt(graphic.style("width")) <= threshold_sm) {
xAxis.ticks(dvc.optional.x_num_ticks_sm_md_lg[0])
} else if (parseInt(graphic.style("width")) <= threshold_md) {
xAxis.ticks(dvc.optional.x_num_ticks_sm_md_lg[1])
} else {
xAxis.ticks(dvc.optional.x_num_ticks_sm_md_lg[2])
}
// parse data into columns
var bars = {};
for (var column in graphic_data[0]) {
if (column == 'name') continue;
bars[column] = graphic_data.map(function(d) {
return {
'name': d.name,
'amt': d[column]
};
});
}
//y domain calculations : zero to intelligent max choice, or intelligent min and max choice, or interval chosen manually
if (dvc.essential.xAxisScale == "auto_zero_max") {
var xDomain = [
0,
d3.max(d3.entries(bars), function(c) {
return d3.max(c.value, function(v) {
var n = v.amt;
return Math.ceil(n);
});
})
];
} else if (dvc.essential.xAxisScale == "auto_min_max") {
var xDomain = [
d3.min(d3.entries(bars), function(c) {
return d3.min(c.value, function(v) {
var n = v.amt;
return Math.floor(n);
});
}),
d3.max(d3.entries(bars), function(c) {
return d3.max(c.value, function(v) {
var n = v.amt;
return Math.ceil(n);
});
})
];
} else {
var xDomain = dvc.essential.xAxisScale;
}
x.domain(xDomain);
d3.select("#buttonid").on("click", function() {
saveSvgAsPng(document.getElementById("chart"), "diagram.png")
});
d3.select('#graphic').select('svg')
.append("g")
.attr("id", "source")
.append("text")
.attr("text-anchor", "start")
.style("font-size", "12px")
.style("fill", "#666")
.attr('y', height + margin.top + margin.bottom - 10)
.attr('x', 0)
.text("Source: ")
.append("a")
.style("fill", "#4774CC")
.attr("href", dvc.essential.sourceURL)
.attr("target", "_blank")
.text(dvc.essential.sourceText);
//create svg for chart
var svg = d3.select('#graphic').append('svg')
.attr("id", "chart")
.style("background-color", "#fff")
.attr("width", chart_width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom + 30)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
svg.append("rect")
.attr("class", "svgRect")
.attr("width", chart_width)
.attr("height", height)
.attr("fill", "transparent")
svg.append('g')
.attr('class', 'x axis')
.attr("transform", "translate(0, " + height + ")")
.call(xAxis).append("text")
.attr("y", 25)
.attr("x", chart_width)
.attr("dy", ".71em")
.style("text-anchor", "end")
.attr("font-size", "12px")
.attr("fill", "#666")
.text(dvc.essential.xAxisLabel);
//create y axis, if x axis doesn't start at 0 drop x axis accordingly
svg.append('g')
.attr('class', 'y axis')
.attr('transform', function(d) {
if (xDomain[0] != 0) {
return 'translate(' + (0) + ',0)'
} else {
return 'translate(' + 0 + ', 0)'
}
})
.call(yAxis);
if (parseInt(graphic.style("width")) < threshold_sm) {
d3.selectAll(".y .tick text")
.call(wrap, dvc.optional.margin_sm[3]-10);
} else if (parseInt(graphic.style("width")) < threshold_md) {
d3.selectAll(".y .tick text")
.call(wrap, dvc.optional.margin_md[3]-10);
} else {
d3.selectAll(".y .tick text")
.call(wrap, dvc.optional.margin_lg[3]-10);
};
svg.append('g').attr("class", "bars").selectAll('rect')
.data(bars["value"])
.enter()
.append('rect')
.attr("fill", function(d) {
if (d.amt > 0) {
return dvc.essential.colour_palette[0]
} else {
return dvc.essential.negative_colour
}
})
.attr("width", function(d) {
return 0 + Math.abs(x2(d.amt) - x2(1));
})
.attr("x", function(d) {
return x2(Math.min(1, d.amt));
})
.attr("y", function(d) {
return y(d.name);
})
.attr("height", y.bandwidth())
//create centre line if required
if (dvc.optional.centre_line == true) {
svg.append("line")
.attr("id", "centreline")
.attr('y1', 0)
.attr('y2', height)
.attr('x1', x(dvc.optional.centre_line_value))
.attr('x2', x(dvc.optional.centre_line_value))
}
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"),
x = text.attr("x"),
dy = parseFloat(text.attr("dy")),
tspan = text.text(null).append("tspan").attr("x", x).attr("y", y).attr("dy", dy + "em");
if (words.length > 2) {
while (word = words.pop()) {
line.push(word);
tspan.text(line.join(" "));
if (tspan.node().getComputedTextLength() > width) {
if (lineNumber == 0) {
tspan.attr("dy", dy - 1.1 + "em")
} else {
tspan.attr("dy", -dy + 0.55 + "em")
}
line.pop();
tspan.text(line.join(" "));
line = [word];
++lineNumber;
tspan = text.append("tspan").attr("x", x).attr("y", y).attr("dy", (0.55 * lineNumber - dy + 0.55) + "em").text(word);
}
}
} else {
while (word = words.pop()) {
line.push(word);
tspan.text(line.join(" "));
if (tspan.node().getComputedTextLength() > width) {
if (lineNumber == 0) {
tspan.attr("dy", dy - 0.55 + "em")
} else {
tspan.attr("dy", -dy + 0.55 + "em")
}
line.pop();
tspan.text(line.join(" "));
line = [word];
++lineNumber;
tspan = text.append("tspan").attr("x", x).attr("y", y).attr("dy", (1.1 * lineNumber - dy + 0.55) + "em").text(word);
}
}
}
});
}
writeAnnotation();
function writeAnnotation() {
if (parseInt(graphic.style("width")) < threshold_sm) {
dvc.essential.annotationBullet.forEach(function(d, i) {
d3.select("#keypoints").append("svg")
.attr("width", "20px")
.attr("height", "20px")
.attr("class", "circles")
.append("circle")
.attr("class", "annocirc" + (i))
.attr("r", "2")
.attr('cy', "12px")
.attr("cx", "10px");
d3.select("#keypoints").append("p").text(dvc.essential.annotationBullet[i])
.attr("font-family", "'Open Sans', sans-serif")
.attr("font-size", "13px")
.attr("color", "#666")
.attr("font-weight", "500");
}) // end foreach
} else {
dvc.essential.annotationChart.forEach(function(d, i) {
// draw annotation text based on content of var annotationArray ...
svg.append("text")
.text(dvc.essential.annotationChart[i])
.attr("class", "annotext" + i)
.attr("text-anchor", dvc.essential.annotationAlign[i])
.attr('y', y(dvc.essential.annotationXY[i][1]))
.attr('x', x(dvc.essential.annotationXY[i][0]))
.attr("font-family", "'Open Sans', sans-serif")
.attr("font-size", "13px")
.attr("fill", "#666")
.attr("font-weight", "500");
d3.selectAll(".annotext" + (i))
.each(insertLinebreaks)
.each(createBackRect);
function insertLinebreaks() {
var str = this;
var el1 = dvc.essential.annotationChart[i];
var el = el1.data;
var words = el1.split(' ');
d3.select(this /*str*/ ).text('');
for (var j = 0; j < words.length; j++) {
var tspan = d3.select(this).append('tspan').text(words[j]);
if (j > 0)
tspan.attr('x', x(dvc.essential.annotationXY[i][0])).attr('dy', '22');
}
};
function createBackRect() {
var BBox = this.getBBox()
svg.insert("rect", ".annotext" + (i))
.attr("width", BBox.width)
.attr("height", BBox.height)
.attr("x", BBox.x)
.attr("y", BBox.y)
.attr("fill", "white")
.attr("opacity", 0.4);
}; // end function createBackRect()
}); // end foreach
} // end else ...
// If you have labels rather than years then you can split the lines using a double space (in the CSV file).
if (dvc.optional.vertical_line == true) {
dvc.optional.annotateLineX1_Y1_X2_Y2.forEach(function(d, i) {
svg.append("line").attr('x1', x(dvc.optional.annotateLineX1_Y1_X2_Y2[i][0][0]))
.attr('x2', x(dvc.optional.annotateLineX1_Y1_X2_Y2[i][1][0]))
.style('stroke', '#888')
.style('stroke-width', 2)
.attr('font-size', '13px')
//.style('stroke-dasharray', '5 5') .attr('y1',y(dvc.optional.annotateLineX1_Y1_X2_Y2[i][0][1]))
.attr('y2', y(dvc.optional.annotateLineX1_Y1_X2_Y2[i][1][1]));
})
}
d3.selectAll("path").attr("fill", "none");
d3.selectAll(".x line")
.attr("stroke", "#CCC")
.attr("stroke-width", "1px")
.attr("shape-rendering", "crispEdges");
d3.selectAll("text").attr("font-family", "'Open Sans', sans-serif");
d3.selectAll(".y text").attr("font-size", "12px").attr("fill", "#666");
d3.selectAll(".x text").attr("font-size", "12px").attr("fill", "#666"); // dates - timelines
d3.selectAll(".y line")
.attr("stroke", "#CCC")
.attr("stroke-width", "1px")
.style("shape-rendering", "crispEdges");
if (dvc.optional.annotateRect == true) {
dvc.optional.annotateRectX_Y.forEach(function(d, i) {
svg.append("rect")
.attr('x', x(dvc.optional.annotateRectX_Y[i][0][0]))
.attr('y', y(dvc.optional.annotateRectX_Y[i][0][1]))
.attr('height', y(dvc.optional.annotateRectX_Y[i][1][1]) - y(dvc.optional.annotateRectX_Y[i][0][1]))
.attr('width', x(dvc.optional.annotateRectX_Y[i][1][0]) - x(dvc.optional.annotateRectX_Y[i][0][0]))
.style('fill', dvc.optional.lineColor_opcty[i][0])
.style('stroke-width', 2)
.style('opacity', dvc.optional.lineColor_opcty[i][1]);
})
}
d3.select(".y").select("path").style("stroke", "#666")
// function insertLinebreaksLabels() {
// var str = this.textContent;
//
// var words = str.split(' ');
//
// d3.select(this/*str*/).text('');
//
// for (var j = 0; j < words.length; j++) {
// var tspan = d3.select(this).append('tspan').text(words[j]);
// if (j > 0)
// tspan
// .attr('x', -10)
// .attr('dy', '1em');
// }
// };
// d3.selectAll(".y text").each(insertLinebreaksLabels)
} // end function writeAnnotation()
d3.select('#graphic').select('svg')
.append("g")
.attr("id", "source")
.append("text")
.attr("text-anchor", "start")
.style("font-size", "12px")
.style("fill", "#666")
.attr('y', height + margin.top + margin.bottom + 28)
.attr('x', 0)
.text("Source: ")
.append("a")
.style("fill", "#4774CC")
.attr("xlink:href", dvc.essential.sourceURL)
.attr("target", "_blank")
.text(dvc.essential.sourceText);
d3.selectAll("text").attr("font-family", "'Open Sans', sans-serif");
//use pym to calculate chart dimensions
if (pymChild) {
pymChild.sendHeight();
}
}
//check whether browser can cope with svg
if (Modernizr.svg) {
//load config
d3.json("config.json", function(error, config) {
dvc = config
//load chart data
d3.csv(dvc.essential.graphic_data_url, function(error, data) {
graphic_data = data;
// graphic_data.forEach(function(d) {
// d.name = d3.time.format(dvc.essential.dateFormat).parse(d.name);
// });
names = d3.keys( /*data*/ graphic_data[0]).filter(function(key) {
return key !== "state";
});
/*data*/
graphic_data.forEach(function(d) {
//d.ages = names.map(function(name) { return {name: name, value: +d[name]}; });
});
//use pym to create iframed chart dependent on specified variables
pymChild = new pym.Child({
renderCallback: drawGraphic
});
});
})
} else {
//use pym to create iframe containing fallback image (which is set as default)
pymChild = new pym.Child();
if (pymChild) {
pymChild.sendHeight();
}
}
</script>
</body>
</html>
https://cdn.ons.gov.uk/vendor/d3/4.2.7/d3.min.js