项目数据分析需要用散点图,但是在官网展示的案例中没有产品想要的效果,所以花了一点时间定制散点图,另外由于散点图的数据要多一些才比较直观,所以使用了mock生成假数据
为了方便后面与后台对接,首先确定了数据结构(可以按照自己喜欢的结构自行构建)
[
{
time: 6,
rate: 90,
name: 'Mick'
}
...
]
定制1:tooltip展示除散点标记数值之外的数据。
tooltip: {
trigger: 'item',
formatter: (params)=> {
// params为当前item的能被Echarts使用的数据
const {value=[]} = params
if (value.length > 1) {
// 使用formatter格式化tooltip
return `${value[2]}:<br/>作业用时:${value[1]}分钟<br/>正确率:${value[0]}%`
}
}
}
定制2:展示平均值标线
// 在series里面添加markLine注意默认展示valueIndex为1的标线,添加多条标线需在data里面添加配置,并制定valueIndex,label可凭产品喜好自行添加。
markLine : {
silent: true, // 标线点击是静默
symbol: ['none','none'], // 标线样式
data : [
{
type: 'average',
name: '平均值',
label:{
position: 'insideEndTop',
formatter:'班级平均值线:{c}%'
}
},
{
valueIndex: 0,
type: 'average',
name: '平均值',
label:{
position: 'end',
formatter:'班级平均值线:{c}分钟' //{c}为平均值
}
}
],
},
定制3:正确率平均值以上的item显示绿色,正确率平均值以下的显示黄色
itemStyle: {
normal: {
shadowBlur: 10,
shadowColor: 'rgba(120, 36, 50, 0.5)',
shadowOffsetY: 5,
color: (e)=>{
const {data=[]} = e
if(data[1] >= this.avageRightRate){ // avageRightRate是自行求出来的
return '#52c41a'
}else{
return '#faad14'
}
}
}
},
mock数据的简单使用
- 安装: npm install mockjs --s
- 在src下创建mock文件夹,添加index.js,chart.js
- 修改chart.js及index.js文件
// chart.js
import Mock from 'mockjs'
const code = 200 // 状态码 项目同一
export default {
getScatterChartData() {
let data = Mock.mock({
'list|30': [{
'time|1-30': 8,
'rate|1-100': 50,
'name': '@name',
}]
})
return {
code,
data
}
}
}
//index.js
import mockjs from 'mockjs';
import ChartApi from './chart.js'
const Mock = require('mockjs') // 使用拦截规则拦截命中的请求
Mock.mock('api/getChartData', ChartApi.getChartData());
export default mockjs
- 在main.js中引入mock文件夹下的index.js
- 在页面使用
import axios from 'axios'
methods: {
getdata(){
axios.get('api/getChartData').then(response => {
let {list} = response.data.data; // mock生成的假数据
this.data = list
this.$nextTick(()=>{
this.echartInit() //获取到接口数据实例化Echarts组件
})
})
}
}
注意,接口请求到的数据结构不一定是Echarts希望得到的数据,因此常常需要对接口请求到的数据进行组装,至于数据结构可以与后台商量。另外mock数据也可以根据自己需要来造。可自行学习mockjs官网
补充
以上mock数据生成之后除非刷新网页才会生成新的数据,若是需要异步刷新数据需要稍微修改一下mock文件夹下的chart.js,及index.js
// chart.js
import { Random } from 'mockjs'
const code = 200
export default {
getScatterChartData() {
let list = []
for (let i = 0; i < 30; i++) {
let item = {}
item['time'] = Random.integer(0, 30)
item['rate'] = Random.integer(0, 100)
item['name'] = Random.name()
list.push(item)
}
return {
code,
data: { list }
}
}
}
// index.js
import mockjs from 'mockjs';
import ChartApi from './chart.js'
const Mock = require('mockjs')
Mock.mock('api/getChartData', () => {
return ChartApi.getScatterChartData()
});
export default mockjs
完整代码:
<template>
<div class="chart-container" ref="chart-container"></div>
</template>
<script>
import axios from 'axios'
import 'zrender/lib/svg/svg';
let echarts = require('echarts/lib/echarts');
require('echarts/lib/component/grid');
require('echarts/lib/chart/scatter');
export default {
props: {
},
data(){
return{
chartDom: null,
data:[]
}
},
mounted() {
window.addEventListener('resize',()=>{this.chartDom.resize()},false)
this.getdata()
},
destroyed() {
window.removeEventListener('resize',()=>{})
},
computed:{
dataList(){
const handleList = this.data.map(item=>{
return Object.values(item)
})
return handleList
},
avageRightRate(){
const rateArray = this.dataList.map(item=>item[1])
return window._.round(window._.mean([...rateArray]),1) // lodash方法求平均值
}
},
methods: {
getdata(){
axios.get('api/getChartData').then(response => {
let {list} = response.data.data;
this.data = list
this.$nextTick(()=>{
this.echartInit()
})
})
},
echartInit(){
this.chartDom = echarts.init(this.$refs['chart-container'],null,{renderer: 'svg'})
this.chartDom.setOption({
xAxis: {
max: 30,
splitNumber: 15,
name: '用时(分钟)',
},
yAxis: {
max: 100,
name: '正确率',
nameTextStyle:{
align: 'right',
},
minorTick:{
show: true,
splitNumber: 2
},
splitNumber: 10
},
tooltip: {
trigger: 'item',
formatter: function(params){
const {value=[]} = params
if (value.length > 1) {
return `${value[2]}:<br/>作业用时:${value[1]}分钟<br/>正确率:${value[0]}%`
}
}
},
series: [{
symbolSize: 16,
markLine : {
silent: true,
symbol: ['none','none'],
precision: 1,
data : [
{
type: 'average',
name: '平均值',
label:{
position: 'insideEndTop',
formatter:'班级平均值线:{c}%'
}
},
{
valueIndex: 0,
type: 'average',
name: '平均值',
label:{
position: 'end',
formatter:'班级平均值线:{c}分钟'
}
}
],
},
itemStyle: {
normal: {
shadowBlur: 10,
shadowColor: 'rgba(120, 36, 50, 0.5)',
shadowOffsetY: 5,
color: (e)=>{
const {data=[]} = e
if(data[1] >= this.avageRightRate){
return '#52c41a'
}else{
return '#faad14'
}
}
}
},
data: this.dataList,
type: 'scatter'
}]
})
}
}
}
</script>
<style lang="scss" scoped>
.chart-container{
width: 100%;
height: 100%;
}
</style>