Skip to content

Commit f9bd3fb

Browse files
committed
feat: d3-charts template package
1 parent 664dbfe commit f9bd3fb

File tree

3 files changed

+189
-19
lines changed
  • packages

3 files changed

+189
-19
lines changed

packages/cubejs-playground/src/libraries/d3.js

Lines changed: 15 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
import * as d3 from 'd3';
22

33
const drawFrame = `// Set the dimensions and margins of the graph
4-
var margin = {top: 10, right: 30, bottom: 30, left: 60},
5-
width = node.clientWidth - margin.left - margin.right, height = 400 - margin.top - margin.bottom;
4+
const margin = {top: 10, right: 30, bottom: 30, left: 60},
5+
width = node.clientWidth - margin.left - margin.right,
6+
height = 400 - margin.top - margin.bottom;
67
78
d3.select(node).html("");
8-
var svg = d3.select(node)
9+
const svg = d3.select(node)
910
.append("svg")
1011
.attr("width", width + margin.left + margin.right)
1112
.attr("height", height + margin.top + margin.bottom)
@@ -14,28 +15,28 @@ const drawFrame = `// Set the dimensions and margins of the graph
1415
"translate(" + margin.left + "," + margin.top + ")");`;
1516

1617
const yAxis = (max) => (`// Add Y axis
17-
var y = d3.scaleLinear()
18+
const y = d3.scaleLinear()
1819
.domain([0, ${max}])
1920
.range([ height, 0 ]);
2021
svg.append("g")
2122
.call(d3.axisLeft(y));`);
2223

2324
const xAxisTime = `// Add X axis
24-
var x = d3.scaleTime()
25+
const x = d3.scaleTime()
2526
.domain(d3.extent(resultSet.chartPivot(), c => d3.isoParse(c.x)))
2627
.range([ 0, width ]);
2728
svg.append("g")
2829
.attr("transform", "translate(0," + height + ")")
2930
.call(d3.axisBottom(x));`;
3031

3132
const stackData = `// Transform data into D3 format
32-
var keys = resultSet.seriesNames().map(s => s.key)
33+
const keys = resultSet.seriesNames().map(s => s.key)
3334
const data = d3.stack()
3435
.keys(keys)
3536
(resultSet.chartPivot())
3637
3738
// Color palette
38-
var color = d3.scaleOrdinal()
39+
const color = d3.scaleOrdinal()
3940
.domain(keys)
4041
.range(COLORS_SERIES)`;
4142

@@ -47,7 +48,7 @@ const drawByChartType = {
4748
}));
4849
4950
// color palette
50-
var color = d3.scaleOrdinal()
51+
const color = d3.scaleOrdinal()
5152
.domain(data.map(d => d.key ))
5253
.range(COLORS_SERIES)
5354
@@ -74,7 +75,7 @@ const drawByChartType = {
7475
${stackData}
7576
7677
// Add X axis
77-
var x = d3.scaleBand()
78+
const x = d3.scaleBand()
7879
.range([ 0, width ])
7980
.domain(resultSet.chartPivot().map(c => c.x))
8081
.padding(0.3);
@@ -123,10 +124,10 @@ const drawByChartType = {
123124
const data_ready = d3.pie()(data);
124125
125126
// The radius of the pieplot is half the width or half the height (smallest one).
126-
var radius = Math.min(400, 400) / 2 - 40;
127+
const radius = Math.min(400, 400) / 2 - 40;
127128
128129
// Seprate container to center align pie chart
129-
var pieContainer = svg.attr('height', height)
130+
const pieContainer = svg.attr('height', height)
130131
.append('g')
131132
.attr('transform', 'translate(' + width/2 + ',' + height/2 +')');
132133
@@ -140,7 +141,6 @@ const drawByChartType = {
140141
.outerRadius(radius)
141142
)
142143
.attr('fill', d => COLORS_SERIES[d.index])
143-
.style("opacity", 0.7)
144144
`
145145
};
146146

@@ -154,13 +154,9 @@ const draw = (node, resultSet, chartType) => {
154154
${drawByChartType[chartType]}
155155
}
156156
157-
const ${renderFnName} = ({ resultSet }) => {
158-
return (
159-
<div
160-
ref={el => el && draw(el, resultSet, '${chartType}')}
161-
/>
162-
);
163-
};
157+
const ${renderFnName} = ({ resultSet }) => (
158+
<div ref={el => el && draw(el, resultSet, '${chartType}')} />
159+
)
164160
`
165161
);
166162

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
const TemplatePackage = require("../../TemplatePackage");
2+
const ChartRendererSnippet = require("../../ChartRendererSnippet");
3+
4+
class D3Template extends TemplatePackage {
5+
constructor(chartLibrary) {
6+
super({
7+
name: 'd3-charts',
8+
fileToSnippet: {
9+
'/src/components/ChartRenderer.js': new ChartRendererSnippet(chartLibrary)
10+
},
11+
type: 'charts',
12+
version: '0.0.1'
13+
});
14+
}
15+
}
16+
17+
module.exports = D3Template;
Lines changed: 157 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,157 @@
1+
import * as d3 from 'd3';
2+
3+
const COLORS_SERIES = ["#FF6492", "#141446", "#7A77FF"];
4+
const CHART_HEIGHT = 300;
5+
6+
const drawPieChart = (node, resultSet) => {
7+
const data = resultSet.series()[0].series.map(s => s.value);
8+
const data_ready = d3.pie()(data);
9+
10+
d3.select(node).html("");
11+
12+
// The radius of the pieplot is half the width or half the height (smallest one).
13+
const radius = CHART_HEIGHT / 2 - 40;
14+
15+
// Seprate container to center align pie chart
16+
const svg = d3.select(node)
17+
.append("svg")
18+
.attr("width", node.clientWidth)
19+
.attr("height", CHART_HEIGHT)
20+
.append("g")
21+
.attr('transform', 'translate(' + node.clientWidth/2 + ',' + CHART_HEIGHT/2 +')');
22+
23+
svg
24+
.selectAll('pieArcs')
25+
.data(data_ready)
26+
.enter()
27+
.append('path')
28+
.attr('d', d3.arc()
29+
.innerRadius(0)
30+
.outerRadius(radius)
31+
)
32+
.attr('fill', d => COLORS_SERIES[d.index])
33+
}
34+
35+
const drawChart = (node, resultSet, chartType) => {
36+
if (chartType === 'pie') {
37+
return drawPieChart(node, resultSet);
38+
}
39+
40+
const margin = { top: 10, right: 30, bottom: 30, left: 60 },
41+
width = node.clientWidth - margin.left - margin.right,
42+
height = CHART_HEIGHT - margin.top - margin.bottom;
43+
44+
d3.select(node).html("");
45+
const svg = d3.select(node)
46+
.append("svg")
47+
.attr("width", width + margin.left + margin.right)
48+
.attr("height", height + margin.top + margin.bottom)
49+
.append("g")
50+
.attr("transform",
51+
"translate(" + margin.left + "," + margin.top + ")");
52+
53+
const keys = resultSet.seriesNames().map(s => s.key)
54+
55+
let data, maxData;
56+
if (chartType === 'line') {
57+
data = resultSet.series().map((series) => ({
58+
key: series.title, values: series.series
59+
}));
60+
maxData = d3.max(data.map((s) => d3.max(s.values, (i) => i.value)))
61+
} else {
62+
data = d3.stack()
63+
.keys(keys)
64+
(resultSet.chartPivot())
65+
maxData = d3.max(data.map((s) => d3.max(s, (i) => i[1])))
66+
}
67+
68+
69+
const color = d3.scaleOrdinal()
70+
.domain(keys)
71+
.range(COLORS_SERIES);
72+
73+
let x;
74+
if (chartType === 'bar') {
75+
x = d3.scaleBand()
76+
.range([ 0, width ])
77+
.domain(resultSet.chartPivot().map(c => c.x))
78+
.padding(0.3);
79+
} else {
80+
x = d3.scaleTime()
81+
.domain(d3.extent(resultSet.chartPivot(), c => d3.isoParse(c.x)))
82+
.range([ 0, width ]);
83+
}
84+
85+
svg.append("g")
86+
.attr("transform", "translate(0," + height + ")")
87+
.call(d3.axisBottom(x));
88+
89+
const y = d3.scaleLinear()
90+
.domain([0, maxData])
91+
.range([ height, 0 ]);
92+
svg.append("g")
93+
.call(d3.axisLeft(y));
94+
95+
if (chartType === 'line') {
96+
svg.selectAll(".line")
97+
.data(data)
98+
.enter()
99+
.append("path")
100+
.attr("fill", "none")
101+
.attr("stroke", d => color(d.key))
102+
.attr("stroke-width", 1.5)
103+
.attr("d", (d) => {
104+
return d3.line()
105+
.x(d => x(d3.isoParse(d.x)))
106+
.y(d => y(+d.value))
107+
(d.values)
108+
})
109+
} else if (chartType === 'area') {
110+
svg
111+
.selectAll("mylayers")
112+
.data(data)
113+
.enter().append("path")
114+
.style("fill", d => color(d.key))
115+
.attr("d", d3.area()
116+
.x(d => x(d3.isoParse(d.data.x)))
117+
.y0(d => y(d[0]))
118+
.y1(d => y(d[1]))
119+
)
120+
} else {
121+
svg.append("g")
122+
.selectAll("g")
123+
// Enter in the stack data = loop key per key = group per group
124+
.data(data)
125+
.enter().append("g")
126+
.attr("fill", d => color(d.key))
127+
.selectAll("rect")
128+
// enter a second time = loop subgroup per subgroup to add all rectangles
129+
.data(d => d)
130+
.enter().append("rect")
131+
.attr("x", d => x(d.data.x))
132+
.attr("y", d => y(d[1]))
133+
.attr("height", d => y(d[0]) - y(d[1]))
134+
.attr("width",x.bandwidth())
135+
}
136+
}
137+
138+
const D3Chart = ({ resultSet, type }) => (
139+
<div
140+
ref={el => el && drawChart(el, resultSet, type)}
141+
/>
142+
);
143+
144+
const TypeToChartComponent = {
145+
line: ({ resultSet }) => (
146+
<D3Chart type='line' resultSet={resultSet} />
147+
),
148+
bar: ({ resultSet }) => (
149+
<D3Chart type='bar' resultSet={resultSet} />
150+
),
151+
area: ({ resultSet }) => (
152+
<D3Chart type='area' resultSet={resultSet} />
153+
),
154+
pie: ({ resultSet }) => (
155+
<D3Chart type='pie' resultSet={resultSet} />
156+
),
157+
};

0 commit comments

Comments
 (0)