Skip to content

Commit

Permalink
Improved yLabels nice scales in VueUiXy, VueUiDonutEvolution & VueUiC…
Browse files Browse the repository at this point in the history
…andlestick
  • Loading branch information
graphieros committed Jan 28, 2024
1 parent 94aa031 commit 41f07f3
Show file tree
Hide file tree
Showing 8 changed files with 103 additions and 63 deletions.
Binary file not shown.
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "vue-data-ui",
"private": false,
"version": "1.9.66",
"version": "1.9.67",
"type": "module",
"description": "A user-empowering data visualization Vue components library",
"keywords": [
Expand Down
30 changes: 15 additions & 15 deletions src/components/vue-ui-candlestick.vue
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<script setup>
import { ref, computed, onMounted, nextTick } from "vue";
import { canShowValue, closestDecimal, shiftHue, opacity, createUid, createCsvContent, downloadCsv } from "../lib";
import { canShowValue, closestDecimal, shiftHue, opacity, createUid, createCsvContent, downloadCsv, calculateNiceScale } from "../lib";
import mainConfig from "../default_configs.json";
import pdf from "../pdf";
import img from "../img";
Expand Down Expand Up @@ -133,11 +133,15 @@ const extremes = computed(() => {
}
});
const niceScale = computed(() => {
return calculateNiceScale(extremes.value.min, extremes.value.max, 10)
})
function convertToPlot(item, index) {
return {
...item,
x: drawingArea.value.left + (index * slot.value) + (slot.value / 2),
y: drawingArea.value.top + (1 - (item / extremes.value.max)) * drawingArea.value.height,
y: drawingArea.value.top + (1 - (item / niceScale.value.max)) * drawingArea.value.height,
value: item
}
}
Expand All @@ -162,20 +166,16 @@ const drawableDataset = computed(() => {
});
function ratioToMax(value) {
return value / extremes.value.max;
return value / niceScale.value.max;
}
const yLabels = computed(() => {
const positiveStep = closestDecimal(extremes.value.max / candlestickConfig.value.style.layout.grid.yAxis.dataLabels.steps);
const steps = [];
for(let i = candlestickConfig.value.style.layout.grid.yAxis.dataLabels.steps; i >= 0; i -= 1) {
const value = positiveStep * i ;
steps.push({
y: drawingArea.value.bottom - (drawingArea.value.height * ratioToMax(positiveStep * i)),
value,
});
}
return steps;
return niceScale.value.ticks.map(t => {
return {
y: drawingArea.value.bottom - (drawingArea.value.height * ratioToMax(t)),
value: t
}
})
});
const xLabels = computed(() => {
Expand Down Expand Up @@ -402,7 +402,7 @@ defineExpose({
<g v-if="candlestickConfig.style.layout.grid.yAxis.dataLabels.show">
<g v-for="(yLabel, i) in yLabels">
<line
v-if="yLabel.value >= 0 && yLabel.value <= extremes.max"
v-if="yLabel.value >= niceScale.min && yLabel.value <= niceScale.max"
:x1="drawingArea.left"
:x2="drawingArea.left - 5"
:y1="yLabel.y"
Expand All @@ -411,7 +411,7 @@ defineExpose({
:stroke-width="candlestickConfig.style.layout.grid.strokeWidth"
/>
<text
v-if="yLabel.value >= 0 && yLabel.value <= extremes.max"
v-if="yLabel.value >= niceScale.min && yLabel.value <= niceScale.max"
:x="drawingArea.left - 8 + candlestickConfig.style.layout.grid.yAxis.dataLabels.offsetX"
:y="yLabel.y + candlestickConfig.style.layout.grid.yAxis.dataLabels.fontSize / 3"
:font-size="candlestickConfig.style.layout.grid.yAxis.dataLabels.fontSize"
Expand Down
35 changes: 19 additions & 16 deletions src/components/vue-ui-donut-evolution.vue
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<script setup>
import { ref, computed, nextTick } from "vue";
import { calcMarkerOffsetX, calcMarkerOffsetY, calcNutArrowPath, canShowValue, closestDecimal, makeDonut, palette, convertColorToHex, opacity, createUid, sumByAttribute, createCsvContent, downloadCsv } from '../lib';
import { calcMarkerOffsetX, calcMarkerOffsetY, calcNutArrowPath, canShowValue, closestDecimal, makeDonut, palette, convertColorToHex, opacity, createUid, sumByAttribute, createCsvContent, downloadCsv, calculateNiceScale } from '../lib';
import pdf from "../pdf";
import img from "../img";
import mainConfig from "../default_configs.json";
Expand Down Expand Up @@ -115,12 +115,15 @@ const drawableDataset = computed(() => {
x,
})
}
const maxSubtotal = Math.max(...arr.map(a => a.subtotal));
const minSubtotal = 0;
const maxSubtotal = Math.max(...arr.map(a => a.subtotal))
return arr.map((a, i) => {
const radiusReference = (slit.value / 2) * 0.5;
const radius = radiusReference > svg.value.width / 16 ? svg.value.width / 16 : radiusReference;
const activeRadius = hoveredIndex.value === a.index ? svg.value.width / 20 : radius;
const y = svg.value.absoluteHeight - padding.value.bottom - (svg.value.height * a.subtotal / maxSubtotal);
const y = svg.value.absoluteHeight - padding.value.bottom - (svg.value.height * a.subtotal / calculateNiceScale(minSubtotal, maxSubtotal, 10).max);
return {
...a,
y,
Expand Down Expand Up @@ -159,21 +162,21 @@ const extremes = computed(() => {
}
});
const niceScale = computed(() => {
return calculateNiceScale(extremes.value.min, extremes.value.max, 10)
})
function ratioToMax(value) {
return value / extremes.value.max;
return value / niceScale.value.max;
}
const yLabels = computed(() => {
const positiveStep = closestDecimal(extremes.value.max / donutEvolutionConfig.value.style.chart.layout.grid.yAxis.dataLabels.steps);
const steps = [];
for(let i = donutEvolutionConfig.value.style.chart.layout.grid.yAxis.dataLabels.steps; i >= 0; i -= 1) {
const value = positiveStep * i ;
steps.push({
y: svg.value.absoluteHeight - padding.value.bottom - (svg.value.height * ratioToMax(positiveStep * i)),
value,
});
}
return steps;
return niceScale.value.ticks.map(t => {
return {
y: svg.value.absoluteHeight - padding.value.bottom - (svg.value.height * ratioToMax(t)),
value: t
}
})
});
function displayArcPercentage(arc, stepBreakdown) {
Expand Down Expand Up @@ -452,7 +455,7 @@ defineExpose({
<g v-if="donutEvolutionConfig.style.chart.layout.grid.yAxis.dataLabels.show" :class="{'donut-opacity': true, 'donut-behind': hoveredIndex !== null || isFixed}">
<g v-for="(yLabel, i) in yLabels">
<line
v-if="yLabel.value >= 0 && yLabel.value <= extremes.max"
v-if="yLabel.value >= niceScale.min && yLabel.value <= niceScale.max"
:x1="padding.left"
:x2="padding.left - 5"
:y1="yLabel.y"
Expand All @@ -461,7 +464,7 @@ defineExpose({
:stroke-width="donutEvolutionConfig.style.chart.layout.grid.strokeWidth"
/>
<text
v-if="yLabel.value >= 0 && yLabel.value <= extremes.max"
v-if="yLabel.value >= niceScale.min && yLabel.value <= niceScale.max"
:x="padding.left - 8 + donutEvolutionConfig.style.chart.layout.grid.yAxis.dataLabels.offsetX"
:y="yLabel.y + donutEvolutionConfig.style.chart.layout.grid.yAxis.dataLabels.fontSize / 3"
:font-size="donutEvolutionConfig.style.chart.layout.grid.yAxis.dataLabels.fontSize"
Expand Down
4 changes: 0 additions & 4 deletions src/components/vue-ui-xy.cy.js
Original file line number Diff line number Diff line change
Expand Up @@ -99,10 +99,6 @@ describe('<VueUiXy />', () => {
cy.get(`[data-cy="xy-line-tag-end-${i}"]`).should('exist')
}

for(let i = 0; i < 11; i += 1) {
cy.get(`[data-cy="xy-label-y-${i}"]`).should('exist');
}

cy.get('[data-cy="xy-axis-xLabel"]').should('exist');
cy.get('[data-cy="xy-axis-yLabel"]').should('exist');

Expand Down
42 changes: 17 additions & 25 deletions src/components/vue-ui-xy.vue
Original file line number Diff line number Diff line change
Expand Up @@ -454,7 +454,7 @@
<g v-if="chartConfig.chart.grid.labels.show">
<g v-for="(yLabel, i) in yLabels" :key="`yLabel_${i}`">
<line
v-if="yLabel.value >= min && yLabel.value <= max"
v-if="yLabel.value >= niceScale.min && yLabel.value <= niceScale.max"
:x1="drawingArea.left"
:x2="drawingArea.left - 5"
:y1="yLabel.y"
Expand All @@ -464,7 +464,7 @@
/>
<text
:data-cy="`xy-label-y-${i}`"
v-if="yLabel.value >= min && yLabel.value <= max"
v-if="yLabel.value >= niceScale.min && yLabel.value <= niceScale.max"
:x="drawingArea.left - 7"
:y="yLabel.y + chartConfig.chart.labels.fontSize / 3"
:font-size="chartConfig.chart.grid.labels.fontSize"
Expand Down Expand Up @@ -697,7 +697,8 @@ import {
createUid,
closestDecimal,
createCsvContent,
downloadCsv
downloadCsv,
calculateNiceScale
} from '../lib';
import mainConfig from "../default_configs.json";
import DataTable from "../atoms/DataTable.vue";
Expand Down Expand Up @@ -812,11 +813,11 @@ export default {
return to - from + 1;
},
relativeZero() {
if(this.min >= 0) return 0;
return Math.abs(this.min);
if(this.niceScale.min >= 0) return 0;
return Math.abs(this.niceScale.min);
},
absoluteMax() {
return this.max + this.relativeZero;
return this.niceScale.max + this.relativeZero;
},
safeDataset(){
if(!this.useSafeValues) return this.dataset;
Expand Down Expand Up @@ -914,6 +915,9 @@ export default {
if(min > 0) return 0;
return min;
},
niceScale() {
return this.calculateNiceScale(this.min, this.max, 10)
},
maxSeries(){
return this.slicer.end - this.slicer.start;
},
Expand Down Expand Up @@ -1047,25 +1051,12 @@ export default {
return `0 0 ${this.chartConfig.chart.width} ${this.chartConfig.chart.height}`;
},
yLabels() {
const positiveStep = this.closestDecimal(this.max / 5);
const positiveSteps = [];
for(let i = 5; i > 0; i -= 1) {
const value = positiveStep * i ;
positiveSteps.push({
y: this.zero - (this.drawingArea.height * this.ratioToMax(positiveStep * i)),
value,
});
}
const negativeStep = this.closestDecimal(this.min / 5);
const negativeSteps = [];
for(let i = 5; i >= 0; i -= 1) {
const value = Math.abs(negativeStep) * i ;
negativeSteps.push({
y: this.zero + (this.drawingArea.height * this.ratioToMax(Math.abs(negativeStep) * i)),
value: -value
});
}
return [...positiveSteps, ...negativeSteps];
return this.niceScale.ticks.map(t => {
return {
y: t >= 0 ? this.zero - (this.drawingArea.height * this.ratioToMax(t)) : this.zero + (this.drawingArea.height * this.ratioToMax(Math.abs(t))),
value: t
}
})
},
zero(){
return this.drawingArea.bottom - (this.drawingArea.height * this.ratioToMax(this.relativeZero));
Expand Down Expand Up @@ -1198,6 +1189,7 @@ export default {
}
},
methods: {
calculateNiceScale,
checkNaN,
createSmoothPath,
isSafeValue,
Expand Down
49 changes: 49 additions & 0 deletions src/lib.js
Original file line number Diff line number Diff line change
Expand Up @@ -783,6 +783,55 @@ export function lightenHexColor(hexColor, percentLighter) {
return lighterHex;
}

export function niceNum(range, round) {
const exponent = Math.floor(Math.log10(range));
const fraction = range / Math.pow(10, exponent);
let niceFraction;

if (round) {
if (fraction < 1.5) {
niceFraction = 1;
} else if (fraction < 3) {
niceFraction = 2;
} else if (fraction < 7) {
niceFraction = 5;
} else {
niceFraction = 10;
}
} else {
if (fraction <= 1) {
niceFraction = 1;
} else if (fraction <= 2) {
niceFraction = 2;
} else if (fraction <= 5) {
niceFraction = 5;
} else {
niceFraction = 10;
}
}

return niceFraction * Math.pow(10, exponent);
}

export function calculateNiceScale(minValue, maxValue, maxTicks) {
const range = niceNum(maxValue - minValue, false);
const tickSpacing = niceNum(range / (maxTicks - 1), true);
const niceMin = Math.floor(minValue / tickSpacing) * tickSpacing;
const niceMax = Math.ceil(maxValue / tickSpacing) * tickSpacing;

const ticks = [];
for (let tick = niceMin; tick <= niceMax; tick += tickSpacing) {
ticks.push(tick);
}

return {
min: niceMin,
max: niceMax,
tickSize: tickSpacing,
ticks
};
}

const lib = {
adaptColorToBackground,
addVector,
Expand Down

0 comments on commit 41f07f3

Please sign in to comment.