[问题解决]Echarts:There is a chart instance already initialized on the dom
产生原因
使用Echarts的时候,多次加载会出现There is a chart instance already initialized on the dom.的警告,表示DOM上已经初始化了一个图表实例
js
<template>
<div class="echarts-style">
<div ref="chart" class="bar-chart"></div>
</div>
</template>
<script>
import * as echarts from "echarts"
export default {
data() {
return {
chartPie: null,
}
},
mounted() {
this.drawChart()
},
props: {
queryParm: Object,
},
watch: {
queryParm: {
handler() {
this.drawChart()
},
deep: true,
},
},
methods: {
drawChart() {
// 如果不存在,就进行初始化
const already = echarts.getInstanceByDom(this.$refs.chart)
if (!already) {
this.chartPie = echarts.init(this.$refs.chart)
}
this.chartPie.setOption({
...
})
if (!already) {
window.addEventListener("resize", () => {
this.chartPie.resize()
})
}
},
},
}
</script>
<style lang="scss" scoped>
.echarts-style {
width: 100%;
height: 300px;
.bar-chart {
width: 100%;
height: 100%;
}
}
</style>
<template>
<div class="echarts-style">
<div ref="chart" class="bar-chart"></div>
</div>
</template>
<script>
import * as echarts from "echarts"
export default {
data() {
return {
chartPie: null,
}
},
mounted() {
this.drawChart()
},
props: {
queryParm: Object,
},
watch: {
queryParm: {
handler() {
this.drawChart()
},
deep: true,
},
},
methods: {
drawChart() {
// 如果不存在,就进行初始化
const already = echarts.getInstanceByDom(this.$refs.chart)
if (!already) {
this.chartPie = echarts.init(this.$refs.chart)
}
this.chartPie.setOption({
...
})
if (!already) {
window.addEventListener("resize", () => {
this.chartPie.resize()
})
}
},
},
}
</script>
<style lang="scss" scoped>
.echarts-style {
width: 100%;
height: 300px;
.bar-chart {
width: 100%;
height: 100%;
}
}
</style>
设置x轴间隔
js
xAxis: {
type: "category",
data: [],
boundaryGap: false, // 留白
splitLine: {
show: true
},
axisLabel: {
showMaxLabel: true, // 显示最大的文本
interval: 59 // 间隔多少显示x轴文本
}
},
xAxis: {
type: "category",
data: [],
boundaryGap: false, // 留白
splitLine: {
show: true
},
axisLabel: {
showMaxLabel: true, // 显示最大的文本
interval: 59 // 间隔多少显示x轴文本
}
},
或者设置成函数的形式
js
axisLabel: {
interval: (index, value) => {
return index % 60 === 0 || value === "23:59";
},
rotate: 20
}
axisLabel: {
interval: (index, value) => {
return index % 60 === 0 || value === "23:59";
},
rotate: 20
}
设置x轴文字倾斜
js
axisLabel: {
rotate: 8,
},
axisLabel: {
rotate: 8,
},
主动置灰单个折线
js
this.chartLine.on("legendselectchanged", () => {
this.options.legend.selected[""] = false
this.chartLine.setOption(this.options)
})
this.chartLine.on("legendselectchanged", () => {
this.options.legend.selected[""] = false
this.chartLine.setOption(this.options)
})
去除x轴坐标线
json
option = {
xAxis: {
type: 'value',
axisTick: {
show: false
},
data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
},
yAxis: {
type: 'value'
},
series: [
{
data: [150, 230, 224, 218, 135, 147, 260],
type: 'line'
}
]
}
option = {
xAxis: {
type: 'value',
axisTick: {
show: false
},
data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
},
yAxis: {
type: 'value'
},
series: [
{
data: [150, 230, 224, 218, 135, 147, 260],
type: 'line'
}
]
}
x轴或y轴显示全部坐标
json
axisLabel:{
interval:0
},
axisLabel:{
interval:0
},
设置x轴百分比
js
yAxis: {
type: "value",
axisLabel: {
show: true,
interval: "auto",
formatter: "{value} %",
},
max: 100,
min: 0,
},
yAxis: {
type: "value",
axisLabel: {
show: true,
interval: "auto",
formatter: "{value} %",
},
max: 100,
min: 0,
},
前端js生成24小时x轴
js
// 生成指定分钟为间隔的时间数组
createTimeArr(step = 5) {
let date = new Date()
date.setHours(0) // 时分从0开始
date.setSeconds(0)
date.setUTCMinutes(5) // 秒从05开始
const timeArr = []
const slotNum = (24 * 60) / step // 算出多少个间隔
for (let f = 0; f < slotNum; f++) {
const time = new Date(Number(date.getTime()) + Number(step * 60 * 1000 * f)) // 获取:零点的时间 + 每次递增的时间
let hour = "",
sec = ""
time.getHours() < 10 ? (hour = "0" + time.getHours()) : (hour = time.getHours()) // 获取小时
time.getMinutes() < 10 ? (sec = "0" + time.getMinutes()) : (sec = time.getMinutes()) // 获取分钟
if (hour === "00" && sec === "00") {
hour = "24"
}
timeArr.push(hour + ":" + sec)
}
return timeArr
},
// 生成指定分钟为间隔的时间数组
createTimeArr(step = 5) {
let date = new Date()
date.setHours(0) // 时分从0开始
date.setSeconds(0)
date.setUTCMinutes(5) // 秒从05开始
const timeArr = []
const slotNum = (24 * 60) / step // 算出多少个间隔
for (let f = 0; f < slotNum; f++) {
const time = new Date(Number(date.getTime()) + Number(step * 60 * 1000 * f)) // 获取:零点的时间 + 每次递增的时间
let hour = "",
sec = ""
time.getHours() < 10 ? (hour = "0" + time.getHours()) : (hour = time.getHours()) // 获取小时
time.getMinutes() < 10 ? (sec = "0" + time.getMinutes()) : (sec = time.getMinutes()) // 获取分钟
if (hour === "00" && sec === "00") {
hour = "24"
}
timeArr.push(hour + ":" + sec)
}
return timeArr
},
设置平均线
js
option = {
tooltip: {},
legend: {},
xAxis: {
data: ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"]
},
yAxis: {},
series: [{
name: "Sale",
type: "bar",
data: [5, 20, 36, 10, 10, 20, 4],
markPoint: {
data: [{
type: "max"
}]
},
markLine: {
data: [{
type: "average"
}],
silent: false
}
}]
}
option = {
tooltip: {},
legend: {},
xAxis: {
data: ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"]
},
yAxis: {},
series: [{
name: "Sale",
type: "bar",
data: [5, 20, 36, 10, 10, 20, 4],
markPoint: {
data: [{
type: "max"
}]
},
markLine: {
data: [{
type: "average"
}],
silent: false
}
}]
}
图例每项之间的间隔
js
legend.itemGap = 10
legend.itemGap = 10
富文本样式formatter+rich
js
label: {
formatter: params => {
let data = params.data
if (parseFloat(data) === this.highValue) {
return `{a|${data}}`
}
return `{b|${data}}`
},
rich: {
a: {
color: "#e4952a",
fontWeight: "bold"
},
b: {
color: "#33e1ae",
fontWeight: "bold"
}
}
},
label: {
formatter: params => {
let data = params.data
if (parseFloat(data) === this.highValue) {
return `{a|${data}}`
}
return `{b|${data}}`
},
rich: {
a: {
color: "#e4952a",
fontWeight: "bold"
},
b: {
color: "#33e1ae",
fontWeight: "bold"
}
}
},
Echarts百万级数据时的渲染优化
减少数据量
从业务的角度出发:拆分图表的数据,比如年月日数据,换成按钮切换显示
Web Worker
缺点是丧失交互功能
懒加载
只渲染可视区域内的图表
降采样
echarts官方配置项,有一个sampling可用,是降采样,也就是渲染的时候不把每一个点渲染出来
折线图在数据量远大于像素点时候的降采样策略,开启后可以有效的优化图表的绘制效率,默认关闭,也就是全部绘制不过滤数据点。
可选:
- 'lttb' 采用 Largest-Triangle-Three-Bucket 算法,可以最大程度保证采样后线条的趋势,形状和极值
- 'average' 取过滤点的平均值
- 'max' 取过滤点的最大值
- 'min' 取过滤点的最小值
- 'sum' 取过滤点的和
数据为0时不显示
js
series: [
{
label: {
show: true,
position: "top",
color: "#000000",
formatter: function (params) {
if (params.value > 0) {
return params.value
} else {
return " "
}
}
},
data: []
}
]
series: [
{
label: {
show: true,
position: "top",
color: "#000000",
formatter: function (params) {
if (params.value > 0) {
return params.value
} else {
return " "
}
}
},
data: []
}
]