Alon Heller d09d521772 sunburst labels
Change-Id: I3902aad3c415374d96e712597d0d3e2de07a8c67
2016-01-20 14:45:15 +02:00

231 lines
5.9 KiB
JavaScript

angular
.module('horizon.dashboard.project.vitrage')
.directive('hzSunburst', hzSunburst);
function hzSunburst() {
var directive = {
link: link,
scope: {
name: '@',
data: '=',
selected: '='
},
templateUrl: STATIC_URL + 'dashboard/project/components/sunburst/sunburst.html',
restrict: 'E'
};
return directive;
function link(scope, element, attrs) {
var svg, path, partition, arc,
width = 500,
height = 500,
Df = {pad: 5, speed: 1000, width: width, height: height, radius: Math.min(width, height) / 2},
fnX = d3.scale.linear().range([0, 2 * Math.PI]),
fnY = d3.scale.pow().exponent(0.5).domain([0, 1]).range([0, Df.radius]),
partition = d3.layout.partition()
.value(function(d) {
return d.size | 1000;
});
arc = d3.svg.arc()
.startAngle(function (d) {
return Math.max(0, Math.min(2 * Math.PI, fnX(d.x)));
})
.endAngle(function (d) {
return Math.max(0, Math.min(2 * Math.PI, fnX(d.x + d.dx)));
})
.innerRadius(function (d) {
return Math.max(0, fnY(d.y));
})
.outerRadius(function (d) {
return Math.max(0, fnY(d.y + d.dy));
});
scope.$watch('data', function(newValue, oldValue) {
if (newValue && newValue != oldValue) {
cloneSelectedItem(newValue);
svg ? update() : init();
}
});
function click(d) {
cloneSelectedItem(d);
console.log('Clicked: ', scope.selected);
scope.$emit('sunburstItemClicked', d);
path.transition()
.duration(750)
.attrTween("d", arcTween(d));
// TEXT ANIMATION
svg.selectAll('text')
.style('visibility', function (e) {
return isParentOf(d, e) ? null : d3.select(this).style('visibility');
})
.transition().duration(Df.speed) // makes the effect of fade-in / fade-out
.attrTween('text-anchor', function (d) {
return function () {
return fnX(d.x + d.dx / 2) > Math.PI ? 'end' : 'start';
};
})
.attrTween('transform', function (d) {
return function () {
var angle = fnX(d.x + d.dx / 2) * 180 / Math.PI - 90;
return ['rotate(', angle, ')', //
'translate(', fnY(d.y) + Df.pad, ')', //
'rotate(', angle > 90 ? -180 : 0, ')'].join('');
};
})
.style('fill-opacity', function (e) {
return isParentOf(d, e) ? 1 : 1e-6;
}) //
.each('end', function (e) {
d3.select(this).style('visibility', isParentOf(d, e) ? null : 'hidden');
});
}
function cloneSelectedItem(d) {
scope.selected = {id: d.id, name: d.name, state: d.state};
}
// Interpolate the scales!
function arcTween(d) {
var xd = d3.interpolate(fnX.domain(), [d.x, d.x + d.dx]);
var yd = d3.interpolate(fnY.domain(), [d.y, maxY(d)]);
var yr = d3.interpolate(fnY.range(), [d.y ? 20 : 0, Df.radius]);
return function (d) {
return function (t) {
fnX.domain(xd(t));
fnY.domain(yd(t)).range(yr(t));
return arc(d);
};
};
}
function maxY(d) {
return d.children ? Math.max.apply(Math, d.children.map(maxY)) : d.y + d.dy;
}
function getColor(d) {
if (d.state) {
switch (d.state.toUpperCase()) {
case 'AVAILABLE':
case 'ACTIVE':
return '#87CE53';
default:
return '#D3D3D3';
}
}
}
function init() {
svg = d3.select('#' + scope.name).append("svg")
.attr("width", width)
.attr("height", height)
.attr("id", scope.name + '_svg')
.append("g")
.attr("transform", "translate(" + width / 2 + "," + (height / 2) + ")");
update();
}
function update() {
// Enter
svg.selectAll("path")
.data(partition.nodes(scope.data), function(d) {
return d.id;
})
.enter().append("path")
.attr("d", arc)
.style("fill", function(d) {
return getColor(d);
})
.on("click", click)
.each(function(d) {
this.x0 = d.x;
this.dx0 = d.dx;
});
svg.selectAll('text')
.data(partition.nodes(scope.data), function (d) {
return d.id;
})
.enter().append('text')
.text(function(d) {
return substringName(d);
})
.attr({
'dy': '.2em',
'text-anchor': function (d) {
return fnX(d.x + d.dx / 2) > Math.PI ? 'end' : 'start';
},
'transform': function (d) {
var angle, rotated;
angle = fnX(d.x + d.dx / 2) * 180 / Math.PI - 90;
rotated = (angle > 90 ? -180 : 0);
return ['rotate(', angle, ')',
'translate(', fnY(d.y) + Df.pad, ')',
'rotate(', rotated, ')'].join('');
}
})
.on("click", click);
svg.selectAll('text')
.append("svg:title").text(function(d){
return createTooltipText(d);
});
// Exit
svg.selectAll("path")
.data(partition.nodes(scope.data), function(d) {
return d.id;
})
.attr("d", arc)
.style("fill", function(d) {
return getColor(d);
})
.exit().remove();
path = svg.selectAll("path");
path.append("svg:title").text(function(d) {
return createTooltipText(d);
}
);
}
function substringName(d){
var name = d.name,
dots = '...';
if (name.length > 4) {
name = d.name.substring(0, 4) + dots;
}
return name;
}
function isParentOf(p, c) {
if (p === c) {
return true;
}
if (p.children) {
return p.children.some(function (d) {
return isParentOf(d, c);
});
}
return false;
}
function createTooltipText(d) {
return d.name;
}
}
}