|
|
@@ -151,6 +151,11 @@ import * as echarts from 'echarts';
|
|
|
wrapXLabel:{
|
|
|
type:Boolean,
|
|
|
default:false
|
|
|
+ },
|
|
|
+ // 作业分析图:空间够则横排完整显示;不够则倾斜并最多 6 字;仍不够再出横向滚动条
|
|
|
+ adaptiveXLabel:{
|
|
|
+ type:Boolean,
|
|
|
+ default:false
|
|
|
}
|
|
|
},
|
|
|
watch:{
|
|
|
@@ -269,13 +274,28 @@ import * as echarts from 'echarts';
|
|
|
// console.log("打印满分",fullMark);
|
|
|
|
|
|
// 换行时加大类目宽度,避免名称挤成很多行
|
|
|
- const barMinWidth = this.scrollable ? (this.wrapXLabel ? 140 : 72) : 30;
|
|
|
- const dataZoomNum = Math.max(1, Math.floor((totalWidth - 140) / barMinWidth));// 当前区域内可显示的柱子的数量
|
|
|
+ const axisFontSize = Number(this.fontSize) || 14;
|
|
|
+ let useRotate = false;
|
|
|
+ let barMinWidth = this.scrollable ? (this.wrapXLabel ? 140 : 72) : 30;
|
|
|
+ if (this.adaptiveXLabel && this.datax.length) {
|
|
|
+ const plotWidth = Math.max(totalWidth - 72, 40);
|
|
|
+ const slotWidth = plotWidth / this.datax.length;
|
|
|
+ const maxChars = this.datax.reduce((max, name) => Math.max(max, String(name == null ? '' : name).length), 0);
|
|
|
+ const horizontalNeed = maxChars * axisFontSize + 8;
|
|
|
+ if (horizontalNeed <= slotWidth) {
|
|
|
+ barMinWidth = 0;
|
|
|
+ } else {
|
|
|
+ useRotate = true;
|
|
|
+ const shownChars = Math.min(maxChars, 6);
|
|
|
+ barMinWidth = Math.ceil(shownChars * axisFontSize * Math.cos(Math.PI / 4) + axisFontSize + 10);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ const dataZoomNum = Math.max(1, Math.floor((totalWidth - 140) / Math.max(barMinWidth, 1)));// 当前区域内可显示的柱子的数量
|
|
|
const dataZoomEnd = Math.min(100, Math.floor((100 / this.datax.length) * dataZoomNum)); // 当前区域内可显示柱子的占比
|
|
|
- const needZoom = this.showDataZoom && this.datax.length > 0 && singleSeriesWidth < barMinWidth;
|
|
|
+ const needZoom = this.showDataZoom && this.datax.length > 0 && barMinWidth > 0 && singleSeriesWidth < barMinWidth;
|
|
|
+ const showScrollBar = this.scrollable || (this.adaptiveXLabel && needZoom);
|
|
|
const visibleCount = needZoom ? Math.min(this.datax.length, dataZoomNum) : Math.max(this.datax.length, 1);
|
|
|
const labelWidth = Math.max(56, Math.floor(Math.max(totalWidth - 48, 40) / visibleCount) - 12);
|
|
|
- const axisFontSize = Number(this.fontSize) || 14;
|
|
|
const charsPerLine = Math.max(4, Math.floor(labelWidth / axisFontSize));
|
|
|
let dataZoom = {
|
|
|
start: 0, //默认为0
|
|
|
@@ -289,22 +309,22 @@ import * as echarts from 'echarts';
|
|
|
height: 8, //组件高度
|
|
|
left: 20, //左边的距离
|
|
|
right: 20, //右边的距离
|
|
|
- bottom: this.scrollable ? 4 : 0, //右边的距离
|
|
|
- fillerColor: this.scrollable ? 'rgba(46,100,250,0.35)' : 'transparent',// 滑动条选中区域颜色
|
|
|
+ bottom: showScrollBar ? 4 : 0, //右边的距离
|
|
|
+ fillerColor: showScrollBar ? 'rgba(46,100,250,0.35)' : 'transparent',// 滑动条选中区域颜色
|
|
|
zoomLock: true,//是否锁定选择区域(或叫做数据窗口)的大小。
|
|
|
handleSize: '0',
|
|
|
handleStyle: {
|
|
|
color: '#b8b8b8',// 滑动条手柄颜色
|
|
|
borderWidth: 2
|
|
|
},
|
|
|
- backgroundColor: this.scrollable ? '#F2F3F5' : 'transparent', //两边未选中的滑动条区域的颜色
|
|
|
+ backgroundColor: showScrollBar ? '#F2F3F5' : 'transparent', //两边未选中的滑动条区域的颜色
|
|
|
showDataShadow: false, //是否显示数据阴影 默认auto
|
|
|
showDetail: false, //即拖拽时候是否显示详细数值信息 默认true
|
|
|
filterMode: 'filter'
|
|
|
|
|
|
};//设置滚动条的样式
|
|
|
const dataZoomOption = needZoom
|
|
|
- ? (this.scrollable
|
|
|
+ ? (showScrollBar
|
|
|
? [dataZoom, { type: 'inside', xAxisIndex: 0, start: 0, end: dataZoomEnd, zoomLock: true }]
|
|
|
: dataZoom)
|
|
|
: null;
|
|
|
@@ -366,7 +386,7 @@ import * as echarts from 'echarts';
|
|
|
left: this.gridLeft,
|
|
|
right: this.gridRight,
|
|
|
top: this.gridTop,
|
|
|
- bottom: needZoom && this.scrollable ? 24 : 0,
|
|
|
+ bottom: needZoom && showScrollBar ? 24 : 0,
|
|
|
containLabel: true, //用于控制网格区域是否包含坐标轴的标签 true 可以确保所有标签都能完整显示,不会被裁剪。
|
|
|
},
|
|
|
dataZoom: dataZoomOption,
|
|
|
@@ -378,7 +398,19 @@ import * as echarts from 'echarts';
|
|
|
axisPointer: {
|
|
|
type: 'shadow'
|
|
|
},
|
|
|
- axisLabel: this.wrapXLabel ? {
|
|
|
+ axisLabel: this.adaptiveXLabel ? {
|
|
|
+ interval: 0,
|
|
|
+ hideOverlap: false,
|
|
|
+ fontWeight: 400,
|
|
|
+ rotate: useRotate ? 45 : 0,
|
|
|
+ color: this.fontColor || '#666666',
|
|
|
+ fontSize: axisFontSize,
|
|
|
+ formatter: function (value) {
|
|
|
+ const text = value == null ? '' : String(value);
|
|
|
+ if (!useRotate || text.length <= 6) return text;
|
|
|
+ return text.slice(0, 6);
|
|
|
+ },
|
|
|
+ } : this.wrapXLabel ? {
|
|
|
interval: 0,
|
|
|
hideOverlap: false,
|
|
|
fontWeight: 400,
|