add utility function for wrapping svg text, apply to sunburst breadcrumbs, and make colors more readable for sunburst.

This commit is contained in:
Chris Williams 2016-03-17 14:02:54 -07:00
parent 06080945b6
commit 3197c4b3f9
3 changed files with 74 additions and 17 deletions

View File

@ -0,0 +1,55 @@
var d3 = require('d3');
/*
Utility function that takes a d3 svg:text selection and a max width, and splits the
text's text across multiple tspan lines such that any given line does not exceed max width
If text does not span multiple lines AND adjustedY is passed, will set the text to the passed val
*/
function wrapSvgText(text, width, adjustedY) {
var lineHeight = 1; // ems
text.each(function () {
var text = d3.select(this),
words = text.text().split(/\s+/),
word,
line = [],
lineNumber = 0,
x = text.attr("x"),
y = text.attr("y"),
dy = parseFloat(text.attr("dy")),
tspan = text.text(null)
.append("tspan")
.attr("x", x)
.attr("y", y)
.attr("dy", dy + "em");
var didWrap = false;
for (var i = 0; i < words.length; i++) {
word = words[i];
line.push(word);
tspan.text(line.join(" "));
if (tspan.node().getComputedTextLength() > width) {
line.pop(); // remove word that pushes over the limit
tspan.text(line.join(" "));
line = [word];
tspan = text.append("tspan")
.attr("x", x)
.attr("y", y)
.attr("dy", ++lineNumber * lineHeight + dy + "em")
.text(word);
didWrap = true;
}
}
if (!didWrap && typeof adjustedY !== "undefined") {
tspan.attr("y", adjustedY);
}
});
}
module.exports = {
wrapSvgText: wrapSvgText
};

View File

@ -2,13 +2,13 @@
shape-rendering: crispEdges;
}
.sunburst path {
stroke: #fff;
stroke-width: 1px;
stroke: #333;
stroke-width: 0.5px;
}
.sunburst .center-label {
text-anchor: middle;
fill: #000;
pointer-events: none;
}
.sunburst .path-percent {
font-size: 4em;
@ -20,20 +20,14 @@
font-size: 1.2em;
}
.sunburst .breadcrumbs {
fill: #00D1C1; /*default*/
}
.sunburst .breadcrumbs text {
font-weight: 600;
font-size: 1.2em;
text-anchor: middle;
fill: #fff;
}
.sunburst .breadcrumbs text.end-label {
fill: #000;
}
/* dashboard specific */
.dashboard .sunburst text {
font-size: 1em;
}

View File

@ -1,5 +1,7 @@
var d3 = window.d3 || require('d3');
var px = require('../javascripts/modules/panoramix.js');
var wrapSvgText = require('../javascripts/modules/utils.js').wrapSvgText;
require('./sunburst.css');
// Modified from http://bl.ocks.org/kerryrodden/7090426
@ -11,7 +13,7 @@ function sunburstVis(slice) {
var margin = { top: 10, right: 5, bottom: 10, left: 5 };
var containerWidth = slice.width();
var containerHeight = slice.height();
var breadcrumbHeight = containerHeight * 0.065;
var breadcrumbHeight = containerHeight * 0.085;
var visWidth = containerWidth - margin.left - margin.right;
var visHeight = containerHeight - margin.top - margin.bottom - breadcrumbHeight;
var radius = Math.min(visWidth, visHeight) / 2;
@ -19,6 +21,7 @@ function sunburstVis(slice) {
var maxBreadcrumbs, breadcrumbDims, // set based on data
totalSize, // total size of all segments; set after loading the data.
colorScale,
breadcrumbs, vis, arcs, gMiddleText; // dom handles
// Helper + path gen functions
@ -107,7 +110,7 @@ function sunburstVis(slice) {
return (d.dx > 0.005); // 0.005 radians = 0.29 degrees
});
var ext, colorScale;
var ext;
if (rawData.form_data.metric !== rawData.form_data.secondary_metric) {
colorByCategory = false;
@ -187,7 +190,7 @@ function sunburstVis(slice) {
function mouseleave(d) {
// Hide the breadcrumb trail
breadcrumbs.style("visibility", "hidden");
// breadcrumbs.style("visibility", "hidden");
gMiddleText.selectAll("*").remove();
@ -235,21 +238,26 @@ function sunburstVis(slice) {
function updateBreadcrumbs(sequenceArray, percentageString) {
var g = breadcrumbs.selectAll("g")
.data(sequenceArray, function (d) { return d.name + d.depth; });
.data(sequenceArray, function (d) {
return d.name + d.depth;
});
// Add breadcrumb and label for entering nodes.
var entering = g.enter().append("svg:g");
entering.append("svg:polygon")
.attr("points", breadcrumbPoints)
.style("fill", function (d) { return colorByCategory ? px.color.category21(d.name) : null; });
.style("fill", function (d) {
return colorByCategory ? px.color.category21(d.name) : colorScale(d.m2 / d.m1);
});
entering.append("svg:text")
.attr("x", (breadcrumbDims.width + breadcrumbDims.tipTailWidth) / 2)
.attr("y", breadcrumbDims.height / 2)
.attr("y", breadcrumbDims.height / 4)
.attr("dy", "0.35em")
.attr("class", "step-label")
.text(function (d) { return d.name; });
.text(function (d) { return d.name; })
.call(wrapSvgText, breadcrumbDims.width, breadcrumbDims.height / 2);
// Set position for entering and updating nodes.
g.attr("transform", function (d, i) {