Improve responsive chart scaling and hide center label earlier
- Scale chart layers on mobile (≤500px) to fill container while keeping same hole size as desktop (20%) - Add resize handler to dynamically update proportions when crossing 500px threshold - Hide center label at 850px (stacked layout) instead of 500px to prevent overlap with chart - Center chart at 50% on mobile since details box is below Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
2b45a42b49
commit
d76e80dc02
88
app.js
88
app.js
@ -470,11 +470,25 @@ function renderChart(data) {
|
|||||||
// Gradual transition between 640-1000px
|
// Gradual transition between 640-1000px
|
||||||
const transitionProgress = (screenWidth - 640) / 360; // 0 to 1
|
const transitionProgress = (screenWidth - 640) / 360; // 0 to 1
|
||||||
centerPosition = 40 + (transitionProgress * 10); // 40 to 50
|
centerPosition = 40 + (transitionProgress * 10); // 40 to 50
|
||||||
|
} else if (screenWidth <= 500) {
|
||||||
|
// Mobile: center the chart since details box is below
|
||||||
|
centerPosition = 50;
|
||||||
} else {
|
} else {
|
||||||
// For smaller screens
|
// For smaller screens (500-640px)
|
||||||
centerPosition = 40;
|
centerPosition = 40;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Mobile: scale chart to fill container, hide outside labels
|
||||||
|
const isMobile = screenWidth <= 500;
|
||||||
|
|
||||||
|
// Mobile: extend layers to fill container, keeping same hole size as desktop
|
||||||
|
// Hole stays at 20%, layers scaled to fill remaining 80% (vs 55% on desktop)
|
||||||
|
const level1Inner = '20%';
|
||||||
|
const level1Outer = isMobile ? '56%' : '45%';
|
||||||
|
const level2Outer = isMobile ? '93%' : '70%';
|
||||||
|
const level3Outer = isMobile ? '100%' : '75%';
|
||||||
|
const outerRadius = isMobile ? '100%' : '95%';
|
||||||
|
|
||||||
option = {
|
option = {
|
||||||
backgroundColor: '#fff',
|
backgroundColor: '#fff',
|
||||||
grid: {
|
grid: {
|
||||||
@ -489,7 +503,7 @@ function renderChart(data) {
|
|||||||
//animationEasingUpdate: 'cubicInOut',
|
//animationEasingUpdate: 'cubicInOut',
|
||||||
series: {
|
series: {
|
||||||
type: 'sunburst',
|
type: 'sunburst',
|
||||||
radius: [0, '95%'],
|
radius: [0, outerRadius],
|
||||||
center: [`${centerPosition}%`, '50%'],
|
center: [`${centerPosition}%`, '50%'],
|
||||||
startAngle: 0,
|
startAngle: 0,
|
||||||
nodeClick: false,
|
nodeClick: false,
|
||||||
@ -518,8 +532,8 @@ function renderChart(data) {
|
|||||||
{},
|
{},
|
||||||
{
|
{
|
||||||
// First level - Categories
|
// First level - Categories
|
||||||
r0: '20%',
|
r0: level1Inner,
|
||||||
r: '45%',
|
r: level1Outer,
|
||||||
label: {
|
label: {
|
||||||
show: true,
|
show: true,
|
||||||
rotate: 'radial',
|
rotate: 'radial',
|
||||||
@ -538,8 +552,8 @@ function renderChart(data) {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
// Second level - Subcategories
|
// Second level - Subcategories
|
||||||
r0: '45%',
|
r0: level1Outer,
|
||||||
r: '70%',
|
r: level2Outer,
|
||||||
label: {
|
label: {
|
||||||
show: function(param) {
|
show: function(param) {
|
||||||
// Show labels for sectors that are at least 5% of the total
|
// Show labels for sectors that are at least 5% of the total
|
||||||
@ -617,16 +631,17 @@ function renderChart(data) {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
// Third level - Microcategories - a bit wider than before
|
// Third level - Microcategories
|
||||||
r0: '70%',
|
r0: level2Outer,
|
||||||
r: '75%',
|
r: level3Outer,
|
||||||
label: {
|
label: {
|
||||||
// Only show labels conditionally based on segment size
|
// Only show labels conditionally based on segment size
|
||||||
show: function(param) {
|
// On mobile, hide outside labels to maximize chart size
|
||||||
|
show: isMobile ? false : function(param) {
|
||||||
// Show label if segment is wide enough (>1%)
|
// Show label if segment is wide enough (>1%)
|
||||||
return param.percent > 0.000;
|
return param.percent > 0.000;
|
||||||
},
|
},
|
||||||
position: 'outside',
|
position: isMobile ? 'inside' : 'outside',
|
||||||
padding: 3,
|
padding: 3,
|
||||||
minAngle: 3, // Add this - default is 5, reducing it will show more labels
|
minAngle: 3, // Add this - default is 5, reducing it will show more labels
|
||||||
silent: false,
|
silent: false,
|
||||||
@ -1756,16 +1771,51 @@ function adjustChartSize() {
|
|||||||
if (!option) return;
|
if (!option) return;
|
||||||
|
|
||||||
const screenWidth = window.innerWidth;
|
const screenWidth = window.innerWidth;
|
||||||
const detailsBox = document.getElementById('details-box');
|
const isMobile = screenWidth <= 500;
|
||||||
const detailsWidth = detailsBox.offsetWidth;
|
|
||||||
|
|
||||||
// Calculate center position with a smooth transition
|
// Mobile: extend layers to fill container, keeping same hole size as desktop
|
||||||
|
// Hole stays at 20%, layers scaled to fill remaining 80% (vs 55% on desktop)
|
||||||
|
const level1Inner = '20%';
|
||||||
|
const level1Outer = isMobile ? '56%' : '45%';
|
||||||
|
const level2Outer = isMobile ? '93%' : '70%';
|
||||||
|
const level3Outer = isMobile ? '100%' : '75%';
|
||||||
|
const outerRadius = isMobile ? '100%' : '95%';
|
||||||
|
|
||||||
|
// Update layer proportions
|
||||||
|
option.series.levels[1].r0 = level1Inner;
|
||||||
|
option.series.levels[1].r = level1Outer;
|
||||||
|
option.series.levels[2].r0 = level1Outer;
|
||||||
|
option.series.levels[2].r = level2Outer;
|
||||||
|
option.series.levels[3].r0 = level2Outer;
|
||||||
|
option.series.levels[3].r = level3Outer;
|
||||||
|
option.series.radius = [0, outerRadius];
|
||||||
|
|
||||||
|
// Update level 3 labels: hide on mobile, show on desktop (with conditions)
|
||||||
|
if (isMobile) {
|
||||||
|
option.series.levels[3].label.show = false;
|
||||||
|
option.series.levels[3].label.position = 'inside';
|
||||||
|
} else if (screenWidth < 950) {
|
||||||
|
option.series.levels[3].label.show = false;
|
||||||
|
option.series.levels[3].label.position = 'outside';
|
||||||
|
} else {
|
||||||
|
option.series.levels[3].label.show = function(param) {
|
||||||
|
return param.percent > 0.000;
|
||||||
|
};
|
||||||
|
option.series.levels[3].label.position = 'outside';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calculate center position
|
||||||
let centerPosition;
|
let centerPosition;
|
||||||
|
if (screenWidth >= 1000) {
|
||||||
if (screenWidth < 950)
|
centerPosition = 50;
|
||||||
option.series.levels[3].label.show=false;
|
} else if (screenWidth >= 640) {
|
||||||
else option.series.levels[3].label.show=true;
|
const transitionProgress = (screenWidth - 640) / 360;
|
||||||
centerPosition = 50;
|
centerPosition = 40 + (transitionProgress * 10);
|
||||||
|
} else if (isMobile) {
|
||||||
|
centerPosition = 50;
|
||||||
|
} else {
|
||||||
|
centerPosition = 40;
|
||||||
|
}
|
||||||
|
|
||||||
// Update chart center position
|
// Update chart center position
|
||||||
option.series.center = [`${centerPosition}%`, '50%'];
|
option.series.center = [`${centerPosition}%`, '50%'];
|
||||||
|
|||||||
16
styles.css
16
styles.css
@ -359,6 +359,10 @@ body {
|
|||||||
.top-item-amount {
|
.top-item-amount {
|
||||||
min-width: 80px;
|
min-width: 80px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.center-label {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (max-width: 500px) {
|
@media (max-width: 500px) {
|
||||||
@ -394,10 +398,6 @@ body {
|
|||||||
gap: 4px;
|
gap: 4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.center-label {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.container {
|
.container {
|
||||||
padding: 15px 10px;
|
padding: 15px 10px;
|
||||||
}
|
}
|
||||||
@ -405,6 +405,12 @@ body {
|
|||||||
.chart-wrapper {
|
.chart-wrapper {
|
||||||
height: 95vw;
|
height: 95vw;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#chart-container {
|
||||||
|
background-color: transparent;
|
||||||
|
box-shadow: none;
|
||||||
|
border-radius: 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (max-width: 400px) {
|
@media (max-width: 400px) {
|
||||||
@ -432,7 +438,7 @@ body {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.chart-wrapper {
|
.chart-wrapper {
|
||||||
height: 98vw;
|
height: 100vw;
|
||||||
}
|
}
|
||||||
|
|
||||||
.details-header {
|
.details-header {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user