@@ -7,6 +7,13 @@ const props = defineProps<{
7
7
after: CompilationSections ;
8
8
}>();
9
9
10
+ enum CompareMode {
11
+ // / Useful for comparing the fractional parts of sections
12
+ Fractional ,
13
+ // / Useful for comparing the absolute durations of sections
14
+ Absolute ,
15
+ }
16
+
10
17
function calculateTotalSectionsDuration(sections : CompilationSections ): number {
11
18
return sections .sections .reduce ((accum , section ) => accum + section .value , 0 );
12
19
}
@@ -18,6 +25,10 @@ const afterTotalWidth = computed(() => {
18
25
return calculateTotalSectionsDuration (props .after );
19
26
});
20
27
28
+ const maxTotalWidth = computed (() => {
29
+ return Math .max (beforeTotalWidth .value , afterTotalWidth .value );
30
+ });
31
+
21
32
const SECTIONS_PALETTE = [
22
33
" #7768AE" ,
23
34
" #FFCf96" ,
@@ -58,6 +69,18 @@ function formatPercent(
58
69
return ` ${percent .toFixed (2 )}% ` ;
59
70
}
60
71
72
+ function getRowWidth(row : number ): number {
73
+ if (compareMode .value === CompareMode .Fractional ) {
74
+ if (row === 0 ) {
75
+ return beforeTotalWidth .value ;
76
+ } else {
77
+ return afterTotalWidth .value ;
78
+ }
79
+ } else {
80
+ return maxTotalWidth .value ;
81
+ }
82
+ }
83
+
61
84
const chartRows: ComputedRef <Array <[string , CompilationSections ]>> = computed (
62
85
() => [
63
86
[" Before" , props .before ],
@@ -89,66 +112,88 @@ function activate(section: string) {
89
112
function deactivate() {
90
113
activeSection .value = null ;
91
114
}
115
+
116
+ const compareMode = ref (CompareMode .Absolute );
92
117
</script >
93
118
94
119
<template >
95
- <div class =" wrapper" >
96
- <div class =" chart-wrapper" >
97
- <div class =" chart" v-for =" ([label, sections], rowIndex) in chartRows" >
98
- <span class =" label" >{{ label }}</span >
99
- <div class =" section-wrapper" >
100
- <div
101
- v-for =" (section, index) in sections.sections"
102
- :class =" {section: true, active: activeSection === section.name}"
103
- @mouseenter =" activate(section.name)"
104
- @mouseleave =" deactivate"
105
- :style =" {
106
- width: calculate_width(
107
- section.value,
108
- rowIndex == 0 ? beforeTotalWidth : afterTotalWidth
109
- ),
110
- backgroundColor: getSectionColor(index),
111
- }"
112
- >
120
+ <div >
121
+ <div class =" wrapper" >
122
+ <div class =" chart-wrapper" >
123
+ <div class =" chart" v-for =" ([label, sections], rowIndex) in chartRows" >
124
+ <span class =" label" >{{ label }}</span >
125
+ <div class =" section-wrapper" >
113
126
<div
114
- class =" description"
115
- v-if =" rowIndex == 1 && activeSection === section.name"
127
+ v-for =" (section, index) in sections.sections"
128
+ :class =" {section: true, active: activeSection === section.name}"
129
+ @mouseenter =" activate(section.name)"
130
+ @mouseleave =" deactivate"
131
+ :style =" {
132
+ width: calculate_width(section.value, getRowWidth(rowIndex)),
133
+ backgroundColor: getSectionColor(index),
134
+ }"
116
135
>
117
- <div >
118
- < b >{{ section.name }}</ b >
119
- </ div >
120
- < div >
136
+ <div
137
+ class = " description "
138
+ v-if = " rowIndex == 1 && activeSection === section.name "
139
+ >
121
140
<div >
122
- {{ formatPercent(props.before, section.name) }} ->
123
- {{ formatPercent(props.after, section.name) }}
141
+ <b >{{ section.name }}</b >
124
142
</div >
125
143
<div >
126
- {{
127
- getSectionByName(props.before, section.name)?.value ?? "??"
128
- }}
129
- ->
130
- {{
131
- getSectionByName(props.after, section.name)?.value ?? "??"
132
- }}
144
+ <div >
145
+ {{ formatPercent(props.before, section.name) }} ->
146
+ {{ formatPercent(props.after, section.name) }}
147
+ </div >
148
+ <div >
149
+ {{
150
+ getSectionByName(props.before, section.name)?.value ??
151
+ "??"
152
+ }}
153
+ ->
154
+ {{
155
+ getSectionByName(props.after, section.name)?.value ?? "??"
156
+ }}
157
+ </div >
133
158
</div >
134
159
</div >
135
160
</div >
136
161
</div >
137
162
</div >
138
163
</div >
164
+ <div class =" legend" >
165
+ <div
166
+ class =" item"
167
+ v-for =" item in legendItems"
168
+ @mouseenter =" activate(item.section.name)"
169
+ @mouseleave =" deactivate"
170
+ >
171
+ <div
172
+ :class =" {color: true, active: activeSection === item.section.name}"
173
+ :style =" {backgroundColor: item.color}"
174
+ ></div >
175
+ <div class =" name" >{{ item.label }}</div >
176
+ </div >
177
+ </div >
139
178
</div >
140
- <div class =" legend " >
179
+ <div class =" controls " >
141
180
<div
142
- class =" item"
143
- v-for =" item in legendItems"
144
- @mouseenter =" activate(item.section.name)"
145
- @mouseleave =" deactivate"
181
+ :class =" {control: true, selected: compareMode === CompareMode.Absolute}"
182
+ @click =" compareMode = CompareMode.Absolute"
183
+ title =" Normalize chart width to the duration of the longer collection. Useful for comparing absolute durations of sections."
146
184
>
147
- <div
148
- :class =" {color: true, active: activeSection === item.section.name}"
149
- :style =" {backgroundColor: item.color}"
150
- ></div >
151
- <div class =" name" >{{ item.label }}</div >
185
+ Absolute
186
+ </div >
187
+   ; /  ;
188
+ <div
189
+ :class =" {
190
+ control: true,
191
+ selected: compareMode === CompareMode.Fractional,
192
+ }"
193
+ @click =" compareMode = CompareMode.Fractional"
194
+ title =" Normalize chart width to the duration of its collection. Useful for comparing percentual fractions of sections."
195
+ >
196
+ Relative
152
197
</div >
153
198
</div >
154
199
</div >
@@ -223,4 +268,20 @@ function deactivate() {
223
268
}
224
269
}
225
270
}
271
+
272
+ .controls {
273
+ display : flex ;
274
+ justify-content : center ;
275
+
276
+ .control {
277
+ cursor : pointer ;
278
+
279
+ & :hover {
280
+ text-decoration : underline ;
281
+ }
282
+ & .selected {
283
+ font-weight : bold ;
284
+ }
285
+ }
286
+ }
226
287
</style >
0 commit comments