Fix timeline reset label alignment and hover state
This commit is contained in:
parent
06fb6bf768
commit
400c0ac765
142
app.js
142
app.js
@ -683,22 +683,30 @@ function buildTimelineOption(drillPath) {
|
||||
triggerEvent: true
|
||||
} : { show: false };
|
||||
|
||||
const legendTop = isDrilled ? 42 : 10;
|
||||
const legendRight = 10;
|
||||
const legendItemWidth = 12;
|
||||
const legendItemHeight = 12;
|
||||
const legendItemGap = 8;
|
||||
const legendPadding = [8, 12];
|
||||
const legendFontSize = 13;
|
||||
|
||||
return {
|
||||
backgroundColor: '#fff',
|
||||
title: chartTitle,
|
||||
tooltip: { show: false },
|
||||
legend: {
|
||||
data: legendData,
|
||||
top: isDrilled ? 42 : 10,
|
||||
right: 10,
|
||||
top: legendTop,
|
||||
right: legendRight,
|
||||
orient: 'vertical',
|
||||
itemWidth: 12,
|
||||
itemHeight: 12,
|
||||
textStyle: { fontSize: 13 },
|
||||
itemGap: 8,
|
||||
itemWidth: legendItemWidth,
|
||||
itemHeight: legendItemHeight,
|
||||
textStyle: { fontSize: legendFontSize },
|
||||
itemGap: legendItemGap,
|
||||
backgroundColor: 'rgba(255,255,255,0.85)',
|
||||
borderRadius: 6,
|
||||
padding: [8, 12],
|
||||
padding: legendPadding,
|
||||
selector: false
|
||||
},
|
||||
grid: {
|
||||
@ -725,7 +733,16 @@ function buildTimelineOption(drillPath) {
|
||||
},
|
||||
series: seriesList,
|
||||
_seriesDataMap: seriesDataMap,
|
||||
_monthCount: months.length
|
||||
_monthCount: months.length,
|
||||
_legendLayout: {
|
||||
top: legendTop,
|
||||
right: legendRight,
|
||||
itemWidth: legendItemWidth,
|
||||
itemHeight: legendItemHeight,
|
||||
itemGap: legendItemGap,
|
||||
padding: legendPadding,
|
||||
fontSize: legendFontSize
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@ -824,6 +841,7 @@ function renderTimelineChart(drillPath, historyAction, legendSelected) {
|
||||
const n = tlOption._monthCount;
|
||||
const visibleTotals = new Array(n).fill(0);
|
||||
const allNames = tlOption.legend.data;
|
||||
const legendLayout = tlOption._legendLayout;
|
||||
let allSelected = true;
|
||||
Object.keys(dataMap).forEach(name => {
|
||||
if (selected[name] !== false) {
|
||||
@ -832,34 +850,94 @@ function renderTimelineChart(drillPath, historyAction, legendSelected) {
|
||||
allSelected = false;
|
||||
}
|
||||
});
|
||||
const legendFont = `${legendLayout.fontSize}px sans-serif`;
|
||||
const resetFontSize = Math.max(11, legendLayout.fontSize - 1);
|
||||
const resetFont = `${resetFontSize}px sans-serif`;
|
||||
const resetXOffset = 3;
|
||||
const maxLegendTextWidth = allNames.reduce((maxWidth, name) => {
|
||||
return Math.max(maxWidth, echarts.format.getTextRect(name, legendFont).width);
|
||||
}, 0);
|
||||
const iconTextGap = 5; // ECharts default icon/text gap for legend items
|
||||
const legendBoxWidth =
|
||||
legendLayout.padding[1] * 2 +
|
||||
legendLayout.itemWidth +
|
||||
iconTextGap +
|
||||
maxLegendTextWidth;
|
||||
const resetTextWidth = echarts.format.getTextRect('× сбросить', resetFont).width;
|
||||
const resetRight =
|
||||
legendLayout.right +
|
||||
legendBoxWidth -
|
||||
legendLayout.padding[1] -
|
||||
resetTextWidth -
|
||||
resetXOffset;
|
||||
const legendView = (myChart._componentsViews || []).find(v => v && v.__model && v.__model.mainType === 'legend');
|
||||
const resetLeft = legendView && legendView.group ? legendView.group.x : null;
|
||||
let resetTop;
|
||||
if (legendView && legendView.group && legendView._contentGroup) {
|
||||
const legendItems = legendView._contentGroup.children();
|
||||
if (legendItems.length > 0) {
|
||||
const lastItem = legendItems[legendItems.length - 1];
|
||||
const prevItem = legendItems.length > 1 ? legendItems[legendItems.length - 2] : null;
|
||||
const rowStep = prevItem ? (lastItem.y - prevItem.y) : (legendLayout.itemHeight + legendLayout.itemGap);
|
||||
const lastRect = lastItem.getBoundingRect();
|
||||
resetTop =
|
||||
legendView.group.y +
|
||||
(legendView._contentGroup.y || 0) +
|
||||
lastItem.y +
|
||||
lastRect.y +
|
||||
rowStep;
|
||||
}
|
||||
}
|
||||
if (resetTop === undefined) {
|
||||
const nextRowTop =
|
||||
legendLayout.top +
|
||||
legendLayout.padding[0] +
|
||||
allNames.length * (legendLayout.itemHeight + legendLayout.itemGap);
|
||||
resetTop = nextRowTop + 11;
|
||||
}
|
||||
|
||||
const resetGraphic = {
|
||||
type: 'text',
|
||||
id: 'resetBtn',
|
||||
top: resetTop,
|
||||
z: 100,
|
||||
zlevel: 1,
|
||||
style: {
|
||||
text: allSelected ? '' : '× сбросить',
|
||||
fontSize: resetFontSize,
|
||||
fill: '#999',
|
||||
fontFamily: '-apple-system, BlinkMacSystemFont, "SF Pro", "Segoe UI", system-ui, sans-serif'
|
||||
},
|
||||
cursor: 'pointer',
|
||||
onmouseover: function() {
|
||||
if (this && this.setStyle) this.setStyle({ fill: '#000' });
|
||||
},
|
||||
onmouseout: function() {
|
||||
if (this && this.setStyle) this.setStyle({ fill: '#999' });
|
||||
},
|
||||
onclick: function() {
|
||||
window._suppressLegendHistory = true;
|
||||
allNames.forEach(name => {
|
||||
myChart.dispatchAction({ type: 'legendSelect', name: name });
|
||||
});
|
||||
window._suppressLegendHistory = false;
|
||||
const resetSelected = {};
|
||||
allNames.forEach(name => { resetSelected[name] = true; });
|
||||
updateTotalsAndResetBtn(resetSelected);
|
||||
history.pushState({ timelineDrill: drillPath }, '');
|
||||
}
|
||||
};
|
||||
if (resetLeft !== null) {
|
||||
resetGraphic.left = resetLeft + resetXOffset;
|
||||
} else {
|
||||
resetGraphic.right = resetRight;
|
||||
}
|
||||
|
||||
myChart.setOption({
|
||||
series: [{ name: '__total__', label: {
|
||||
formatter: (p) => Math.round(visibleTotals[p.dataIndex] / 1000) + 'к'
|
||||
}}],
|
||||
graphic: [{
|
||||
type: 'text',
|
||||
id: 'resetBtn',
|
||||
right: 22,
|
||||
top: (drillPath.length > 0 ? 42 : 10) + allNames.length * 20 + 16,
|
||||
style: {
|
||||
text: allSelected ? '' : 'Очистить',
|
||||
fontSize: 13,
|
||||
fill: '#999',
|
||||
fontFamily: '-apple-system, BlinkMacSystemFont, "SF Pro", "Segoe UI", system-ui, sans-serif'
|
||||
},
|
||||
cursor: 'pointer',
|
||||
onclick: function() {
|
||||
window._suppressLegendHistory = true;
|
||||
allNames.forEach(name => {
|
||||
myChart.dispatchAction({ type: 'legendSelect', name: name });
|
||||
});
|
||||
window._suppressLegendHistory = false;
|
||||
const resetSelected = {};
|
||||
allNames.forEach(name => { resetSelected[name] = true; });
|
||||
updateTotalsAndResetBtn(resetSelected);
|
||||
history.pushState({ timelineDrill: drillPath }, '');
|
||||
}
|
||||
}]
|
||||
graphic: [resetGraphic]
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user