领导的想法需求:在页面中拖动组件到图表中,表图中的数据根据拖放的组件显示相应的图表,Demo已完成,在此做个踩坑记录。
目前的项目使用的是vue-cil,所以此Demo采用的是vue-cli+ECharts+JS完成。框架和依赖的安装在此就不做记录了。
HTML代码:
<div class="classity" id="tag">
<div class="tagcell hidden" v-for="item in dataValue" v-if="item.code=='no1'"
:data-chartvalue="JSON.stringify(item.chartList)"
draggable='true' @dragend="allowDrop($event)">
{{item.tagName}}
</div>
<div class="tagcell" v-for="item in dataValue" v-if="item.code!='no1'"
:data-chartvalue="JSON.stringify(item.chartList)"
draggable='true' @dragend="allowDrop($event)">
{{item.tagName}}
</div>
</div>
<div class="myChart">
<div id="myChart" :style="{width: '1000px', height: '750px'}"></div>
</div>
页面布局很简单,左侧一个tag栏右侧是表图。左侧tag栏中的tag设置为动态加载的,默认显示第一个选项的数据,显示后的tag为灰色,其他为蓝色。表图就很简单,设置好容器的宽高ID即可。
CSS
.container{
position: relative;
margin-top: 20px;
}
.myChart{
display: inline-block;
float: left;
margin-left: 40px;
}
.classity{
width: 300px;
height: 500px;
border: 1px solid #eee;
padding: 20px;
top: 0;
left: 0;
display: inline-block;
float: left;
}
.tagcell{
display: inline-block;
padding: 10px 20px;
margin: 5px;
height: 42px;
box-sizing: border-box;
color: #fff;
background-color: deepskyblue;
-webkit-border-radius: 3px;
-moz-border-radius: 3px;
border-radius: 3px;
float: left;
}
.hidden{
background-color: #999;
}
.prop{
display: inline-block;
position: absolute;
z-index: 999;
background-color: rgba(0,0,0,0.5);
width: 100%;
height: 100%;
top: 0;
left: 0;
font-size: 26px;
letter-spacing: 3px;
text-align: center;
color: white;
}
.tdtxt{
padding: 20px 30px;
/* border: 3px dashed white; */
vertical-align: middle;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%,-50%);
}
本地JSON
{
"data": [
{
"tagName": "销量",
"code":"no1",
"chartList": {
"titleText": "销量(单位:万件)",
"legendValue": [
"毛巾",
"帽子",
"围巾"
],
"xAxisValue": [
"一月",
"二月",
"三月",
"四月",
"五月",
"六月",
"七月",
"八月",
"九月",
"十月",
"十一月",
"十二月"
],
"seriesValue": [
{
"name": "毛巾",
"type": "bar",
"data": [
5,
20,
36,
10,
10,
20,
5,
20,
36,
10,
10,
20
]
},
{
"name": "帽子",
"type": "bar",
"data": [
5,
20,
10,
20,
5,
20,
36,
10,
36,
10,
10,
20
]
},
{
"name": "围巾",
"type": "bar",
"data": [
20,
5,
20,
36,
12,
36,
30,
10,
20,
10,
5,
20
]
}
]
}
},
{
"tagName": "营业额",
"code":"no2",
"chartList": {
"titleText": "营业额(单位:万元)",
"legendValue": [
"毛巾",
"帽子",
"围巾"
],
"xAxisValue": [
"一月",
"二月",
"三月",
"四月",
"五月",
"六月",
"七月",
"八月",
"九月",
"十月",
"十一月",
"十二月"
],
"seriesValue": [
{
"name": "毛巾",
"type": "bar",
"data": [
151,
120,
306,
100,
130,
120,
115,
230,
360,
110,
180,
270
]
},
{
"name": "帽子",
"type": "bar",
"data": [
115,
230,
360,
110,
180,
270,
100,
130,
120,
115,
230,
360
]
},
{
"name": "围巾",
"type": "bar",
"data": [
360,
110,
180,
270,
100,
130,
120,
306,
100,
130,
120,
115
]
}
]
}
},
{
"tagName": "月增长",
"code":"no3",
"chartList": {
"titleText": "月增长(单位:%)",
"legendValue": [
"毛巾",
"帽子",
"围巾"
],
"xAxisValue": [
"一月",
"二月",
"三月",
"四月",
"五月",
"六月",
"七月",
"八月",
"九月",
"十月",
"十一月",
"十二月"
],
"seriesValue": [
{
"name": "毛巾",
"type": "bar",
"data": [
20,
5,
20,
36,
-12,
36,
30,
10,
23,
10,
5,
20
]
},
{
"name": "帽子",
"type": "bar",
"data": [
50,
20,
36,
10,
10,
20,
5,
20,
36,
10,
10,
20
]
},
{
"name": "围巾",
"type": "bar",
"data": [
15,
20,
10,
20,
5,
20,
36,
10,
36,
-10,
-11,
20
]
}
]
}
}
],
"errCode": 0,
"sucess": true,
"message": "成功"
}
首先在webpack.dev.conf.js文件下进行设置,获取本地json数据。
//在webpack.dev.confi.js中大概11行后添加以下代码(const portfinder = require('portfinder' 后);)
const api = require('../src/untils/api');//设置可在api.js中设置访问路径,此处未用到
const express = require('express')
const app = express()//请求server
var appData = require('../static/data.json')//加载本地数据文件
var apiRoutes = express.Router()
app.use('/api', apiRoutes)//通过路由请求数据
const HOST = process.env.HOST
const PORT = process.env.PORT && Number(process.env.PORT)
//在 watchOptions: { poll: config.dev.poll, },后添加以下代码
before(app) {
app.get('/api', (req, res) => {
res.json({
errCode: 0,
sucess:true,
message:'成功',
data: appData
})
})
}
在新建utils文件夹,在其中添加http.js
//引入axios
import axios from 'axios';
//过滤器
axios.interceptors.request.use(function (config) {
return config
},function (error) {
console.log(error)
});
axios.interceptors.response.use(response => {
return response
}, error => {
console.log(error)
});
//剥出数据
function responseHandler(response) {
return new Promise((resolve,reject)=>{
resolve(response.data.data)
}
//返回方法
export default {
get(url,data){
return axios({
method:'GET',
url,
data:data
}).then(
(res) => {
console.log(res)
return responseHandler(res);
}
)
}
下面在组件中写方法,首先设置图表默认展示第一条tag的数据内容
//获取数据
getValue(){
http.get('/api').then(res=>{
this.dataValue = res.data;
this.chartValue= res.data[0].chartList;
this.drawLine();
})
}
drawLine(){
//基于DOM ,初始化echarts实例
let myChart = this.$echarts.init(document.getElementById("myChart"))
//绘制图表
myChart.setOption({
title:{
text:this.chartValue.titleText
},
tooltip:{},
legend: {
data:this.chartValue.legendValue
},
dataZoom: [
{
id: "dataZoomX",
type: "slider",
xAxisIndex: [0],
filterMode: "filter"
}
],
xAxis: {
data:this.chartValue.xAxisValue
},
yAxis: {},
series:this.chartValue.seriesValue
})
}
给tag绑定 @dragend="allowDrop($event)",方法如下
allowDrop:function(event){
let dom = null;
dom = event.currentTarget; //获取当前拖动的tag的dom
//获取所有tag的dom
let doms = dom.parentNode.getElementsByClassName("tagcell");
console.log(event.layerX,event.layerY);//可以拖动到范围的四个角,通过打印获取坐标范围值
//判断是否拖动到区域内
if(event.layerX >400 && event.layerX<2300 && event.layerY>20&& event.layerY<1000){
for(var i = 0 ; i < doms.length ; i++){
//遍历dom,先删除掉所有dom的展示中样式
doms[i].classList.remove("hidden");
};
//通过.getAttribute()方法获取当前拖动的dom的自定义属性data-chartvalue绑定的值
//并将获取的字符串转成对象
this.chartValue = JSON.parse(dom.getAttribute('data-chartvalue'));
//给拖动的元素添加class,让其改变为当前展示中数据的样式
dom.classList.add('hidden');
//绘制图表
this.drawLine();
}
},
这里有一个坑,给tag绑定自定义属性data-chartvalue的值必须通过JSON.stringify()转化成字符串,否则通过.getAttribute()获取的值为字符串的“Object Object]”,在data中绑定的chartValue接收数据时必须使用JSON.parse()方法再将获取的字符串转化成对象,而且需要直接赋值,不能先定义一个变量接收(如:let a;),再将chartValue赋值为JSON.parse(a)。