html
<template>
<div class="app-container dashboard">
<el-popover placement="left" width="30%" trigger="click" class="btn-add">
<el-collapse v-model="activeNames">
<el-collapse-item v-for="item in projectList" :key="item.key" :title="item.title" :name="item.key">
<div v-for="row in item.list" :key="row.key">
<el-switch v-model="row.isShow" :active-text="row.name" @change="isShow(row)">el-switch>
div>
el-collapse-item>
el-collapse>
<el-button type="primary" icon="el-icon-plus" slot="reference" circle>el-button>
el-popover>
<div id="canvas">
<div class="item" v-for="(item, index) in divList" :key="index" draggable="true" :id="item.key"
@dragstart="handleDragStart($event, item)"
@dragenter="handleDragEnter($event, item)"
@dragover.prevent="handleDragover($event, item)"
@drop="handleDrop($event, item)"
@dragend="handleDragEnd($event, item)">
div>
div>
div>
template>
js
<script>
// 生成图表
import dashboardChart from './chart/dashboardChart'
export default {
name: 'dashboard',
data() {
return {
divList: [],
projectList: [],
activeNames: [],
dragging: null
}
},
mounted() {
this.getList()
},
methods: {
// 获取已保存的图表
getList() {
this.projectList = [
{
title: '申请环节',
key: '1',
list: [
{ name: '累计放款VS预估值', key: 'estimate', type: 'dashboard', color: '#1890FF', value: 0.1, isShow: false },
{ name: '累计放款VS余额', key: 'totalBalance', type: 'dashboard', color: '#95DE64', value: 0.2, isShow: false }
]
}
]
for (const i in this.projectList) {
const project = this.projectList[i]
this.activeNames.push(project.key)
// 遍历出已经选择的图表
for (const j in project.list) {
const one = project.list[j]
// 把选择的图表在页面渲染出来
if (one.isShow === true) {
this.divList.push(one)
this.$nextTick(() => {
this.getChart(one)
})
}
}
}
},
// 在页面新增或删除图表
isShow(row) {
// 新增
if (row.isShow === true) {
this.divList.push(row)
this.$nextTick(() => {
this.getChart(row)
})
// 删除
} else {
for (const i in this.divList) {
if (row.key === this.divList[i].key) {
this.divList.splice(i, 1)
}
}
this.$nextTick(() => {
for (const j in this.divList) {
document.getElementById(this.divList[j].key).innerHTML = ''
this.getChart(this.divList[j])
}
})
}
},
// 生成图表
getChart(row) {
if (row.type === 'dashboard') {
const value = [
{ value: row.value }
]
dashboardChart(row.key, value, row.color, row.name)
}
},
// 当元素被拖动时
handleDragStart(e, item) {
this.dragging = item
},
// 当被鼠标拖动的对象进入其容器范围内时触发此事件
handleDragEnter(e) {
// 为需要移动的元素设置dragstart事件
e.dataTransfer.effectAllowed = 'move'
},
// 当某被拖动的对象在另一对象容器范围内拖动时触发此事件
handleDragover(e) {
// 首先把div变成可以放置的元素,即重写dragenter/dragover
// 在dragenter中针对放置目标来设置!
e.dataTransfer.dropEffect = 'move'
},
// 当放置被拖元素时
handleDrop(e, item) {
e.dataTransfer.dropEffect = 'move'
if(item === this.dragging){
return
}
const newItems = [...this.divList]
const from = newItems.indexOf(this.dragging)
const to = newItems.indexOf(item)
newItems[from] = item
newItems[to] = this.dragging
this.divList = newItems
document.getElementById(this.dragging.key).innerHTML = ''
document.getElementById(item.key).innerHTML = ''
this.$nextTick(() => {
this.getChart(newItems[from])
this.getChart(newItems[to])
})
},
// 完成元素拖动后触发
handleDragEnd() {
this.dragging = null
}
}
}
</script>
dashboardChart
import G2 from '@antv/g2'
/**
* 仪表盘
* @param {*} id 容器
* @param {*} data 数据
* [{ value: 0.5 }]
* @param {*} color 颜色
* @param {*} title 标题
*/
function draw(id, data, color, title) {
var Shape = G2.Shape;
// 自定义Shape 部分
Shape.registerShape('point', 'pointer', {
drawShape: function drawShape(cfg, group) {
var center = this.parsePoint({ // 获取极坐标系下画布中心点
x: 0,
y: 0
});
// 绘制指针
group.addShape('line', {
attrs: {
x1: center.x,
y1: center.y,
x2: cfg.x,
y2: cfg.y,
stroke: cfg.color,
lineWidth: 3,
lineCap: 'round'
}
});
return group.addShape('circle', {
attrs: {
x: center.x,
y: center.y,
r: 8,
stroke: cfg.color,
lineWidth: 2.5,
fill: '#fff'
}
});
}
});
var chart = new G2.Chart({
container: id,
forceFit: true,
height: 250,
padding: 'auto'
});
chart.source(data);
chart.coord('polar', {
startAngle: -10 / 8 * Math.PI,
endAngle: 2 / 8 * Math.PI,
radius: 0.75
});
chart.scale('value', {
min: 0,
max: 1,
nice: false,
ticks: [0.1, 0.3, 0.5, 0.7, 0.9]
});
chart.axis('1', false);
chart.axis('value', {
zIndex: 2,
line: null,
label: {
offset: -15,
formatter: function formatter(val) {
if (val === '0.1') {
return '10%';
} else if (val === '0.3') {
return '30%';
} else if (val === '0.5') {
return '50%';
} else if (val === '0.7') {
return '70%';
} else if (val === '0.9') {
return '90%';
}
},
textStyle: {
fontSize: 14,
textAlign: 'center'
}
},
tickLine: null,
grid: null
});
chart.legend(false);
chart.point().position('value*1').shape('pointer').color(color).active(false);
// 绘制仪表盘刻度线
chart.guide().line({
start: [0.1, 0.95],
end: [0.1, 0.85],
lineStyle: {
stroke: color, // 线的颜色
lineDash: null, // 虚线的设置
lineWidth: 2
}
});
chart.guide().line({
start: [0.3, 0.95],
end: [0.3, 0.85],
lineStyle: {
stroke: color, // 线的颜色
lineDash: null, // 虚线的设置
lineWidth: 2
}
});
chart.guide().line({
start: [0.5, 0.95],
end: [0.5, 0.85],
lineStyle: {
stroke: color, // 线的颜色
lineDash: null, // 虚线的设置
lineWidth: 2
}
});
chart.guide().line({
start: [0.7, 0.95],
end: [0.7, 0.85],
lineStyle: {
stroke: color, // 线的颜色
lineDash: null, // 虚线的设置
lineWidth: 2
}
});
chart.guide().line({
start: [0.9, 0.95],
end: [0.9, 0.85],
lineStyle: {
stroke: color, // 线的颜色
lineDash: null, // 虚线的设置
lineWidth: 2
}
});
// 绘制仪表盘背景
chart.guide().arc({
zIndex: 0,
top: false,
start: [0, 0.965],
end: [1, 0.965],
style: { // 底灰色
stroke: '#F5F5F5',
lineWidth: 10
}
});
// 绘制指标
chart.guide().arc({
zIndex: 1,
start: [0, 0.965],
end: [data[0].value, 0.965],
style: {
stroke: color,
lineWidth: 10
}
});
// 绘制指标数字
chart.guide().html({
position: ['50%', '95%'],
html: '' + ''
+ title + '' + ''
+ ((data[0].value) * 100).toFixed(2) + '%' + ''
});
chart.render();
return chart
}
export default draw
css