弹出层配置
示例,双y轴刻度,防止线重叠
测试数据
chartData: [
{
name: "W29",
visit: 143,
sale: 8,
price: 65642,
},
{
name: "W30",
visit: 138,
sale: 4,
price: 61147,
},
{
name: "W31",
visit: 148,
sale: 5,
price: 60506,
},
{
name: "W32",
visit: 143,
sale: 6,
price: 64730,
},
{
name: "W33",
visit: 192,
sale: 4,
price: 66901,
},
{
name: "W34",
visit: 234,
sale: 7,
price: 57480,
},
{
name: "W35",
visit: 185,
sale: 4,
price: 62975,
},
{
name: "W36",
visit: 161,
sale: 7,
price: 57905,
},
],
let optionData = {
series:[],
...
}
const splitNumber = 4;
//计算双轴刻度最大值,防止线重叠
//数据中的最大值seriesDataLMax1 ,interval1 分割刻度间隔数 ,splitNumber 分割几条线
//计算左右轴刻度最大值方法1:
let seriesDataLMax1 = Math.max(...optionData.series[0].data)
let interval1 = seriesDataLMax1 % splitNumber != 0 ? Math.trunc(seriesDataLMax1 / splitNumber) + 1 : seriesDataLMax1 / splitNumber;
seriesDataLMax1 = interval1 * splitNumber;
let seriesDataLMax2 = Math.max(...optionData.series[optionData.series.length - 1].data)
let interval2 = seriesDataLMax2 % splitNumber != 0 ? Math.trunc(seriesDataLMax2 / splitNumber) + 1 : seriesDataLMax2 / splitNumber;
seriesDataLMax2 = interval2 * splitNumber;
//计算左右轴刻度最大值方法2:
//左轴最大值
const seriesDataLMax = this.$global.numberFormat(
Math.max(
...this.chartData.map((item) => item.visit),
...this.chartData.map((item) => item.sale)
)
);
//右轴最大值
const seriesDataRMax = this.$global.numberFormat(
Math.max(...this.chartData.map((item) => item.price))
);
//charts中yAxis配置
interval: parseFloat((seriesDataLMax / splitNumber).toFixed(2)), //左
interval: parseFloat((seriesDataRMax / splitNumber).toFixed(2)), //右
let legendData = optionData?.series?.map(i => {
return i.name
})
option = {
grid: {
top: optionData.series.length == 4 ? '24%' : '20%', //动态顶部距离
bottom: '8%',
right: '5%',
left: '3%',
containLabel: true
// containLabel: true,
},
//滑动
dataZoom: [{
type: 'slider',
startValue: optionData.xAxis.length - 5,//配置起始位置,默认显示最后
endValue: optionData.xAxis.length,//配置起始位置,默认显示最后
// end: 150,
height: 0, // 设置滑动条的高度
bottom: 20,
moveHandleSize: 6, //默认显示个数
borderColor: '#051d49',
moveHandleStyle: {
color: '#123D7F',
},
}],
tooltip: {
trigger: 'axis',
extraCssText: 'z-index:10', // 修改层级
axisPointer: {
type: "none", //隐藏中心线
},
confine: true, //适配,在移动端展示展示,防止溢出
//调用封装
...this.tooltipFormat('unit'),
//直接使用
valueFormatter: function (value) { //添加单位
return value ? value + ' ' + unit : '-';
}
},
legend: {
data: legendData,
top: '10px',
icon: '',
// type: 'scroll',
// icon: 'rect',
pageIconColor: '#fff', //翻页器颜色
pageIconInactiveColor: '#333',//翻页器颜色
pageTextStyle: {
color: '#C2C3C4',//翻页器颜色
},
itemStyle: {
borderRadius: 0,
},
textStyle: {
color: "#C2C3C4",
fontSize: this.$global.vw(12),
padding: [0, 0, 0, this.$global.vw(5)],
},
itemWidth: 10,
itemHeight: 10,
},
xAxis: [{
type: 'category',
data: optionData.xAxis,
axisPointer: {
// type: 'shadow',
color: '#BDC3C9',
fontSize: 12,
fontWeight: 400
},
axisTick: {
show: false, //隐藏刻度小线
},
axisLabel: {
margin: this.$global.vw(4),
formatter: function (value) {
//x轴文案显示格式化,如果有-,换行显示文本
return optionData.xAxis.length > 4 ? value.split('-').join('-\n') : value;
},
textStyle: {
color: "#BDC3C9",
fontSize: this.$global.vw(12),
},
},
splitLine: {
lineStyle: {
color: "#38487A",
},
},
}],
yAxis: [{
type: 'value',
name: optionData.unit1,
nameTextStyle: {
color: '#BDC3C9',
fontSize: 12,
padding: [0, 0, 5, seriesDataLMax1 ? '' : 20]
},
splitNumber: splitNumber,
interval: interval1,
max: seriesDataLMax1,//dataZoom显示刻度必须设置
min: 0,//dataZoom显示刻度必须设置
axisLabel: {
textStyle: {
color: '#BDC3C9',
fontSize: 12,
fontWeight: 400
}
},
splitLine: {
lineStyle: {
color: ['#505F8A']
}
}
},
{
type: 'value',
name: optionData.unit2,
nameTextStyle: {
color: '#BDC3C9',
fontSize: 12,
padding: [0, 5, 5, 0]
},
max: seriesDataLMax2,
splitNumber: splitNumber,
interval: interval2,
min: 0,
axisLabel: {
textStyle: {
color: '#BDC3C9', //刻度文字颜色
fontSize: 12,
fontWeight: 400
}
},
splitLine: {
lineStyle: {
color: ['#505F8A']
}
}
}
],
series: [
{
name: "来访(组)",
type: "bar",
yAxisIndex: 0,
itemStyle: {
color: new this.$echarts.graphic.LinearGradient(0.5, 1, 0.5, 0, [ //渐变色
{
offset: 0,
color: "#205CAB",
},
{
offset: 1,
color: "#4F95E5",
},
]),
},
barGap: 0,
barWidth: this.$global.vw(10),
data: this.chartData.map((item) => item.visit),
},
{
name: "价格(元/㎡)",
type: "line",
yAxisIndex: 1,
symbol: "circle",
symbolSize: this.$global.vw(8),
smooth: true,
lineStyle: {
color: "#E48E31",
width: this.$global.vw(2),
},
itemStyle: {
color: "#E48E31",
},
emphasis: {
scale: false,
},
data: this.chartData.map((item) => item.price),
},
]
}
methods: {
//封装tooltip,数据格式化
tooltipFormat(unit) {
return {
valueFormatter: function (value) {
return value ? value + ' ' + unit : '-';
}
}
},
}
封住一些常用js方法
创建目录utils/global.js文件,
再main.js引入 import global from '@/utils/global.js'
Vue.prototype.$global = global;
export default {
setCookie: function (cname, cvalue, exdays) {
var d = new Date();
d.setTime(d.getTime() + (exdays * 24 * 60 * 60 * 1000));
var expires = "expires=" + d.toUTCString();
document.cookie = cname + "=" + cvalue + "; " + expires;
},
deepClone(obj, map = new WeakMap()) {
if (obj === null || typeof obj !== 'object') return obj;
if (obj instanceof Date) return new Date(obj);
if (obj instanceof RegExp) return new RegExp(obj);
if (map.has(obj)) return map.get(obj);
const clone = Array.isArray(obj) ? [] : {};
map.set(obj, clone);
for (const key in obj) {
if (obj.hasOwnProperty(key)) {
clone[key] = this.deepClone(obj[key], map);
}
}
return clone;
},
uuid() {
var s = [];
var hexDigits = "0123456789abcdef";
for (var i = 0; i < 36; i++) {
s[i] = hexDigits.substr(Math.floor(Math.random() * 0x10), 1);
}
s[14] = "4"; // bits 12-15 of the time_hi_and_version field to 0010
s[19] = hexDigits.substr((s[19] & 0x3) | 0x8, 1); // bits 6-7 of the clock_seq_hi_and_reserved to 01
s[8] = s[13] = s[18] = s[23] = "-";
var uuid = s.join("");
return uuid;
},
groupedByCategory(list, category) {
const object = list.reduce((acc, item) => {
const _category = item[category];
// 如果分类不存在于结果对象中,创建一个新的数组
if (!acc[_category]) {
acc[_category] = [];
}
// 将当前项添加到对应的分类数组中
acc[_category].push(item);
return acc;
}, {});
return object
},
vw: (val) => {
return val / 375 * document.body.clientWidth;
},
numberFormat: (num, isMax = true) => {
let arr = num.toString().split('')
if (isMax) {
if (arr.length > 2) {
let list = []
arr.forEach((item, index) => {
if (index === 0) {
list.push(parseInt(item) + 1)
} else {
list.push(0)
}
});
return parseInt(list.join(''))
} else if (arr.length > 1) {
return 100;
} else {
return 10
}
} else {
if (arr.length > 1) {
let list = []
arr.forEach((item, index) => {
if (index === 0) {
list.push(parseInt(item) + 1)
} else {
list.push(0)
}
});
return parseInt(list.join(''))
} else {
return 10
}
}
},
getWeekData(year) {
let list = [];
if (year) {
let beginDate = year + "-01-01";
let week = dayjs(beginDate).day();
week = week ? week : 7;
if (week !== 1) {
beginDate = dayjs(beginDate)
.subtract(week - 1, "day")
.add(7, "day")
.format("YYYY-MM-DD");
}
let i = 0;
do {
let endDate = dayjs(beginDate)
.add(6, "day")
.format("YYYY-MM-DD");
list.push({
year: year,
week: ++i,
beginDate: dayjs(beginDate).format("MM/DD"),
endDate: dayjs(endDate).format("MM/DD"),
beginAllDate: beginDate,
endAllDate: endDate,
});
beginDate = dayjs(beginDate).add(7, "day").format("YYYY-MM-DD");
} while (Number(beginDate.substring(0, 4)) === year);
}
return list;
},
getRouterParams() {
const temp1 = window.location.href.split('?');
const pram = temp1[1];
if (!pram) return;
const keyValue = pram.split('&');
let obj = {};
for (let i = 0; i < keyValue.length; i++) {
const item = keyValue[i].split('=');
const key = item[0];
const value = item[1];
if (key === 'name' || key === 'vue') {
obj[key] = decodeURI(value)
} else {
obj[key] = decodeURI(value)
}
}
return obj
},
objectToQuery(obj) {
return Object.keys(obj)
.map(key => encodeURIComponent(key) + '=' + encodeURIComponent(obj[key]))
.join('&');
},
waltzMobile() {
if (/Mobi|Android|iPhone/i.test(navigator.userAgent)) {
waltz.call({
module: 'WZApi',
handlerName: 'setResultData',
data: {
appId: 'f71eaf99d2c78d358254cf070a1aa446',
taskComplete: true
}
}).then(() => {
// 调用华尔兹返回函数,返回上一级页面
this.waltz.window.close()
}).catch(err => {
/*handle error here */
});
} else {
waltz.call({
module: 'WZApi',
appId: 'f71eaf99d2c78d358254cf070a1aa446',
handlerName: 'sendMessage',
data: {
type: 'task_center',
focus: true,
data: {
taskComplete: true
}
}
}).then(() => {
// 调用华尔兹返回函数,返回上一级页面
this.waltz.window.close()
}).catch(err => {
/*handle error here */
});
}
},
px2rem(px) {
if (/%/ig.test(px)) { // 有百分号%,特殊处理,表述pc是一个有百分号的数,比如:90%
return px
} else {
return (parseFloat(px) / 37.5) + 'rem'
}
},
pxFitScreen(px) {
if (window.innerWidth < 450) {
return px
}
if (/%/ig.test(px)) { // 有百分号%,特殊处理,表述pc是一个有百分号的数,比如:90%
return px
} else {
return (parseFloat(px) / 37.5) * px
}
}
}