Skip to content

Commit a467bf7

Browse files
committed
Fix #537 => Add barMixedColumnrangeWithPatternFillChart sample
1 parent b696a43 commit a467bf7

File tree

2 files changed

+214
-0
lines changed

2 files changed

+214
-0
lines changed

AAInfographicsDemo.xcodeproj/project.pbxproj

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@
6161
84123BC92DB0F0EB003DA7A0 /* AAPackedbubble.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84123BC82DB0F0EB003DA7A0 /* AAPackedbubble.swift */; };
6262
84123BCB2DB0F130003DA7A0 /* AALayoutAlgorithm.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84123BCA2DB0F130003DA7A0 /* AALayoutAlgorithm.swift */; };
6363
8418479928B8755900094106 /* JSFunctionForAAChartEventsComposer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8418479828B8755900094106 /* JSFunctionForAAChartEventsComposer.swift */; };
64+
842EB1B82DF16ECF000166C2 /* AAMixedChartComposer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 842EB1B72DF16ECF000166C2 /* AAMixedChartComposer.swift */; };
6465
842FC3EE2CBE119500FBAD3A /* CustomTooltipEventCallbackVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = 842FC3ED2CBE119500FBAD3A /* CustomTooltipEventCallbackVC.swift */; };
6566
84339F4F2D536AC900F54F1E /* SortAlgorithmVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84339F4E2D536AC900F54F1E /* SortAlgorithmVC.swift */; };
6667
84339F572D54591900F54F1E /* ChartSampleProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84339F562D54591900F54F1E /* ChartSampleProvider.swift */; };
@@ -313,6 +314,7 @@
313314
84123BC82DB0F0EB003DA7A0 /* AAPackedbubble.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AAPackedbubble.swift; sourceTree = "<group>"; };
314315
84123BCA2DB0F130003DA7A0 /* AALayoutAlgorithm.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AALayoutAlgorithm.swift; sourceTree = "<group>"; };
315316
8418479828B8755900094106 /* JSFunctionForAAChartEventsComposer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JSFunctionForAAChartEventsComposer.swift; sourceTree = "<group>"; };
317+
842EB1B72DF16ECF000166C2 /* AAMixedChartComposer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AAMixedChartComposer.swift; sourceTree = "<group>"; };
316318
842FC3ED2CBE119500FBAD3A /* CustomTooltipEventCallbackVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomTooltipEventCallbackVC.swift; sourceTree = "<group>"; };
317319
84339F4E2D536AC900F54F1E /* SortAlgorithmVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SortAlgorithmVC.swift; sourceTree = "<group>"; };
318320
84339F562D54591900F54F1E /* ChartSampleProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChartSampleProvider.swift; sourceTree = "<group>"; };
@@ -660,6 +662,7 @@
660662
84086B1928E45015006BD30D /* AAOptionsWithJS */ = {
661663
isa = PBXGroup;
662664
children = (
665+
842EB1B72DF16ECF000166C2 /* AAMixedChartComposer.swift */,
663666
44EB70A622BCB606008FECE4 /* JSFunctionForAATooltipVC.swift */,
664667
84DEB89F28F7A58900BF9423 /* JSFunctionForAATooltipVC2.swift */,
665668
84086B1A28E45127006BD30D /* JSFunctionForAAAxisVC.swift */,
@@ -1092,6 +1095,7 @@
10921095
84086B1E28E6C612006BD30D /* CustomTableViewCell.swift in Sources */,
10931096
8441C0972C620ED400A6F784 /* CustomStyleForAreasplineChartComposer.swift in Sources */,
10941097
844007742B6F3FA00072FB66 /* MixedChartVC.swift in Sources */,
1098+
842EB1B82DF16ECF000166C2 /* AAMixedChartComposer.swift in Sources */,
10951099
8441C0952C620AC900A6F784 /* CustomStyleForSplineChartVC.swift in Sources */,
10961100
84903CA02DBA24B50029FE5A /* EmojiProvider.swift in Sources */,
10971101
845BABF12D030318004C15D4 /* OfficialChartSample.swift in Sources */,
Lines changed: 210 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,210 @@
1+
//
2+
// AAMixedChartComposer.swift
3+
// AAInfographicsDemo
4+
//
5+
// Created by AnAn on 2025/6/5.
6+
// Copyright © 2025 An An. All rights reserved.
7+
//
8+
9+
import AAInfographics
10+
11+
class AAMixedChartComposer {
12+
13+
static func barMixedColumnrangeWithPatternFillChart() -> AAOptions {
14+
// 配置常量 - 使用二级枚举
15+
let Colors = [
16+
"darker": ["#603EAC", "#7560B1", "#4390AD", "#AF8D0E"],
17+
"actual": ["#8B5CF6", "#A78BFA", "#60CDF5", "#FACC15"]
18+
]
19+
20+
let Dimensions = [
21+
"pointWidth": 20 as Float,
22+
"capHeight": 32 as Float,
23+
"capWidth": 2 as Float
24+
]
25+
26+
let YAxis = [
27+
"min": 0 as Double,
28+
"max": 100 as Double,
29+
"tickInterval": 10 as Float
30+
] as [String : Any]
31+
32+
// 原始数据
33+
let sleepData = [
34+
"ideal": [
35+
["low": 20, "high": 32, "category": "深睡"],
36+
["low": 40, "high": 60, "category": "浅睡"],
37+
["low": 10, "high": 25, "category": "REM"],
38+
["low": 0, "high": 5, "category": "清醒"]
39+
],
40+
"actual": [
41+
["value": 27, "label": "1小时22分钟(27%)"],
42+
["value": 53, "label": "3小时42分钟(53%)"],
43+
["value": 18, "label": "1小时49分钟(18%)"],
44+
["value": 2, "label": "5分钟(2%)"]
45+
]
46+
]
47+
48+
/**
49+
// 数据处理函数
50+
function createCategories() {
51+
return sleepData.ideal.map(item => item.category);
52+
}
53+
54+
*/
55+
56+
// 数据处理函数
57+
func createCategories() -> [String] {
58+
return sleepData["ideal"]!.map { item in
59+
return item["category"] as! String
60+
}
61+
}
62+
63+
func createBoxplotData() -> [[String: Any]] {
64+
return sleepData["ideal"]!.enumerated().map { index, item in
65+
let low = item["low"] as! Int
66+
let high = item["high"] as! Int
67+
return [
68+
"x": index,
69+
"low": low,
70+
"q1": low,
71+
"median": low,
72+
"q3": high,
73+
"high": high,
74+
"fillColor": "url(#customPattern\(index))",
75+
"whiskerColor": Colors["darker"]![index]
76+
]
77+
}
78+
}
79+
80+
func createActualData() -> [[String: Any]] {
81+
return sleepData["actual"]!.enumerated().map { index, item in
82+
let value = item["value"] as! Int
83+
let label = item["label"] as! String
84+
return [
85+
"y": value,
86+
"color": Colors["actual"]![index],
87+
"label": label
88+
]
89+
}
90+
}
91+
92+
// 创建plotLines函数
93+
func createPlotLines() -> [AAPlotLinesElement] {
94+
return sleepData["ideal"]!.enumerated().map { index, item in
95+
let category = item["category"] as! String
96+
let label = sleepData["actual"]![index]["label"] as! String
97+
return AAPlotLinesElement()
98+
.value(Double(index))
99+
.width(0)
100+
.label(AALabel()
101+
.text("<span style=\"color:#999999\">\(category)</span> <span style=\"color:#000000\">\(label)</span>".aa_toPureHTMLString())
102+
.useHTML(true)
103+
.align(.left)
104+
.x(10)
105+
.y(-20)
106+
.style(AAStyle()
107+
.fontSize(20)))
108+
}
109+
}
110+
111+
// 图表配置
112+
let aaChart = AAChart()
113+
.type(.columnrange)
114+
.inverted(true)
115+
.events(AAChartEvents()
116+
.load("""
117+
function() {
118+
const renderer = this.renderer;
119+
let defs = renderer.defs;
120+
if (!defs) {
121+
defs = renderer.createElement('defs').add();
122+
renderer.defs = defs;
123+
}
124+
125+
const Colors = {
126+
darker: ['#603EAC', '#7560B1', '#4390AD', '#AF8D0E']
127+
};
128+
129+
const patternHTML = Colors.darker
130+
.map((color, index) => `
131+
<pattern id="customPattern${index}"
132+
patternUnits="userSpaceOnUse"
133+
width="3"
134+
height="3"
135+
patternTransform="scale(1.4 1.4)">
136+
<path d="M 0 3 L 3 0 M -0.5 0.5 L 0.5 -0.5 M 2.5 3.5 L 3.5 2.5"
137+
fill="none"
138+
stroke="${color}"
139+
stroke-width="1"
140+
stroke-dasharray="none"/>
141+
</pattern>`)
142+
.join('');
143+
144+
defs.element.innerHTML += patternHTML;
145+
}
146+
"""))
147+
148+
let aaXAxis = AAXAxis()
149+
.categories(createCategories())
150+
.lineWidth(0)
151+
.labels(AALabels()
152+
.enabled(false))
153+
.plotLines(createPlotLines())
154+
155+
let aaYAxis = AAYAxis()
156+
.min(YAxis["min"] as! Double)
157+
.max(YAxis["max"] as! Double)
158+
.tickInterval(YAxis["tickInterval"] as! Float)
159+
.title(nil)
160+
.gridLineWidth(0)
161+
.labels(AALabels().enabled(false))
162+
163+
let aaPlotOptions = AAPlotOptions()
164+
.bar(AABar()
165+
.grouping(false)
166+
.borderWidth(0)
167+
.pointWidth(Dimensions["pointWidth"] as! Float)
168+
.dataLabels(AADataLabels().enabled(false)))
169+
.boxplot(AABoxplot()
170+
.grouping(false)
171+
.lineWidth(0)
172+
.medianWidth(0)
173+
.medianColor("transparent")
174+
.stemWidth(0)
175+
// .pointWidth(Dimensions["pointWidth"] as! Float)
176+
// .whiskerLength(Dimensions["capHeight"] as! Float)
177+
.whiskerWidth(Dimensions["capWidth"] as! Float)
178+
.whiskerColor("transparent"))
179+
180+
let aaTooltip = AATooltip()
181+
.enabled(false)
182+
183+
let aaSeries = [
184+
AASeriesElement()
185+
.name("实际睡眠")
186+
.type(.bar)
187+
.data(createActualData())
188+
.zIndex(0),
189+
AASeriesElement()
190+
.name("理想睡眠区间")
191+
.type(.boxplot)
192+
.data(createBoxplotData())
193+
.zIndex(1)
194+
.showInLegend(true)
195+
.clip(false)
196+
]
197+
198+
let aaOptions = AAOptions()
199+
.chart(aaChart)
200+
.title(AATitle().text("睡眠阶段 vs 理想区间"))
201+
.xAxis(aaXAxis)
202+
.yAxis(aaYAxis)
203+
.plotOptions(aaPlotOptions)
204+
.legend(AALegend().enabled(true))
205+
.tooltip(aaTooltip)
206+
.series(aaSeries)
207+
208+
return aaOptions
209+
}
210+
}

0 commit comments

Comments
 (0)