Skip to content

Commit

Permalink
feat(arc): Intent to ship arc.needle
Browse files Browse the repository at this point in the history
Implement arc.needle option

Close #3205
  • Loading branch information
netil authored and netil committed May 18, 2023
1 parent 8981211 commit 04e90aa
Show file tree
Hide file tree
Showing 20 changed files with 1,010 additions and 28 deletions.
4 changes: 2 additions & 2 deletions demo/chart.js
Expand Up @@ -386,7 +386,7 @@ var billboardDemo = {
.replace("_plugins", "plugins")
.replace(new RegExp('"?'+ this.replacer.plugin +'"?', "g"), "");

if (/(polarChart|multiline)/i.test(options.bindto)) {
if (/(polarChart|multiline|gaugeneedle)/i.test(options.bindto)) {
codeStr = codeStr.replace(/\\n(?=(\t|\s+))/g, "")
.replace(/\\\\n(?=[a-zA-Z0-9])/g, "\\n")
.replace('+"\\\\n"+', '+"\\n+"');
Expand Down Expand Up @@ -485,7 +485,7 @@ var billboardDemo = {
code.data.push("\r\n\r\n" + func.toString()
.replace(/[\t\s]*function\s*\(chart[\d+]?\) \{[\r\n\t\s]*/, "")
.replace(/}$/, "")
.replace(/chart.timer = \[[\r\n\t\s]*/, "")
.replace(/chart[\d]?.timer = \[[\r\n\t\s]*/, "")
.replace(/\t{5}/g, "")
.replace(/[\r\n\t\s]*\];?[\r\n\t\s]*$/, "")
.replace(/(\d)\),?/g, "$1);"));
Expand Down
171 changes: 171 additions & 0 deletions demo/demo.js
Expand Up @@ -4892,6 +4892,98 @@ d3.select(".chart_area")
}
}
},
DonutNeedle: [
{
options: {
title: {
text: "Custom Needle"
},
data: {
columns: [
["data1", 10],
["data2", 10],
["data3", 10],
["data4", 10],
["data5", 10],
["data6", 10]
],
type: "donut"
},
donut: {
title: "( {=NEEDLE_VALUE} )"
},
arc: {
needle: {
show: true,
value: 13,
path: function(length) {
const len = length - 20;
const path = `M 0 -${len + 20}
L -12 -${len}
L -5 -${len}
L -5 0
A 1 1 0 0 0 5 0
L 5 -${len}
L 12 -${len} Z`;

return path;
},
length: 55
}
}
}
},
{
options: {
data: {
columns: [
["data1", 25],
["data2", 25],
["data3", 25],
["data4", 25]
],
type: "donut"
},
donut: {
title: "{=NEEDLE_VALUE}%"
},
arc: {
needle: {
show: true,
color: "red",
length: 80,
top: {
width: 5,
rx: 1,
ry: 1
}
}
}
},
func: function(chart2) {
chart2.timer = [
setTimeout(function() {
chart2.$.needle.updateHelper(25)
}, 1000),

setTimeout(function() {
chart2.$.needle.updateHelper(50)
}, 2000),

setTimeout(function() {
chart2.$.needle.updateHelper(75)
}, 3000),

setTimeout(function() {
chart2.$.needle.updateHelper(0)
}, 4000)
];
},
style: [
"#donutNeedle_1 .bb-chart-arcs-title, #donutNeedle_2 .bb-chart-arcs-title {font-size: 3em;fill: blue;transform: translateY(40px);}"
]
}
],
LabelRatio: {
options: {
data: {
Expand Down Expand Up @@ -5064,6 +5156,85 @@ d3.select(".chart_area")
}
}
},
GaugeNeedle: [
{
options: {
data: {
columns: [
["Poor", 20],
["Fair", 20],
["Good", 20],
["Great", 20],
["Excellent", 20]
],
type: "gauge"
},
size: {
height: 220
},
interaction: {
enabled: false
},
legend: {
show: false
},
gauge: {
width: 10,
title: "Total Quality\n{=NEEDLE_VALUE}%",
label: {
format: function(value, ratio, id) { return id; }
}
},
arc: {
needle: {
show: true,
value: 0
}
}
},
func: function(chart) {
chart.timer = [
setTimeout(function() { chart.$.needle.updateHelper(77, true); }, 1000),
];
},
style: [
"#gaugeNeedle_1 .bb-chart-arcs-gauge-title tspan:first-child { font-size:0.3em;}",
"#gaugeNeedle_1 .bb-chart-arcs-gauge-title { transform:translateY(-80px);font-size:4em; }",
"#gaugeNeedle_2 .bb-chart-arcs-gauge-title { font-size:3.5em;fill:red;transform:translateY(-40px); }"
]
},
{
options: {
data: {
columns: [
["data", 80]
],
type: "gauge"
},
size: {
height: 220
},
arc: {
needle: {
show: true,
length: 80,
color: "rgb(2 253 15 / 39%)",
top: {
width: 5
},
bottom: {
rx: 0,
ry: 0,
width: 5
}
}
},
gauge: {
title: "{=NEEDLE_VALUE}%",
}
}
},
],
GaugeStackData: [
{
options: {
Expand Down
21 changes: 21 additions & 0 deletions demo/tomorrow.css
Expand Up @@ -135,3 +135,24 @@ code.html {
#fitPadding_2 svg {
border: 1px dashed red;
}

#donutNeedle_1 .bb-chart-arcs-title, #donutNeedle_2 .bb-chart-arcs-title {
font-size: 3em;
fill: blue;
transform: translateY(40px);
}

#gaugeNeedle_1 .bb-chart-arcs-gauge-title tspan:first-child {
font-size: 0.3em;
}

#gaugeNeedle_1 .bb-chart-arcs-gauge-title {
transform: translateY(-80px);
font-size: 4em;
}

#gaugeNeedle_2 .bb-chart-arcs-gauge-title {
font-size: 3.5em;
fill: red;
transform: translateY(-20px);
}
31 changes: 30 additions & 1 deletion src/Chart/Chart.ts
Expand Up @@ -39,6 +39,10 @@ import apiTooltip from "./api/tooltip";
* @property {d3.selection} $.svg Main svg element
* @property {d3.selection} $.defs Definition element
* @property {d3.selection} $.main Main grouping element
* @property {d3.selection} $.needle Needle element
* - **NOTE:**
* - The element will have `bb-needle` as class name.
* - Will provide speical helper `.updateHelper(value: number, updateConfig: boolean)` method to facilitate needle position update.
* @property {d3.selection} $.tooltip Tooltip element
* @property {d3.selection} $.legend Legend element
* @property {d3.selection} $.title Title element
Expand All @@ -55,10 +59,35 @@ import apiTooltip from "./api/tooltip";
* @property {d3.selection} $.text.texts Data label text elements
* @memberof Chart
* @example
* var chart = bb.generate({ ... });
* const chart = bb.generate({ ... });
*
* chart.$.chart; // wrapper element
* chart.$.line.circles; // all data point circle elements
* @example
* // Update arc needle position
* const chart = bb.generate({
* data: {
* type: "donut"
* },
* arc: {
* needle: {
* show: true,
* ...
* }
* }
* });
*
* chart.$.needle.updateHelper(70); // update needle position to point value 70.
*
* // update needle position to point value 70 and the config value.
* // NOTE: updating config value, will update needle pointer initial value too.
* chart.$.needle.updateHelper(70, true);
*
* // update needle point position every 1 second
* let i = 0;
* setInterval(() => {
* chart.$.needle.updateHelper(i += 10);
* }, 1000)
*/
/**
* Plugin instance array
Expand Down
4 changes: 3 additions & 1 deletion src/ChartInternal/ChartInternal.ts
Expand Up @@ -574,7 +574,7 @@ export default class ChartInternal {
setChartElements(): void {
const $$ = this;
const {$el: {
chart, svg, defs, main, tooltip, legend, title, grid,
chart, svg, defs, main, tooltip, legend, title, grid, needle,
arcs: arc,
circle: circles,
bar: bars,
Expand All @@ -584,6 +584,7 @@ export default class ChartInternal {
text: texts,
}} = $$;

// public
$$.api.$ = {
chart,
svg,
Expand All @@ -598,6 +599,7 @@ export default class ChartInternal {
bar: {bars},
candlestick,
line: {lines, areas},
needle,
text: {texts}
};
}
Expand Down
3 changes: 2 additions & 1 deletion src/ChartInternal/data/data.ts
Expand Up @@ -930,7 +930,8 @@ export default {

// otherwise, based on the rendered angle value
} else {
const gaugeArcLength = config.gauge_fullCircle ? $$.getArcLength() : $$.getStartAngle() * -2;
const gaugeArcLength = config.gauge_fullCircle ?
$$.getArcLength() : $$.getGaugeStartAngle() * -2;
const arcLength = $$.hasType("gauge") ? gaugeArcLength : Math.PI * 2;

ratio = (d.endAngle - d.startAngle) / arcLength;
Expand Down
6 changes: 5 additions & 1 deletion src/ChartInternal/internals/size.ts
Expand Up @@ -325,6 +325,10 @@ export default {
const subchartHeight = config.subchart_show && !isNonAxis ?
(config.subchart_size_height + subchartXAxisHeight) : 0;

// when needle is shown with legend, it need some bottom space to not overlap with legend text
const gaugeHeight = $$.hasType("gauge") && config.arc_needle_show &&
!config.gauge_fullCircle && !config.gauge_label_show ? 10 : 0;

const padding = $$.getCurrentPadding();

// for main
Expand All @@ -336,7 +340,7 @@ export default {
} : {
top: (isFitPadding ? 0 : 4) + padding.top, // for top tick text
right: isNonAxis ? 0 : $$.getCurrentPaddingRight(true),
bottom: xAxisHeight + subchartHeight + legendHeightForBottom + padding.bottom,
bottom: gaugeHeight + xAxisHeight + subchartHeight + legendHeightForBottom + padding.bottom,
left: isNonAxis ? 0 : padding.left
};

Expand Down

0 comments on commit 04e90aa

Please sign in to comment.