Skip to content

Commit

Permalink
feat(gauge): Intent to ship stack data
Browse files Browse the repository at this point in the history
- Implement stack data handling for gauge type
- Implement gauge.title option
- Make multiline text functionality as separate util funciton

Fix #580
  • Loading branch information
netil committed May 30, 2019
1 parent 173990b commit 0d7fb3e
Show file tree
Hide file tree
Showing 13 changed files with 256 additions and 125 deletions.
46 changes: 44 additions & 2 deletions demo/demo.js
Expand Up @@ -3261,7 +3261,7 @@ d3.select(".chart_area")
}
}
},
MultilneTitle: {
MultilineTitle: {
options: {
data: {
columns: [
Expand Down Expand Up @@ -3322,7 +3322,49 @@ d3.select(".chart_area")
}
}
}
}
},
GaugeStackData: [
{
options: {
data: {
columns: [
["data1", 30, 10],
["data2", 190],
["data3", 70],
["data4", 150],
["data5", 50]
],
type: "gauge",
order: "asc"
},
gauge: {
title: "Title A"
}
}
},
{
options: {
data: {
columns: [
["data1", 100],
["data2", 150]
],
type: "gauge",
order: null
},
gauge: {
max: 500,
title: "Title B",
label: {
format: function(value, ratio) {
return value;
}
},
width: 80
}
}
}
]
},
LineChartOptions: {
HidePoints: {
Expand Down
2 changes: 1 addition & 1 deletion spec/internals/legend-spec.js
Expand Up @@ -71,7 +71,7 @@ describe("LEGEND", () => {
it("should be located on the right of chart", () => {
const x = util.parseNum(chart.$.legend.attr("transform"));

expect(x).to.be.closeTo(584, 1);
expect(x).to.be.closeTo(584, 3);
});
});

Expand Down
105 changes: 93 additions & 12 deletions spec/shape/shape.arc-spec.js
Expand Up @@ -344,7 +344,7 @@ describe("SHAPE ARC", () => {
expect(max.empty()).to.be.true;
});

it("check for fullCircle option", () => {
it("check for fullCircle option", done => {
const chart = util.generate({
gauge: {
width: 10,
Expand All @@ -354,25 +354,106 @@ describe("SHAPE ARC", () => {
},
data: {
columns: [
["data", 75]
["data", 10]
],
type: "gauge"
}
});

const chartArc = chart.$.main.select(`.${CLASS.chartArcs}`);
const min = chartArc.select(`.${CLASS.chartArcsGaugeMin}`);
const max = chartArc.select(`.${CLASS.chartArcsGaugeMax}`);
setTimeout(() => {
const chartArc = chart.$.main.select(`.${CLASS.chartArcs}`);
const min = chartArc.select(`.${CLASS.chartArcsGaugeMin}`);
const max = chartArc.select(`.${CLASS.chartArcsGaugeMax}`);

// check if gauge value text is centered
expect(+chartArc.select(`.${CLASS.gaugeValue}`).attr("dy")).to.be.above(0);
// check if gauge value text is centered
expect(+chartArc.select(`.${CLASS.gaugeValue}`).attr("dy")).to.be.above(0);

// check background height
expect(chartArc.select(`.${CLASS.chartArcsBackground}`).node().getBBox().height).to.be.above(400);
// check background height
expect(chartArc.select(`.${CLASS.chartArcsBackground}`).node().getBBox().height).to.be.above(400);

// with fullCircle option, only min text is showed
expect(min.empty()).to.be.false;
expect(max.empty()).to.be.true;
// with fullCircle option, only min text is showed
expect(min.empty()).to.be.false;
expect(max.empty()).to.be.true;

done();
}, 100);
});

it("check for stack data #1", done => {
const chart = util.generate({
size: {
width: 640,
height: 480
},
data: {
columns: [
["data1", 50, 10],
["data2", 200],
["data3", 70],
["data4", 50],
["data5", 50],
],
type: "gauge",
order: null
}
});

const expected = [
"M-304,-3.7229262694079536e-14A304,304,0,0,1,-275.25626419791655,-129.03483645824778L-165.15375851874995,-77.42090187494867A182.4,182.4,0,0,0,-182.4,-2.2337557616447722e-14Z",
"M-275.25626419791655,-129.03483645824778A304,304,0,0,1,98.15564305051961,-287.71769103991323L58.893385830311765,-172.63061462394796A182.4,182.4,0,0,0,-165.15375851874995,-77.42090187494867Z",
"M98.15564305051961,-287.71769103991323A304,304,0,0,1,226.4107435541097,-202.86491861156077L135.84644613246581,-121.71895116693646A182.4,182.4,0,0,0,58.893385830311765,-172.63061462394796Z",
"M226.4107435541097,-202.86491861156077A304,304,0,0,1,283.9408970546946,-108.59819049954436L170.36453823281676,-65.15891429972662A182.4,182.4,0,0,0,135.84644613246581,-121.71895116693646Z",
"M283.9408970546946,-108.59819049954436A304,304,0,0,1,304,0L182.4,0A182.4,182.4,0,0,0,170.36453823281676,-65.15891429972662Z"
];

setTimeout(() => {
chart.$.arc.selectAll(`.${CLASS.target} path`).each(function(d, i) {
expect(this.getAttribute("d")).to.be.equal(expected[i]);
});

done();
}, 100);
});

it("check for stack data #2", done => {
const args = {
size: {
width: 640,
height: 480
},
data: {
columns: [
["data1", 50],
["data2", 200]
],
type: "gauge",
order: "desc"
},
gauge: {
min: 50,
max: 550,
title: "TitleText"
}
};
const chart = util.generate(args);

const expected = [
"M-93.941166289984,-289.1211809537267A304,304,0,0,1,1.8614631347039768e-14,-304L1.1168778808223861e-14,-182.4A182.4,182.4,0,0,0,-56.364699773990395,-173.47270857223603Z",
"M-304,-3.7229262694079536e-14A304,304,0,0,1,-93.941166289984,-289.1211809537267L-56.364699773990395,-173.47270857223603A182.4,182.4,0,0,0,-182.4,-2.2337557616447722e-14Z"
];

setTimeout(() => {
const data = chart.data();

expect(chart.$.arc.select(`.${CLASS.chartArcsGaugeTitle}`).text()).to.be.equal(args.gauge.title);

chart.$.arc.selectAll(`.${CLASS.target} path`).each(function(d, i) {
expect(d.value).to.be.equal(data[i].values[0].value);
expect(this.getAttribute("d")).to.be.equal(expected[i]);
});

done();
}, 100);
});
});

Expand Down
3 changes: 3 additions & 0 deletions src/config/Options.js
Expand Up @@ -3048,6 +3048,7 @@ export default class Options {
* @property {Number} [gauge.min=0] Set min value of the gauge.
* @property {Number} [gauge.max=100] Set max value of the gauge.
* @property {Number} [gauge.startingAngle=-1 * Math.PI / 2]
* @property {String} [gauge.title=""] Set title of gauge chart. Use `\n` character to enter line break.
* @property {String} [gauge.units] Set units of the gauge.
* @property {Number} [gauge.width] Set width of gauge chart.
* @example
Expand All @@ -3073,6 +3074,7 @@ export default class Options {
* },
* min: -100,
* max: 200,
* title: "Title Text",
* units: "%",
* width: 10
* }
Expand All @@ -3084,6 +3086,7 @@ export default class Options {
gauge_max: 100,
gauge_startingAngle: -1 * Math.PI / 2,
gauge_label_extents: undefined,
gauge_title: "",
gauge_units: undefined,
gauge_width: undefined,
gauge_expand: {},
Expand Down
1 change: 1 addition & 0 deletions src/config/classes.js
Expand Up @@ -31,6 +31,7 @@ export default {
chartArcsGaugeMin: "bb-chart-arcs-gauge-min",
chartArcsGaugeUnit: "bb-chart-arcs-gauge-unit",
chartArcsTitle: "bb-chart-arcs-title",
chartArcsGaugeTitle: "bb-chart-arcs-gauge-title",
chartBar: "bb-chart-bar",
chartBars: "bb-chart-bars",
chartLine: "bb-chart-line",
Expand Down
12 changes: 8 additions & 4 deletions src/data/data.js
Expand Up @@ -323,8 +323,8 @@ extend(ChartInternal.prototype, {

/**
* Get total data sum
* @private
* @return {Number}
* @private
*/
getTotalDataSum() {
const $$ = this;
Expand Down Expand Up @@ -414,7 +414,7 @@ extend(ChartInternal.prototype, {
filterTargetsToShow(targets) {
const $$ = this;

return targets.filter(t => $$.isTargetToShow(t.id));
return (targets || $$.data.targets).filter(t => $$.isTargetToShow(t.id));
},

mapTargetsToUniqueXs(targets) {
Expand Down Expand Up @@ -497,6 +497,10 @@ extend(ChartInternal.prototype, {
return false;
},

hasMultiTargets() {
return this.filterTargetsToShow().length > 1;
},

hasNegativeValueInTargets(targets) {
return this.checkValueInTargets(targets, v => v < 0);
},
Expand All @@ -507,9 +511,9 @@ extend(ChartInternal.prototype, {

_checkOrder(type) {
const config = this.config;
const order = config.data_order;

return isString(config.data_order) &&
config.data_order.toLowerCase() === type;
return isString(order) && order.toLowerCase() === type;
},

isOrderDesc() {
Expand Down
9 changes: 2 additions & 7 deletions src/internals/title.js
Expand Up @@ -3,7 +3,7 @@
* billboard.js project is licensed under the MIT license
*/
import ChartInternal from "./ChartInternal";
import {extend, isNumber} from "./util";
import {extend, isNumber, setTextValue} from "./util";
import CLASS from "../config/classes";

/**
Expand Down Expand Up @@ -44,12 +44,7 @@ extend(ChartInternal.prototype, {
.style("text-anchor", getTextPos($$.config.title_position))
.attr("class", CLASS.title);

$$.config.title_text.split("\n").forEach((v, i) => {
text.append("tspan")
.attr("x", 0)
.attr("dy", `${i ? "1.5" : ".3"}em`)
.text(v);
});
setTextValue(text, $$.config.title_text, [0.3, 1.5]);
}
},

Expand Down
29 changes: 29 additions & 0 deletions src/internals/util.js
Expand Up @@ -76,6 +76,34 @@ const callFn = (fn, ...args) => {
*/
const sanitise = str => (isString(str) ? str.replace(/</g, "&lt;").replace(/>/g, "&gt;") : str);

/**
* Set text value. If there's multiline add nodes.
* @param {d3Selection} node Text node
* @param {String} text Text value string
* @param {Array} lineHeight Line height value for multilined text
*/
const setTextValue = (node, text, lineHeight = [-1, 1]) => {
if (text.indexOf("\n") === -1) {
node.text(text);
} else {
const diff = [node.text(), text].map(v => v.replace(/[\s\n]/g, ""));

if (diff[0] !== diff[1]) {
const multiline = text.split("\n");

// reset possible text
node.html("");

multiline.forEach((v, i) => {
node.append("tspan")
.attr("x", 0)
.attr("dy", `${i === 0 ? lineHeight[0] : lineHeight[1]}em`)
.text(v);
});
}
}
};

// substitution of SVGPathSeg API polyfill
const getRectSegList = path => {
/*
Expand Down Expand Up @@ -370,6 +398,7 @@ export {
mergeArray,
notEmpty,
sanitise,
setTextValue,
sortValue,
toArray,
tplProcess
Expand Down
5 changes: 5 additions & 0 deletions src/scss/billboard.scss
Expand Up @@ -215,6 +215,11 @@
font-size: 1.3em;
}

.bb-chart-arcs-gauge-title {
dominant-baseline: middle;
font-size: 2.7em;
}

.bb-chart-arcs {
.bb-chart-arcs-background {
fill: #e0e0e0;
Expand Down
5 changes: 5 additions & 0 deletions src/scss/theme/graph.scss
Expand Up @@ -285,6 +285,11 @@ rect.bb-circle, use.bb-circle {
font-size: 1.3em;
}

.bb-chart-arcs-gauge-title {
dominant-baseline: middle;
font-size: 2.7em;
}

.bb-chart-arcs {
.bb-chart-arcs-background {
fill: #e0e0e0;
Expand Down
5 changes: 5 additions & 0 deletions src/scss/theme/insight.scss
Expand Up @@ -265,6 +265,11 @@ rect.bb-circle, use.bb-circle {
font-size: 1.3em;
}

.bb-chart-arcs-gauge-title {
dominant-baseline: middle;
font-size: 2.7em;
}

.bb-chart-arcs {
.bb-chart-arcs-background {
fill: #e0e0e0;
Expand Down

0 comments on commit 0d7fb3e

Please sign in to comment.