上司的想法需求:在頁面中拖動元件到圖表中,表圖中的資料根據拖放的元件顯示相應的圖表,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)。