Ray1ee01 commited on
Commit
98fcaef
·
verified ·
1 Parent(s): c8a0ba2

Upload folder using huggingface_hub

Browse files
modules/chart_engine/template/d3-js/type74_treemap/treemap_plain_chart_01.js ADDED
@@ -0,0 +1,171 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*
2
+ REQUIREMENTS_BEGIN
3
+ {
4
+ "chart_type": "Treemap",
5
+ "chart_name": "treemap_plain_chart_01",
6
+ "required_fields": ["x", "y"],
7
+ "required_fields_type": [["categorical"], ["numerical"]],
8
+ "required_fields_range": [[3, 20], [0, "inf"]],
9
+ "required_fields_icons": [],
10
+ "required_other_icons": [],
11
+ "required_fields_colors": ["x"],
12
+ "required_other_colors": [],
13
+ "supported_effects": [],
14
+ "min_height": 400,
15
+ "min_width": 600,
16
+ "background": "light",
17
+ "icon_mark": "none",
18
+ "icon_label": "none",
19
+ "has_x_axis": "no",
20
+ "has_y_axis": "no"
21
+ }
22
+ REQUIREMENTS_END
23
+ */
24
+
25
+ function makeChart(containerSelector, data) {
26
+ // 提取数据
27
+ const jsonData = data;
28
+ const chartData = jsonData.data.data;
29
+ const variables = jsonData.variables;
30
+ const typography = jsonData.typography;
31
+ const colors = jsonData.colors || {};
32
+ const colorResolver = chartUtils.color.resolver(jsonData);
33
+ const dataColumns = chartUtils.schema.columns(jsonData);
34
+ const images = jsonData.images || {};
35
+
36
+ // 清空容器
37
+ d3.select(containerSelector).html("");
38
+
39
+ // 获取字段名
40
+ const categoryField = chartUtils.schema.columnField(dataColumns, 0);
41
+ const valueField = chartUtils.schema.columnField(dataColumns, 1);
42
+
43
+ // 设置尺寸和边距
44
+ const width = variables.width;
45
+ const height = variables.height;
46
+ const margin = { top: 10, right: 10, bottom: 10, left: 10 };
47
+
48
+ // 创建SVG
49
+ const svg = d3.select(containerSelector)
50
+ .append("svg")
51
+ .attr("width", "100%")
52
+ .attr("height", height)
53
+ .attr("viewBox", `0 0 ${width} ${height}`)
54
+ .attr("style", "max-width: 100%; height: auto; font: 10px sans-serif;")
55
+ .attr("xmlns", "http://www.w3.org/2000/svg")
56
+ .attr("xmlns:xlink", "http://www.w3.org/1999/xlink");
57
+
58
+ // 创建图表区域
59
+ const chartWidth = width - margin.left - margin.right;
60
+ const chartHeight = height - margin.top - margin.bottom;
61
+
62
+ const g = svg.append("g")
63
+ .attr("transform", `translate(${margin.left}, ${margin.top})`);
64
+
65
+ // 准备层次结构数据
66
+ // 将扁平数据转换为层次结构
67
+ const hierarchyData = {
68
+ name: "root",
69
+ children: []
70
+ };
71
+
72
+ // 按类别分组数据
73
+ const groupedData = d3.group(chartData, d => d[categoryField]);
74
+
75
+ // 将分组数据转换为层次结构
76
+ groupedData.forEach((values, category) => {
77
+ // 计算该类别的总值
78
+ const total = d3.sum(values, d => +d[valueField]);
79
+
80
+ hierarchyData.children.push({
81
+ name: category,
82
+ value: total
83
+ });
84
+ });
85
+
86
+ // 创建颜色比例尺
87
+ const colorScale = d => colorResolver.field(d, hierarchyData.children.findIndex(item => item.name === d), { palette: "tableau10" }).value;
88
+
89
+ // 计算树图布局
90
+ const root = d3.treemap()
91
+ .size([chartWidth, chartHeight])
92
+ .padding(3)
93
+ .round(true)
94
+ (d3.hierarchy(hierarchyData)
95
+ .sum(d => d.value)
96
+ .sort((a, b) => b.value - a.value));
97
+
98
+ // 为每个叶子节点创建一个单元格
99
+ const leaf = g.selectAll("g")
100
+ .data(root.leaves())
101
+ .join("g")
102
+ .attr("transform", d => `translate(${d.x0},${d.y0})`);
103
+
104
+ // 添加矩形
105
+ leaf.append("rect")
106
+ .attr("width", d => Math.max(0, d.x1 - d.x0))
107
+ .attr("height", d => Math.max(0, d.y1 - d.y0))
108
+ .attr("fill", d => {
109
+ // 获取类别名称
110
+ const category = d.data.name;
111
+ return colorScale(category);
112
+ })
113
+ .attr("fill-opacity", 0.8)
114
+ .attr("stroke", "#fff");
115
+
116
+ // 为每个矩形添加工具提示
117
+ const format = value => chartUtils.format.autoText(+value);
118
+ leaf.append("title")
119
+ .text(d => `${d.data.name}: ${format(d.value)}`);
120
+
121
+ // 添加文本标签
122
+ leaf.append("text")
123
+ .attr("x", 4)
124
+ .attr("y", 14)
125
+ .attr("fill", "#fff")
126
+ .attr("font-size", "12px")
127
+ .attr("font-weight", "bold")
128
+ .text(d => d.data.name)
129
+ .each(function(d) {
130
+ // 检查文本是否适合矩形
131
+ const rectWidth = d.x1 - d.x0;
132
+ const maxTextWidth = rectWidth - 8;
133
+ const measureLabelWidth = value => chartUtils.text.measure(null, value, {
134
+ fontSize: 12,
135
+ fontWeight: "bold"
136
+ }).width;
137
+
138
+ // 如果文本太长,截断它
139
+ const text = d3.select(this);
140
+ let textContent = text.text();
141
+ let displayText = textContent;
142
+ while (measureLabelWidth(displayText) > maxTextWidth && textContent.length > 0) {
143
+ textContent = textContent.slice(0, -1);
144
+ displayText = textContent + "...";
145
+ text.text(displayText);
146
+ }
147
+ });
148
+
149
+ // 添加值标签
150
+ leaf.append("text")
151
+ .attr("x", 4)
152
+ .attr("y", 30)
153
+ .attr("fill", "#fff")
154
+ .attr("fill-opacity", 0.7)
155
+ .attr("font-size", "10px")
156
+ .text(d => format(d.value))
157
+ .each(function(d) {
158
+ // 检查文本是否适合矩形
159
+ const textWidth = chartUtils.text.measure(null, format(d.value), {
160
+ fontSize: 10
161
+ }).width;
162
+ const rectWidth = d.x1 - d.x0;
163
+
164
+ if (textWidth > rectWidth - 8 || (d.y1 - d.y0) < 40) {
165
+ // 如果文本太长或矩形太小,隐藏它
166
+ d3.select(this).style("display", "none");
167
+ }
168
+ });
169
+
170
+ return svg.node();
171
+ }
modules/chart_engine/template/d3-js/type74_treemap/treemap_plain_chart_02.js ADDED
@@ -0,0 +1,207 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*
2
+ REQUIREMENTS_BEGIN
3
+ {
4
+ "chart_type": "Treemap",
5
+ "chart_name": "treemap_plain_chart_02",
6
+ "required_fields": ["x", "y"],
7
+ "required_fields_type": [["categorical"], ["numerical"]],
8
+ "required_fields_range": [[3, 20], [0, "inf"]],
9
+ "required_fields_icons": ["x"],
10
+ "required_other_icons": [],
11
+ "required_fields_colors": ["x"],
12
+ "required_other_colors": [],
13
+ "supported_effects": [],
14
+ "min_height": 400,
15
+ "min_width": 600,
16
+ "background": "light",
17
+ "icon_mark": "overlay",
18
+ "icon_label": "none",
19
+ "has_x_axis": "no",
20
+ "has_y_axis": "no"
21
+ }
22
+ REQUIREMENTS_END
23
+ */
24
+
25
+ function makeChart(containerSelector, data) {
26
+ // 提取数据
27
+ const jsonData = data;
28
+ const chartData = jsonData.data.data;
29
+ const variables = jsonData.variables;
30
+ const typography = jsonData.typography;
31
+ const colors = jsonData.colors || {};
32
+ const colorResolver = chartUtils.color.resolver(jsonData);
33
+ const dataColumns = chartUtils.schema.columns(jsonData);
34
+ const images = jsonData.images || {};
35
+
36
+ // 清空容器
37
+ d3.select(containerSelector).html("");
38
+
39
+ // 获取字段名
40
+ const categoryField = chartUtils.schema.columnField(dataColumns, 0);
41
+ const valueField = chartUtils.schema.columnField(dataColumns, 1);
42
+ // 获取单位
43
+ const valueUnit = chartUtils.schema.column(dataColumns, 1).unit;
44
+
45
+ // 设置尺寸和边距
46
+ const width = variables.width;
47
+ const height = variables.height;
48
+ const margin = { top: 10, right: 10, bottom: 10, left: 10 };
49
+
50
+ // 创建SVG
51
+ const svg = d3.select(containerSelector)
52
+ .append("svg")
53
+ .attr("width", "100%")
54
+ .attr("height", height)
55
+ .attr("viewBox", `0 0 ${width} ${height}`)
56
+ .attr("style", "max-width: 100%; height: auto; font: 10px sans-serif;")
57
+ .attr("xmlns", "http://www.w3.org/2000/svg")
58
+ .attr("xmlns:xlink", "http://www.w3.org/1999/xlink");
59
+
60
+ // 创建图表区域
61
+ const chartWidth = width - margin.left - margin.right;
62
+ const chartHeight = height - margin.top - margin.bottom;
63
+
64
+ const g = svg.append("g")
65
+ .attr("transform", `translate(${margin.left}, ${margin.top})`);
66
+
67
+ // 准备层次结构数据
68
+ // 将扁平数据转换为层次结构
69
+ const hierarchyData = {
70
+ name: "root",
71
+ children: []
72
+ };
73
+
74
+ // 按类别分组数据
75
+ const groupedData = d3.group(chartData, d => d[categoryField]);
76
+
77
+ // 将分组数据转换为层次结构
78
+ groupedData.forEach((values, category) => {
79
+ // 计算该类别的总值
80
+ const total = d3.sum(values, d => +d[valueField]);
81
+
82
+ hierarchyData.children.push({
83
+ name: category,
84
+ value: total
85
+ });
86
+ });
87
+
88
+ // 创建颜色比例尺
89
+ const colorScale = d => colorResolver.field(d, hierarchyData.children.findIndex(item => item.name === d), { palette: "tableau10" }).value;
90
+
91
+ // 计算树图布局
92
+ const root = d3.treemap()
93
+ .size([chartWidth, chartHeight])
94
+ .padding(8)
95
+ .round(true)
96
+ (d3.hierarchy(hierarchyData)
97
+ .sum(d => d.value)
98
+ .sort((a, b) => b.value - a.value));
99
+
100
+ // 为每个叶子节点创建一个单元格
101
+ const leaf = g.selectAll("g")
102
+ .data(root.leaves())
103
+ .join("g")
104
+ .attr("transform", d => `translate(${d.x0},${d.y0})`);
105
+
106
+ // 添加矩形
107
+ leaf.append("rect")
108
+ .attr("width", d => Math.max(0, d.x1 - d.x0))
109
+ .attr("height", d => Math.max(0, d.y1 - d.y0))
110
+ .attr("rx", 8)
111
+ .attr("ry", 8)
112
+ .attr("fill", d => {
113
+ // 获取类别名称
114
+ const category = d.data.name;
115
+ return colorScale(category);
116
+ })
117
+ .attr("fill-opacity", 0.8)
118
+ .attr("stroke", "none");
119
+
120
+ // 为每个矩形添加工具提示
121
+ const format = value => chartUtils.format.autoText(+value);
122
+ leaf.append("title")
123
+ .text(d => `${d.data.name}: ${format(d.value)}`);
124
+
125
+ // 创建包含标签和图标的组
126
+ const labelGroup = leaf.append("g")
127
+ .attr("transform", "translate(12, 12)"); // 增加边距
128
+ const measureCategoryLabelWidth = value => chartUtils.text.measure(null, value, {
129
+ fontSize: 20,
130
+ fontWeight: "bold"
131
+ }).width;
132
+ const measureValueLabelWidth = value => chartUtils.text.measure(null, value, {
133
+ fontSize: 16
134
+ }).width;
135
+
136
+ // 添加类别标签 (x label) - 变大并放在左上角,使用白色
137
+ labelGroup.append("text")
138
+ .attr("class", "category-label")
139
+ .attr("x", 0)
140
+ .attr("y", 18)
141
+ .attr("fill", "#ffffff")
142
+ .attr("font-size", "20px") // 字体变得更大
143
+ .attr("font-weight", "bold") // 使用粗体
144
+ .text(d => d.data.name)
145
+ .each(function(d) {
146
+ // 检查文本是否适合矩形(考虑图标宽度)
147
+ const rectWidth = d.x1 - d.x0 - 48; // 减去图标宽度和更多间距
148
+ const maxTextWidth = rectWidth - 12;
149
+
150
+ // 如果文本太长,截断它
151
+ const text = d3.select(this);
152
+ let textContent = text.text();
153
+ let displayText = textContent;
154
+ while (measureCategoryLabelWidth(displayText) > maxTextWidth && textContent.length > 0) {
155
+ textContent = textContent.slice(0, -1);
156
+ displayText = textContent + "...";
157
+ text.text(displayText);
158
+ }
159
+ });
160
+
161
+ // 添加图标(在x label右侧)
162
+ labelGroup.each(function(d) {
163
+ const g = d3.select(this);
164
+ const categoryName = d.data.name;
165
+
166
+ // 获取图标
167
+ if (images.field && images.field[categoryName]) {
168
+ const textWidth = measureCategoryLabelWidth(g.select(".category-label").text());
169
+
170
+ // 添加白色填充的圆形背景
171
+ g.append("circle")
172
+ .attr("cx", textWidth + 30) // 放在文本右侧,向右移动10px
173
+ .attr("cy", 10) // 向下移动10px
174
+ .attr("r", 22) // 半径增加到22 (17+5)
175
+ .attr("fill", "#ffffff") // 纯白色填充
176
+ .attr("fill-opacity", 0.75) // 75%透明度
177
+ .attr("stroke", "none"); // 移除描边
178
+
179
+ g.append("image")
180
+ .attr("x", textWidth + 14) // 放在文本右侧,向右移动10px
181
+ .attr("y", -6) // 调整y位置,向下移动10px
182
+ .attr("width", 32)
183
+ .attr("height", 32)
184
+ .attr("xlink:href", images.field[categoryName]);
185
+ }
186
+ });
187
+
188
+ // 添加值标签 (data label) - 放在x label下方,使用黑色,添加单位
189
+ labelGroup.append("text")
190
+ .attr("x", 0)
191
+ .attr("y", 42) // 放在x label下方
192
+ .attr("fill", "#000000") // 使用黑色
193
+ .attr("font-size", "16px") // 字体变大
194
+ .text(d => `${format(d.value)}${valueUnit}`) // 添加单位
195
+ .each(function(d) {
196
+ // 检查文本是否适合矩形
197
+ const textWidth = measureValueLabelWidth(`${format(d.value)}${valueUnit}`);
198
+ const rectWidth = d.x1 - d.x0;
199
+
200
+ if (textWidth > rectWidth - 24 || (d.y1 - d.y0) < 70) {
201
+ // 如果文本太长或矩形太小,隐藏它
202
+ d3.select(this).style("display", "none");
203
+ }
204
+ });
205
+
206
+ return svg.node();
207
+ }