天天看点

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