Skip to content

Commit 2c49efd

Browse files
committed
Improvement - VueUiXy - Improve series layout in stacked mode; add option to set x axis crosshairs always on zero axis
1 parent d4a1c70 commit 2c49efd

File tree

6 files changed

+65
-20
lines changed

6 files changed

+65
-20
lines changed

TestingArena/ArenaVueUiXy.vue

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -112,8 +112,8 @@ function createDs(n, m = 100) {
112112
const dataset = ref([
113113
{
114114
name: "A",
115-
series: [null, 100, 112, 221, 119, 75, null, 226, 243, 198, 156, 127, null],
116-
type: "line",
115+
series: [null, 100, 112, 221, 119, 75, null, -226, -243, 198, 156, 127, null],
116+
type: "bar",
117117
dataLabels: false,
118118
},
119119
{
@@ -122,6 +122,12 @@ const dataset = ref([
122122
type: "line",
123123
dataLabels: false,
124124
},
125+
{
126+
name: "C",
127+
series: [null, 75, 11, 20, 10, 8, null, 20, 22, 204, 146, 117, null],
128+
type: "plot",
129+
dataLabels: false,
130+
},
125131
// {
126132
// name: "A",
127133
// series: [null, 100, 112, 221, 119, 75, 213, 226, 243, 198, 156, 127, null],
@@ -419,7 +425,7 @@ const model = ref([
419425
{ key: 'chart.highlightArea.caption.padding', def: 3, type: 'number', min: 0, max: 48, label: 'captionPadding', category: 'highlight' },
420426
{ key: 'chart.highlightArea.caption.textAlign', def: 'center', type: 'select', options: ['left', 'center', 'right'], label: 'textAlign', category: 'highlight' },
421427
422-
{ key: 'chart.grid.stroke', def: '#FF0000', type: 'color', label: 'lineColor', category: 'grid' },
428+
{ key: 'chart.grid.stroke', def: '#CCCCCC', type: 'color', label: 'lineColor', category: 'grid' },
423429
{ key: 'chart.grid.showVerticalLines', def: true, type: 'checkbox', label: 'verticalLines', category: 'grid' },
424430
{ key: 'chart.grid.showHorizontalLines', def: true, type: 'checkbox', label: 'verticalLines', category: 'grid' },
425431
@@ -452,7 +458,7 @@ const model = ref([
452458
{ key: 'chart.grid.labels.yAxis.commonScaleSteps', def: 10, min: 0, max: 100, type: 'number' },
453459
{ key: 'chart.grid.labels.yAxis.useIndividualScale', def: false, type: "checkbox" },
454460
{ key: 'chart.grid.labels.yAxis.stacked', def: false, type: 'checkbox' },
455-
{ key: 'chart.grid.labels.yAxis.gap', def: 12, min: 0, max: 200, type: 'number' },
461+
{ key: 'chart.grid.labels.yAxis.gap', def: 24, min: 0, max: 200, type: 'number' },
456462
{ key: 'chart.grid.labels.yAxis.labelWidth', def: 48, min: 0, max: 100, type: 'number' },
457463
{ key: 'chart.grid.labels.yAxis.showBaseline', def: true, type: 'checkbox' },
458464
{ key: 'chart.grid.labels.yAxis.scaleMin', def: null, type: 'number', min: -1000, max: 1000 },
@@ -464,6 +470,8 @@ const model = ref([
464470
465471
{ key: 'chart.grid.labels.yAxis.showCrosshairs', def: true, type: 'checkbox'},
466472
{ key: 'chart.grid.labels.xAxis.showCrosshairs', def: true, type: 'checkbox'},
473+
{ key: 'chart.grid.labels.xAxis.crosshairSize', def: 6, type: 'number', min: 0, max: 24},
474+
{ key: 'chart.grid.labels.xAxis.crosshairsAlwaysAtZero', def: false, type: 'checkbox'},
467475
468476
{ key: 'chart.grid.labels.xAxis.showBaseline', def: true, type: 'checkbox' },
469477
{ key: 'chart.grid.labels.zeroLine.show', def: true, type: 'checkbox' },

src/components/vue-ui-xy.vue

Lines changed: 44 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -230,14 +230,14 @@
230230
<line
231231
data-cy="axis-x-tick"
232232
v-if="FINAL_CONFIG.chart.grid.labels.xAxis.showCrosshairs"
233-
:y1="drawingArea.bottom"
234-
:y2="drawingArea.bottom + FINAL_CONFIG.chart.grid.labels.xAxis.crosshairSize"
233+
:y1="FINAL_CONFIG.chart.grid.labels.xAxis.crosshairsAlwaysAtZero ? zero - (zero === drawingArea.bottom ? 0 : FINAL_CONFIG.chart.grid.labels.xAxis.crosshairSize / 2) : drawingArea.bottom"
234+
:y2="FINAL_CONFIG.chart.grid.labels.xAxis.crosshairsAlwaysAtZero ? zero + (FINAL_CONFIG.chart.grid.labels.xAxis.crosshairSize / (zero === drawingArea.bottom ? 1 : 2)) : drawingArea.bottom + FINAL_CONFIG.chart.grid.labels.xAxis.crosshairSize"
235235
:x1="drawingArea.left + (drawingArea.width / maxSeries) * i + (drawingArea.width / maxSeries / 2)"
236236
:x2="drawingArea.left + (drawingArea.width / maxSeries) * i + (drawingArea.width / maxSeries / 2)"
237237
:stroke="FINAL_CONFIG.chart.grid.stroke"
238238
:stroke-width="1"
239239
stroke-linecap="round"
240-
:style="{ animation: 'none !important '}"
240+
:style="{ animation: 'none !important'}"
241241
/>
242242
</template>
243243
</g>
@@ -2138,7 +2138,15 @@ export default {
21382138
return result;
21392139
},
21402140
barSet() {
2141-
return this.activeSeriesWithStackRatios.filter(s => s.type === 'bar').map((datapoint, i) => {
2141+
const stackSeries = this.activeSeriesWithStackRatios
2142+
.filter(s => ['bar','line','plot'].includes(s.type));
2143+
const totalSeries = stackSeries.length;
2144+
const gap = this.FINAL_CONFIG.chart.grid.labels.yAxis.gap;
2145+
const stacked = this.mutableConfig.isStacked;
2146+
const totalGap = stacked ? gap * (totalSeries - 1) : 0
2147+
const usableHeight = this.drawingArea.height - totalGap;
2148+
2149+
return stackSeries.filter(s => s.type === 'bar').map((datapoint, i) => {
21422150
this.checkAutoScaleError(datapoint);
21432151
const min = this.scaleGroups[datapoint.scaleLabel].min;
21442152
const max = this.scaleGroups[datapoint.scaleLabel].max;
@@ -2170,9 +2178,11 @@ export default {
21702178
const individualMax = individualScale.max + individualZero;
21712179
const autoScaleMax = autoScaleSteps.max + Math.abs(autoScaleZero);
21722180
2173-
const yOffset = this.mutableConfig.isStacked ? (this.drawingArea.height * (1 - datapoint.cumulatedStackRatio)) : 0;
2174-
2175-
const individualHeight = this.mutableConfig.isStacked ? (this.drawingArea.height * datapoint.stackRatio) - this.FINAL_CONFIG.chart.grid.labels.yAxis.gap : this.drawingArea.height;
2181+
const origIdx = datapoint.stackIndex;
2182+
const flippedIdx = totalSeries - 1 - origIdx;
2183+
const flippedLowerRatio = stacked ? 1 - datapoint.cumulatedStackRatio : 0;
2184+
const yOffset = stacked ? usableHeight * flippedLowerRatio + gap * flippedIdx : 0;
2185+
const individualHeight = stacked ? usableHeight * datapoint.stackRatio : this.drawingArea.height;
21762186
21772187
const zeroPosition = this.drawingArea.bottom - yOffset - ((individualHeight) * individualZero / individualMax);
21782188
const autoScaleZeroPosition = this.drawingArea.bottom - yOffset - (individualHeight * autoScaleZero / autoScaleMax);
@@ -2276,7 +2286,15 @@ export default {
22762286
})
22772287
},
22782288
lineSet() {
2279-
return this.activeSeriesWithStackRatios.filter(s => s.type === 'line').map((datapoint) => {
2289+
const stackSeries = this.activeSeriesWithStackRatios
2290+
.filter(s => ['bar','line','plot'].includes(s.type));
2291+
const totalSeries = stackSeries.length;
2292+
const gap = this.FINAL_CONFIG.chart.grid.labels.yAxis.gap;
2293+
const stacked = this.mutableConfig.isStacked;
2294+
const totalGap = stacked ? gap * (totalSeries - 1) : 0
2295+
const usableHeight = this.drawingArea.height - totalGap;
2296+
2297+
return stackSeries.filter(s => s.type === 'line').map((datapoint, i) => {
22802298
this.checkAutoScaleError(datapoint);
22812299
22822300
const min = this.scaleGroups[datapoint.scaleLabel].min;
@@ -2309,9 +2327,11 @@ export default {
23092327
const individualMax = individualScale.max + Math.abs(individualZero);
23102328
const autoScaleMax = autoScaleSteps.max + Math.abs(autoScaleZero);
23112329
2312-
const yOffset = this.mutableConfig.isStacked ? (this.drawingArea.height * (1 - datapoint.cumulatedStackRatio)) : 0;
2313-
2314-
const individualHeight = this.mutableConfig.isStacked ? (this.drawingArea.height * datapoint.stackRatio) - this.FINAL_CONFIG.chart.grid.labels.yAxis.gap : this.drawingArea.height;
2330+
const origIdx = datapoint.stackIndex;
2331+
const flippedIdx = totalSeries - 1 - origIdx;
2332+
const flippedLowerRatio = stacked ? 1 - datapoint.cumulatedStackRatio : 0;
2333+
const yOffset = stacked ? usableHeight * flippedLowerRatio + gap * flippedIdx : 0;
2334+
const individualHeight = stacked ? usableHeight * datapoint.stackRatio : this.drawingArea.height;
23152335
23162336
const zeroPosition = this.drawingArea.bottom - yOffset - ((individualHeight) * individualZero / individualMax);
23172337
@@ -2453,7 +2473,14 @@ export default {
24532473
});
24542474
},
24552475
plotSet() {
2456-
return this.activeSeriesWithStackRatios.filter(s => s.type === 'plot').map((datapoint) => {
2476+
const stackSeries = this.activeSeriesWithStackRatios.filter(s => ['bar','line','plot'].includes(s.type));
2477+
const totalSeries = stackSeries.length;
2478+
const gap = this.FINAL_CONFIG.chart.grid.labels.yAxis.gap;
2479+
const stacked = this.mutableConfig.isStacked;
2480+
const totalGap = stacked ? gap * (totalSeries - 1) : 0;
2481+
const usableHeight = this.drawingArea.height - totalGap;
2482+
2483+
return stackSeries.filter(s => s.type === 'plot').map((datapoint) => {
24572484
this.checkAutoScaleError(datapoint);
24582485
const min = this.scaleGroups[datapoint.scaleLabel].min;
24592486
const max = this.scaleGroups[datapoint.scaleLabel].max;
@@ -2486,9 +2513,11 @@ export default {
24862513
const individualMax = individualScale.max + individualZero;
24872514
const autoScaleMax = autoScaleSteps.max + Math.abs(autoScaleZero);
24882515
2489-
const yOffset = this.mutableConfig.isStacked ? (this.drawingArea.height * (1 - datapoint.cumulatedStackRatio)) : 0;
2490-
2491-
const individualHeight = this.mutableConfig.isStacked ? (this.drawingArea.height * datapoint.stackRatio) - this.FINAL_CONFIG.chart.grid.labels.yAxis.gap : this.drawingArea.height;
2516+
const origIdx = datapoint.stackIndex;
2517+
const flippedIdx = totalSeries - 1 - origIdx;
2518+
const flippedLowerRatio = stacked ? 1 - datapoint.cumulatedStackRatio : 0;
2519+
const yOffset = stacked ? usableHeight * flippedLowerRatio + gap * flippedIdx : 0;
2520+
const individualHeight = stacked ? usableHeight * datapoint.stackRatio : this.drawingArea.height;
24922521
24932522
const zeroPosition = this.drawingArea.bottom - yOffset - ((individualHeight) * individualZero / individualMax);
24942523
const autoScaleZeroPosition = this.drawingArea.bottom - yOffset - (individualHeight * autoScaleZero / autoScaleMax);

src/lib.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1727,10 +1727,11 @@ export function assignStackRatios(arr) {
17271727
}));
17281728

17291729
let cumulatedRatio = 0;
1730-
output = output.map(item => {
1730+
output = output.map((item, i) => {
17311731
cumulatedRatio += item.stackRatio;
17321732
return {
17331733
...item,
1734+
stackIndex: i,
17341735
cumulatedStackRatio: cumulatedRatio
17351736
};
17361737
});

src/useConfig.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -522,6 +522,7 @@ export function useConfig() {
522522
xAxis: {
523523
showBaseline: false,
524524
showCrosshairs: true,
525+
crosshairsAlwaysAtZero: false,
525526
crosshairSize: 6,
526527
},
527528
yAxis: {

tests/lib.test.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1745,18 +1745,21 @@ describe("assignStackRatios", () => {
17451745
series: [1, 2, 3],
17461746
stackRatio: 0.5,
17471747
cumulatedStackRatio: 0.5,
1748+
stackIndex: 0,
17481749
},
17491750
{
17501751
name: "B",
17511752
series: [1, 2, 3],
17521753
stackRatio: 0.25,
17531754
cumulatedStackRatio: 0.75,
1755+
stackIndex: 1
17541756
},
17551757
{
17561758
name: "C",
17571759
series: [1, 2, 3],
17581760
stackRatio: 0.25,
17591761
cumulatedStackRatio: 1,
1762+
stackIndex: 2
17601763
},
17611764
];
17621765

@@ -1777,12 +1780,14 @@ describe("assignStackRatios", () => {
17771780
series: [1, 2, 3],
17781781
stackRatio: 0.5,
17791782
cumulatedStackRatio: 0.5,
1783+
stackIndex: 0
17801784
},
17811785
{
17821786
name: "A",
17831787
series: [1, 2, 3],
17841788
stackRatio: 0.5,
17851789
cumulatedStackRatio: 1,
1790+
stackIndex: 1
17861791
},
17871792
];
17881793

types/vue-data-ui.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2773,6 +2773,7 @@ declare module "vue-data-ui" {
27732773
showBaseline?: boolean;
27742774
showCrosshairs?: boolean;
27752775
crosshairSize?: number;
2776+
crosshairsAlwaysAtZero?: boolean;
27762777
};
27772778
xAxisLabels?: {
27782779
color?: string;

0 commit comments

Comments
 (0)