天天看點

在vue中拖放元素,更新ECharts圖表資料

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

在vue中拖放元素,更新ECharts圖表資料

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)。