feat: move legend to top-right box with hover highlighting
- Move legend from bottom to vertical top-right box with background - Highlight hovered category in legend (bold text, others dimmed) - Dim legend color swatches to 0.15 opacity for non-hovered items - Make drill-down title larger (22px bold centered) - Reserve right margin (180px) for legend, free up bottom space Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
b91aa65f61
commit
9b848610ae
50
app.js
50
app.js
@ -614,9 +614,14 @@ function buildTimelineOption(drillCategory) {
|
||||
|
||||
const chartTitle = drillCategory ? {
|
||||
text: '← ' + drillCategory,
|
||||
left: 20,
|
||||
top: 10,
|
||||
textStyle: { fontSize: 16, fontWeight: 500, color: '#555' },
|
||||
left: 'center',
|
||||
top: 6,
|
||||
textStyle: {
|
||||
fontSize: 22,
|
||||
fontWeight: 'bold',
|
||||
fontFamily: '-apple-system, BlinkMacSystemFont, "SF Pro", "Segoe UI", system-ui, sans-serif',
|
||||
color: '#333'
|
||||
},
|
||||
triggerEvent: true
|
||||
} : { show: false };
|
||||
|
||||
@ -626,18 +631,23 @@ function buildTimelineOption(drillCategory) {
|
||||
tooltip: { show: false },
|
||||
legend: {
|
||||
data: legendData,
|
||||
bottom: 0,
|
||||
left: 'center',
|
||||
itemWidth: 14,
|
||||
itemHeight: 14,
|
||||
top: drillCategory ? 42 : 10,
|
||||
right: 10,
|
||||
orient: 'vertical',
|
||||
itemWidth: 12,
|
||||
itemHeight: 12,
|
||||
textStyle: { fontSize: 13 },
|
||||
itemGap: 16
|
||||
itemGap: 8,
|
||||
backgroundColor: 'rgba(255,255,255,0.85)',
|
||||
borderRadius: 6,
|
||||
padding: [8, 12],
|
||||
selector: false
|
||||
},
|
||||
grid: {
|
||||
left: 30,
|
||||
right: 30,
|
||||
top: drillCategory ? 50 : 40,
|
||||
bottom: 50,
|
||||
right: 180,
|
||||
top: drillCategory ? 55 : 40,
|
||||
bottom: 30,
|
||||
containLabel: true
|
||||
},
|
||||
xAxis: {
|
||||
@ -675,23 +685,41 @@ function renderTimelineChart(drillCategory) {
|
||||
myChart.setOption(tlOption, true);
|
||||
|
||||
// Highlight entire series on hover so all bars show emphasis.label
|
||||
// Also highlight the corresponding legend item
|
||||
const legendNames = tlOption.legend.data;
|
||||
let hlSeries = null;
|
||||
|
||||
function updateLegend(activeName) {
|
||||
myChart.setOption({
|
||||
legend: {
|
||||
data: legendNames.map(name => {
|
||||
if (!activeName) return { name, textStyle: { fontWeight: 'normal', color: '#333' }, itemStyle: { opacity: 1 } };
|
||||
if (name === activeName) return { name, textStyle: { fontWeight: 'bold', color: '#333' }, itemStyle: { opacity: 1 } };
|
||||
return { name, textStyle: { fontWeight: 'normal', color: '#ccc' }, itemStyle: { opacity: 0.15 } };
|
||||
})
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
myChart.on('mouseover', function(params) {
|
||||
if (params.componentType !== 'series' || params.seriesName === '__total__') return;
|
||||
if (hlSeries === params.seriesName) return;
|
||||
if (hlSeries) myChart.dispatchAction({ type: 'downplay', seriesName: hlSeries });
|
||||
hlSeries = params.seriesName;
|
||||
myChart.dispatchAction({ type: 'highlight', seriesName: params.seriesName });
|
||||
updateLegend(params.seriesName);
|
||||
});
|
||||
myChart.on('mouseout', function(params) {
|
||||
if (params.componentType !== 'series' || !hlSeries) return;
|
||||
myChart.dispatchAction({ type: 'downplay', seriesName: hlSeries });
|
||||
hlSeries = null;
|
||||
updateLegend(null);
|
||||
});
|
||||
myChart.on('globalout', function() {
|
||||
if (hlSeries) {
|
||||
myChart.dispatchAction({ type: 'downplay', seriesName: hlSeries });
|
||||
hlSeries = null;
|
||||
updateLegend(null);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user