Pie Charts now inherit from Bootstrap Theme
Horizon's pie charts had hard coded styles directly in the JavaScript code. This made it impossible for them to inherit any of their look and feel from the install theme. This patch fixes that problem. It was noted, while doing the refactor, that the legend was being implemented within D3, but this was not necessary at all, since it has no graphing visuals associated with it. It was impossible to allow the legend label sizes to inherit and be configurable from the css while they were being generated in the SVG. The height could never be known unless D3 knew the height of each element. Noted Improvements: * Consistent Colors! Colors, even for distribution charts, now come from the palette * All aspects of the charts are now resizable and can inherit the sizes of the charts, as well as the paddings and type settings from the theme * A bug in the 'Show Numbers' function was discovered and will be fixed as a result * The legend symbol, which was a hardcoded cube before, is now an icon font, and therefore can be customized per theme. I.E., you can now use rectangles, circles, ovals, smiley faces, etc * It now inherits directly from the Theme Change-Id: I5d5c13e57553f8b504593aac6d7611175e900f3c Partially-Implements: blueprint horizon-theme-css-reorg
This commit is contained in:
parent
3c6783e18b
commit
2d007cb1b7
@ -16,36 +16,14 @@
|
||||
</div>
|
||||
*/
|
||||
|
||||
// Pie chart dimensions
|
||||
// Pie chart SVG internal dimensions
|
||||
var WIDTH = 100;
|
||||
var HEIGHT = 100;
|
||||
var RADIUS = 45;
|
||||
|
||||
// Colors
|
||||
var BKGRND = "#F2F2F2";
|
||||
var FRGRND = "#006CCF";
|
||||
var FULL = "#D0342B";
|
||||
var NEARLY_FULL = "#FFA500";
|
||||
var STROKE_USAGE = "#CCCCCC";
|
||||
var STROKE_DISTRIBUTION = "#609ED2";
|
||||
var BLUE_SHADES = [
|
||||
"#609ED2",
|
||||
"#BFD8ED",
|
||||
"#EFF5FB",
|
||||
"#2D6997",
|
||||
"#1F4A6F",
|
||||
"#122A40",
|
||||
"#428BCA",
|
||||
"#90BAE0",
|
||||
"#DFEBF6"
|
||||
];
|
||||
|
||||
|
||||
function create_vis(chart) {
|
||||
return d3.select(chart).append("svg:svg")
|
||||
.attr("class", "chart")
|
||||
.attr("width", WIDTH)
|
||||
.attr("height", HEIGHT)
|
||||
.attr("class", "chart pie-chart")
|
||||
.attr("viewBox", "0 0 " + WIDTH + " " + HEIGHT )
|
||||
.append("g")
|
||||
.attr("transform",
|
||||
@ -99,10 +77,7 @@ horizon.d3_pie_chart_usage = {
|
||||
.enter()
|
||||
.append("path")
|
||||
.attr("class","arc")
|
||||
.attr("d", arc)
|
||||
.style("fill", BKGRND)
|
||||
.style("stroke", STROKE_USAGE)
|
||||
.style("stroke-width", 1);
|
||||
.attr("d", arc);
|
||||
|
||||
// Animate filling the pie chart
|
||||
var animate = function(data) {
|
||||
@ -110,25 +85,16 @@ horizon.d3_pie_chart_usage = {
|
||||
.data(pie(data))
|
||||
.enter()
|
||||
.append("path")
|
||||
.attr("class","arc")
|
||||
.attr("d", arc)
|
||||
.style("fill", function(){
|
||||
.attr("class", function() {
|
||||
var ret_val = "arc inner";
|
||||
if (self.data[0].percentage >= 100) {
|
||||
return FULL;
|
||||
ret_val += " FULL";
|
||||
} else if (self.data[0].percentage >= 80) {
|
||||
return NEARLY_FULL;
|
||||
} else {
|
||||
return FRGRND;
|
||||
}
|
||||
})
|
||||
.style("stroke", STROKE_USAGE)
|
||||
.style("stroke-width", function() {
|
||||
if (self.data[0].percentage <= 0 || self.data[0].percentage >= 100) {
|
||||
return 0;
|
||||
} else {
|
||||
return 1;
|
||||
ret_val += " NEARLY_FULL";
|
||||
}
|
||||
return ret_val;
|
||||
})
|
||||
.attr("d", arc)
|
||||
.transition()
|
||||
.duration(500)
|
||||
.attrTween("d", function(start) {
|
||||
@ -144,8 +110,7 @@ horizon.d3_pie_chart_usage = {
|
||||
|
||||
var show_numbers = function() {
|
||||
vis.append("text")
|
||||
.style("fill", "black")
|
||||
.style("font-size","28px")
|
||||
.attr("class", "chart-numbers")
|
||||
.attr('text-anchor', 'middle')
|
||||
.attr('dominant-baseline', 'central')
|
||||
.text(self.data);
|
||||
@ -154,6 +119,10 @@ horizon.d3_pie_chart_usage = {
|
||||
if (fill) {
|
||||
animate(self.data);
|
||||
} else {
|
||||
|
||||
// TODO: this seems to be very broken...
|
||||
// https://bugs.launchpad.net/horizon/+bug/1490787
|
||||
// It prints: [object Object] to the screen
|
||||
show_numbers(self.data);
|
||||
}
|
||||
}
|
||||
@ -161,8 +130,6 @@ horizon.d3_pie_chart_usage = {
|
||||
|
||||
|
||||
horizon.d3_pie_chart_distribution = {
|
||||
colors: BLUE_SHADES,
|
||||
|
||||
init: function() {
|
||||
var self = this;
|
||||
var pie_chart_data = $(".d3_pie_chart_distribution");
|
||||
@ -181,11 +148,11 @@ horizon.d3_pie_chart_distribution = {
|
||||
self.data.push(d);
|
||||
self.keys.push(key_value[0]);
|
||||
}
|
||||
self.pieChart(i);
|
||||
self.pieChart(i, $(pie_chart_data[i]));
|
||||
}
|
||||
},
|
||||
// Draw a pie chart
|
||||
pieChart: function(i) {
|
||||
pieChart: function(i, $elem) {
|
||||
var self = this;
|
||||
var vis = create_vis(self.chart[0][i]);
|
||||
var arc = create_arc();
|
||||
@ -207,10 +174,7 @@ horizon.d3_pie_chart_distribution = {
|
||||
.enter()
|
||||
.append("path")
|
||||
.attr("class","arc")
|
||||
.attr("d", arc)
|
||||
.style("fill", BKGRND)
|
||||
.style("stroke", STROKE_DISTRIBUTION)
|
||||
.style("stroke-width", 1);
|
||||
.attr("d", arc);
|
||||
|
||||
// Animate filling the pie chart
|
||||
var animate = function(data) {
|
||||
@ -218,13 +182,8 @@ horizon.d3_pie_chart_distribution = {
|
||||
.data(pie(data))
|
||||
.enter()
|
||||
.append("path")
|
||||
.attr("class","arc")
|
||||
.attr("class","arc inner")
|
||||
.attr("d", arc)
|
||||
.style("fill", function(d) {
|
||||
return self.colors[self.data.indexOf(d.data)];
|
||||
})
|
||||
.style("stroke", STROKE_DISTRIBUTION)
|
||||
.style("stroke-width", 1)
|
||||
.transition()
|
||||
.duration(500)
|
||||
.attrTween("d", function(start) {
|
||||
@ -240,51 +199,50 @@ horizon.d3_pie_chart_distribution = {
|
||||
animate(self.data);
|
||||
}
|
||||
|
||||
// Add a legend
|
||||
var legend = d3.select(self.chart[0][i])
|
||||
.append("svg")
|
||||
.attr("class", "legend")
|
||||
.attr("width", WIDTH * 2)
|
||||
.attr("height", self.data.length * 18 + 20)
|
||||
.selectAll("g")
|
||||
.data(self.keys)
|
||||
.enter()
|
||||
.append("g")
|
||||
.attr("transform", function(d, i) {
|
||||
return "translate(0," + i * 20 + ")";
|
||||
});
|
||||
// The legend actually doesn't need to be an SVG element at all
|
||||
// By making it standard markup, we can allow greater customization
|
||||
var $legend = $(document.createElement('div')).addClass('legend');
|
||||
|
||||
legend.append("rect")
|
||||
.attr("width", 18)
|
||||
.attr("height", 18)
|
||||
.style("fill", function(d) {
|
||||
var item;
|
||||
for (var i = 0; i < self.data.length; i++) {
|
||||
if (self.data[i].key == d) {
|
||||
item = self.data[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
return self.colors[self.data.indexOf(item)];
|
||||
});
|
||||
// This loop might seem wasteful, but we need to determine the total for the label
|
||||
var total = 0;
|
||||
for (var j = 0; j < self.data.length; j++) {
|
||||
|
||||
legend.append("text")
|
||||
.attr("x", 24)
|
||||
.attr("y", 9)
|
||||
.attr("dy", ".35em")
|
||||
.text(function(d) {
|
||||
if (total === 0) {
|
||||
return d + " 0%";
|
||||
}
|
||||
var value = 0;
|
||||
for (var j = 0; j < self.data.length; j++) {
|
||||
if (self.data[j].key == d) {
|
||||
value = self.data[j].value;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return d + " " + Math.round(value/total * 100) + "%";
|
||||
});
|
||||
// We need to use it as a float again later, convert it now and store ... its faster
|
||||
self.data[j].value = parseFloat(self.data[j].value);
|
||||
total += self.data[j].value;
|
||||
}
|
||||
|
||||
for (var j = 0; j < self.data.length; j++) {
|
||||
var this_item = self.data[j];
|
||||
var $this_group = $(document.createElement('div'))
|
||||
.addClass('legend-group')
|
||||
.appendTo($legend);
|
||||
|
||||
$(document.createElement('span'))
|
||||
.addClass('legend-symbol')
|
||||
.appendTo($this_group);
|
||||
|
||||
$(document.createElement('span'))
|
||||
.addClass('legend-key')
|
||||
.text(this_item.key)
|
||||
.appendTo($this_group);
|
||||
|
||||
var $this_value = $(document.createElement('span'))
|
||||
.addClass('legend-value');
|
||||
|
||||
// If its zero, then we don't need to Math it.
|
||||
if (this_item.value === 0) {
|
||||
$this_item.text("0%");
|
||||
} else {
|
||||
$this_value.text(Math.round((this_item.value/total) * 100) + "%");
|
||||
}
|
||||
|
||||
// Append it to the container
|
||||
$this_value.appendTo($this_group);
|
||||
}
|
||||
|
||||
// Append the container last ... cause its faster
|
||||
$elem.append($legend);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -0,0 +1,112 @@
|
||||
// General Pie Chart Styles
|
||||
|
||||
// The idea behind this mixin in to allow a variety of
|
||||
// colors to be configured, from 1 - $num, that will
|
||||
// toggle between an incrementing percentage ($increment)
|
||||
// from the theme's primary brand color. This should
|
||||
// adapt nicely to most themes.
|
||||
@mixin make_pie_chart_distribution($num, $increment) {
|
||||
@for $ii from 1 through $num {
|
||||
$color_increment: $increment * ($ii/2);
|
||||
|
||||
// Set the arc color
|
||||
.arc:nth-child(#{$ii}n) {
|
||||
@if $ii % 2 == 0 {
|
||||
fill: lighten($brand-primary, $color_increment * 1%);
|
||||
} @else {
|
||||
fill: darken($brand-primary, $color_increment * 1%);
|
||||
}
|
||||
}
|
||||
|
||||
// Set the corresponding legend symbol
|
||||
.legend-group:nth-child(#{$ii}n) .legend-symbol {
|
||||
@if $ii % 2 == 0 {
|
||||
color: lighten($brand-primary, $color_increment * 1%);
|
||||
} @else {
|
||||
color: darken($brand-primary, $color_increment * 1%);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// This is who sets the size of the pie chart
|
||||
.pie-chart {
|
||||
width: $font-size-h1*3;
|
||||
height: $font-size-h1*3;
|
||||
|
||||
// The container arc's color and stroke
|
||||
.arc {
|
||||
fill: $table-border-color;
|
||||
stroke-width: 1px;
|
||||
}
|
||||
}
|
||||
|
||||
// Chart Usage Specifics
|
||||
.d3_pie_chart_usage {
|
||||
|
||||
.arc {
|
||||
stroke: $table-border-color;
|
||||
}
|
||||
|
||||
// The inner arc
|
||||
.arc.inner {
|
||||
fill: $brand-primary;
|
||||
stroke: none;
|
||||
|
||||
// Specialness if its full
|
||||
&.FULL {
|
||||
fill: $brand-danger;
|
||||
}
|
||||
|
||||
// Specialness if its almost full
|
||||
&.NEARLY_FULL {
|
||||
fill: $brand-warning;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Chart Distribution Specifics
|
||||
.d3_pie_chart_distribution {
|
||||
|
||||
// The container arc's color and stroke
|
||||
.arc {
|
||||
stroke: $brand-primary;
|
||||
}
|
||||
|
||||
// Set the colors!
|
||||
@include make_pie_chart_distribution(8, 8);
|
||||
|
||||
.legend {
|
||||
padding: $padding-base-horizontal $padding-base-vertical;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.legend-group {
|
||||
padding: $padding-xs-horizontal $padding-small-vertical;
|
||||
}
|
||||
|
||||
.legend-symbol {
|
||||
@extend .fa;
|
||||
@extend .fa-square;
|
||||
font-size: $font-size-h3;
|
||||
padding-right: $padding-small-vertical;
|
||||
}
|
||||
|
||||
.legend-symbol,
|
||||
.legend-key,
|
||||
.legend-value {
|
||||
display: inline-block;
|
||||
line-height: $line-height-computed;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.legend-key {
|
||||
padding-right: $padding-small-vertical;
|
||||
}
|
||||
}
|
||||
|
||||
.chart-numbers {
|
||||
fill: $gray-dark;
|
||||
font-size: $font-size-h3;
|
||||
}
|
||||
|
@ -22,6 +22,7 @@
|
||||
@import "components/workflow";
|
||||
@import "components/network_topology";
|
||||
@import "components/context_selection";
|
||||
@import "components/pie_charts";
|
||||
@import "/framework/framework";
|
||||
|
||||
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
@import 'components/_context_selection';
|
||||
@import 'components/sidebar';
|
||||
@import 'components/pie_charts';
|
||||
|
||||
.navbar-brand {
|
||||
|
||||
|
@ -0,0 +1,12 @@
|
||||
.d3_pie_chart_usage {
|
||||
.arc {
|
||||
stroke: $gray-light;
|
||||
fill: $gray-lighter;
|
||||
}
|
||||
}
|
||||
|
||||
.d3_pie_chart_distribution {
|
||||
.legend-group {
|
||||
padding: 1px $padding-small-vertical;
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user