Fix timeline reset label alignment and hover state
This commit is contained in:
parent
06fb6bf768
commit
400c0ac765
114
app.js
114
app.js
@ -683,22 +683,30 @@ function buildTimelineOption(drillPath) {
|
|||||||
triggerEvent: true
|
triggerEvent: true
|
||||||
} : { show: false };
|
} : { 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 {
|
return {
|
||||||
backgroundColor: '#fff',
|
backgroundColor: '#fff',
|
||||||
title: chartTitle,
|
title: chartTitle,
|
||||||
tooltip: { show: false },
|
tooltip: { show: false },
|
||||||
legend: {
|
legend: {
|
||||||
data: legendData,
|
data: legendData,
|
||||||
top: isDrilled ? 42 : 10,
|
top: legendTop,
|
||||||
right: 10,
|
right: legendRight,
|
||||||
orient: 'vertical',
|
orient: 'vertical',
|
||||||
itemWidth: 12,
|
itemWidth: legendItemWidth,
|
||||||
itemHeight: 12,
|
itemHeight: legendItemHeight,
|
||||||
textStyle: { fontSize: 13 },
|
textStyle: { fontSize: legendFontSize },
|
||||||
itemGap: 8,
|
itemGap: legendItemGap,
|
||||||
backgroundColor: 'rgba(255,255,255,0.85)',
|
backgroundColor: 'rgba(255,255,255,0.85)',
|
||||||
borderRadius: 6,
|
borderRadius: 6,
|
||||||
padding: [8, 12],
|
padding: legendPadding,
|
||||||
selector: false
|
selector: false
|
||||||
},
|
},
|
||||||
grid: {
|
grid: {
|
||||||
@ -725,7 +733,16 @@ function buildTimelineOption(drillPath) {
|
|||||||
},
|
},
|
||||||
series: seriesList,
|
series: seriesList,
|
||||||
_seriesDataMap: seriesDataMap,
|
_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 n = tlOption._monthCount;
|
||||||
const visibleTotals = new Array(n).fill(0);
|
const visibleTotals = new Array(n).fill(0);
|
||||||
const allNames = tlOption.legend.data;
|
const allNames = tlOption.legend.data;
|
||||||
|
const legendLayout = tlOption._legendLayout;
|
||||||
let allSelected = true;
|
let allSelected = true;
|
||||||
Object.keys(dataMap).forEach(name => {
|
Object.keys(dataMap).forEach(name => {
|
||||||
if (selected[name] !== false) {
|
if (selected[name] !== false) {
|
||||||
@ -832,22 +850,71 @@ function renderTimelineChart(drillPath, historyAction, legendSelected) {
|
|||||||
allSelected = false;
|
allSelected = false;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
myChart.setOption({
|
const legendFont = `${legendLayout.fontSize}px sans-serif`;
|
||||||
series: [{ name: '__total__', label: {
|
const resetFontSize = Math.max(11, legendLayout.fontSize - 1);
|
||||||
formatter: (p) => Math.round(visibleTotals[p.dataIndex] / 1000) + 'к'
|
const resetFont = `${resetFontSize}px sans-serif`;
|
||||||
}}],
|
const resetXOffset = 3;
|
||||||
graphic: [{
|
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',
|
type: 'text',
|
||||||
id: 'resetBtn',
|
id: 'resetBtn',
|
||||||
right: 22,
|
top: resetTop,
|
||||||
top: (drillPath.length > 0 ? 42 : 10) + allNames.length * 20 + 16,
|
z: 100,
|
||||||
|
zlevel: 1,
|
||||||
style: {
|
style: {
|
||||||
text: allSelected ? '' : 'Очистить',
|
text: allSelected ? '' : '× сбросить',
|
||||||
fontSize: 13,
|
fontSize: resetFontSize,
|
||||||
fill: '#999',
|
fill: '#999',
|
||||||
fontFamily: '-apple-system, BlinkMacSystemFont, "SF Pro", "Segoe UI", system-ui, sans-serif'
|
fontFamily: '-apple-system, BlinkMacSystemFont, "SF Pro", "Segoe UI", system-ui, sans-serif'
|
||||||
},
|
},
|
||||||
cursor: 'pointer',
|
cursor: 'pointer',
|
||||||
|
onmouseover: function() {
|
||||||
|
if (this && this.setStyle) this.setStyle({ fill: '#000' });
|
||||||
|
},
|
||||||
|
onmouseout: function() {
|
||||||
|
if (this && this.setStyle) this.setStyle({ fill: '#999' });
|
||||||
|
},
|
||||||
onclick: function() {
|
onclick: function() {
|
||||||
window._suppressLegendHistory = true;
|
window._suppressLegendHistory = true;
|
||||||
allNames.forEach(name => {
|
allNames.forEach(name => {
|
||||||
@ -859,7 +926,18 @@ function renderTimelineChart(drillPath, historyAction, legendSelected) {
|
|||||||
updateTotalsAndResetBtn(resetSelected);
|
updateTotalsAndResetBtn(resetSelected);
|
||||||
history.pushState({ timelineDrill: drillPath }, '');
|
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: [resetGraphic]
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user