Improve center label and details box styling
- Move center label from ECharts canvas to HTML overlay for better font rendering - Style ₽ symbol separately with lighter color (#888) and slightly smaller size (20px) - Use tighter line height (1.0) for center label - Remove "Детали" heading from details box, use total as header - Remove top border from details header - Increase header font sizes to 20px - Add more whitespace above "Top Items:" Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
fbbf94c3c4
commit
c441d5979f
55
app.js
55
app.js
@ -1,10 +1,21 @@
|
||||
// Format RUB amount: no decimals, thin space (U+2009) as thousands separator
|
||||
// Format RUB amount: no decimals, narrow no-break space as thousands separator
|
||||
function formatRUB(amount) {
|
||||
return Math.round(amount)
|
||||
.toLocaleString('ru-RU')
|
||||
.replace(/\u00a0/g, '\u202F');
|
||||
}
|
||||
|
||||
// Update HTML center label (month in gray, category optional, amount in black)
|
||||
function updateCenterLabel(month, amount, category = null) {
|
||||
const labelEl = document.getElementById('center-label');
|
||||
if (!labelEl) return;
|
||||
|
||||
labelEl.querySelector('.center-month').textContent = month;
|
||||
labelEl.querySelector('.center-category').textContent = category || '';
|
||||
labelEl.querySelector('.center-amount-num').textContent = formatRUB(amount);
|
||||
labelEl.querySelector('.center-rub').textContent = '\u202F₽';
|
||||
}
|
||||
|
||||
// Initialize the chart
|
||||
const chartDom = document.getElementById('chart-container');
|
||||
const myChart = echarts.init(chartDom);
|
||||
@ -50,13 +61,8 @@ function navigateToHistoryState(state) {
|
||||
const russianMonth = getRussianMonthName(document.getElementById('month-select').value);
|
||||
option.series.data = state.data;
|
||||
|
||||
if (state.contextName) {
|
||||
option.graphic.elements[0].style.text = `${russianMonth}\n${state.contextName}\n${formatRUB(state.total)}\u202F₽`;
|
||||
} else {
|
||||
option.graphic.elements[0].style.text = russianMonth + '\n' + formatRUB(state.total) + '\u202F₽';
|
||||
}
|
||||
|
||||
myChart.setOption(option, { replaceMerge: ['series'] });
|
||||
updateCenterLabel(russianMonth, state.total, state.contextName);
|
||||
setupHoverEvents({ total: state.total, data: state.data }, state.contextName);
|
||||
|
||||
// Restore drill path and update mini-charts
|
||||
@ -705,22 +711,7 @@ function renderChart(data) {
|
||||
}
|
||||
},
|
||||
graphic: {
|
||||
elements: [
|
||||
{
|
||||
type: 'text',
|
||||
left: 'center',
|
||||
top: 'middle',
|
||||
z: 100,
|
||||
style: {
|
||||
text: russianMonth + '\n' + formatRUB(sunburstData.total) + '\u202F₽',
|
||||
fontFamily: '-apple-system, BlinkMacSystemFont, "SF Pro", "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif',
|
||||
fontWeight: 'bold',
|
||||
fontSize: 18,
|
||||
textAlign: 'left',
|
||||
fill: '#000'
|
||||
}
|
||||
}
|
||||
]
|
||||
elements: [] // Center label is now HTML overlay
|
||||
}
|
||||
};
|
||||
|
||||
@ -914,9 +905,8 @@ function renderChart(data) {
|
||||
|
||||
// Update the center text to show the drilled-down category
|
||||
const russianMonth = getRussianMonthName(document.getElementById('month-select').value);
|
||||
option.graphic.elements[0].style.text = `${russianMonth}\n${params.name}\n${formatRUB(params.value)}\u202F₽`;
|
||||
|
||||
myChart.setOption(option, { replaceMerge: ['series'] });
|
||||
updateCenterLabel(russianMonth, params.value, params.name);
|
||||
|
||||
// Update hover events with the new data structure, passing the drilled-down name
|
||||
setupHoverEvents({ total: params.value, data: newData }, params.name);
|
||||
@ -928,6 +918,9 @@ function renderChart(data) {
|
||||
|
||||
myChart.setOption(option);
|
||||
|
||||
// Update HTML center label
|
||||
updateCenterLabel(russianMonth, sunburstData.total);
|
||||
|
||||
// Add click handler for the center to go back in history
|
||||
const zr = myChart.getZr();
|
||||
zr.on('click', function(params) {
|
||||
@ -1685,11 +1678,6 @@ async function selectMonth(index) {
|
||||
|
||||
// Update the total amount in the center text
|
||||
const russianMonth = getRussianMonthName(month);
|
||||
if (targetName) {
|
||||
option.graphic.elements[0].style.text = `${russianMonth}\n${targetName}\n${formatRUB(targetTotal)}\u202F₽`;
|
||||
} else {
|
||||
option.graphic.elements[0].style.text = russianMonth + '\n' + formatRUB(targetTotal) + '\u202F₽';
|
||||
}
|
||||
|
||||
myChart.setOption({
|
||||
series: [{
|
||||
@ -1698,13 +1686,14 @@ async function selectMonth(index) {
|
||||
layoutAnimation: true,
|
||||
animationDuration: 500,
|
||||
animationEasing: 'cubicInOut'
|
||||
}],
|
||||
graphic: option.graphic
|
||||
}]
|
||||
}, {
|
||||
lazyUpdate: false,
|
||||
silent: false
|
||||
});
|
||||
|
||||
updateCenterLabel(russianMonth, targetTotal, targetName);
|
||||
|
||||
// Update hover events
|
||||
setupHoverEvents({ total: targetTotal, data: targetData }, targetName);
|
||||
|
||||
@ -1780,8 +1769,6 @@ function adjustChartSize() {
|
||||
|
||||
// Update chart center position
|
||||
option.series.center = [`${centerPosition}%`, '50%'];
|
||||
option.graphic.elements[0].left = 'center';
|
||||
option.graphic.elements[0].top = 'middle';
|
||||
|
||||
myChart.setOption(option);
|
||||
}
|
||||
|
||||
@ -21,6 +21,11 @@
|
||||
</div>
|
||||
<div class="content-wrapper">
|
||||
<div id="chart-container"></div>
|
||||
<div id="center-label" class="center-label">
|
||||
<div class="center-month"></div>
|
||||
<div class="center-category"></div>
|
||||
<div class="center-amount"><span class="center-amount-num"></span><span class="center-rub"></span></div>
|
||||
</div>
|
||||
<button id="chart-eye-btn" class="chart-eye-btn" title="View transactions">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5">
|
||||
<path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z"/>
|
||||
@ -28,7 +33,6 @@
|
||||
</svg>
|
||||
</button>
|
||||
<div id="details-box" class="details-box">
|
||||
<h3>Детали</h3>
|
||||
<div id="details-header" class="details-header">
|
||||
<span class="hover-name">Hover over a segment to see details</span>
|
||||
<span class="hover-amount"></span>
|
||||
|
||||
52
styles.css
52
styles.css
@ -140,6 +140,51 @@ body {
|
||||
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
/* Center label overlay */
|
||||
.center-label {
|
||||
position: absolute;
|
||||
left: 35%; /* Half of chart-container width (70% / 2) */
|
||||
top: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
text-align: left;
|
||||
pointer-events: none;
|
||||
font-family: -apple-system, BlinkMacSystemFont, "SF Pro", "Segoe UI", system-ui, sans-serif;
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
.center-month {
|
||||
font-size: 18px;
|
||||
font-weight: 400;
|
||||
color: #666;
|
||||
line-height: 1.0;
|
||||
}
|
||||
|
||||
.center-category {
|
||||
font-size: 18px;
|
||||
font-weight: 600;
|
||||
color: #333;
|
||||
line-height: 1.0;
|
||||
}
|
||||
|
||||
.center-category:empty {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.center-amount {
|
||||
font-size: 22px;
|
||||
font-weight: 700;
|
||||
line-height: 1.0;
|
||||
}
|
||||
|
||||
.center-amount-num {
|
||||
color: #000;
|
||||
}
|
||||
|
||||
.center-rub {
|
||||
color: #888;
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
/* Override ECharts default pointer cursor - only eye button should have pointer */
|
||||
#chart-container canvas {
|
||||
cursor: default !important;
|
||||
@ -174,7 +219,7 @@ body {
|
||||
}
|
||||
|
||||
#details-box h4 {
|
||||
margin: 10px 0 5px;
|
||||
margin: 18px 0 5px;
|
||||
color: #555;
|
||||
font-size: 14px;
|
||||
}
|
||||
@ -186,7 +231,6 @@ body {
|
||||
margin-bottom: 20px;
|
||||
padding: 10px 0;
|
||||
border-bottom: 1px solid #eee;
|
||||
border-top: 1px solid #eee;
|
||||
}
|
||||
|
||||
.hover-name {
|
||||
@ -196,11 +240,11 @@ body {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
font-size: 16px;
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
.hover-amount {
|
||||
font-size: 18px;
|
||||
font-size: 20px;
|
||||
color: #0066cc;
|
||||
font-weight: bold;
|
||||
margin-left: 10px;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user