vue基于Echarts的拖拽数据可视化功能实现

我司产品提出了一个需求,做一个数据基于Echars的可拖拽缩放的数据可视化,上网百度了一番,结果出现了两种结局,一种花钱买成熟产品(公司不出钱),一种没有成熟代码,只能自己写了,故事即将开始,敬请期待......。  不,还是先上一张效果图吧,请看......

 

前期知识点

 

1. offset(偏移量)

定义:当前元素在屏幕上占用的空间,如下图:

其中:

offsetHeight: 该元素在垂直方向上的占用的空间,单位为px,不包括margin。

offsetWidth:该元素在水平方向上的占用空间,单位为px,不包括margin。

offsetLeft: 该元素距离左侧并且是定位过(relative || absolute)的父元素内边框的距离。注意:如果父元素中没有一个是定位的,则是距离body元素的距离。

offsetTop:该元素距离顶部并且是定位过(relative || absolute)的父元素内边框的距离。注意:如果父元素中没有一个是定位的,则是距离body元素的距离。

 

2. 鼠标事件

2.1 当前鼠标的坐标点

clientX:返回鼠标触点相对于浏览器可视区域的X坐标,单位为px,这个属性值可以根据用户对可视区的缩放行为发生变化。

clientY:返回鼠标触点相对于浏览器可视区域的Y坐标,单位为px,这个属性值可以根据用户对可视区的缩放行为发生变化。

2.2 相关的鼠标事件

ondragstart: 规定当元素被拖动时,发生什么,该属性调用一个函数,drag(event),它规定了被拖动的数据。可通过dataTransfer.setData() 方法设置被拖数据的数据类型和值:

1

2

3

4

function drag(ev)

{

 ev.dataTransfer.setData("Text",ev.target.id);

}

ondragover: 规定在何处放置被拖动的数据,默认地,无法将数据/元素放置到其他元素中。如果需要设置允许放置,我们必须阻止对元素的默认处理方式。这要通过调用 ondragover 事件的 event.preventDefault() 方法:

1

event.preventDefault()

ondrop:当放置被拖数据时,会发生 drop 事件。ondrop 属性调用了一个函数,drop(event):

1

2

3

4

5

6

7

8

9

function drop(ev)

{

 // 避免浏览器对数据的默认处理(drop 事件的默认行为是以链接形式打开)

 ev.preventDefault();

 // 获得被拖的数据。该方法将返回在 setData() 方法中设置为相同类型的任何数据。

 var data=ev.dataTransfer.getData("Text");

 // 把被拖元素追加到放置元素(目标元素)中

 ev.target.appendChild(document.getElementById(data));

}

onMouseDown: 鼠标上的按钮被按下时触发的事件

onMouseMove:鼠标移动时触发的事件

onmouseup:鼠标按下后,松开时激发的事件

 

拖拽功能

本功能以Echarts图表中柱状图为例,进行讲解:

先定义可拖拽元素

1

2

3

4

5

6

<div>

    <el-button class="drag-button" type="success" draggable="true" 

 @dragstart.native="dragStart($event,'histogram')">

 柱状图

 </el-button>

 </div>

注意:元素默认是不能进行拖拽的,需要将draggable属性设置为"true",即draggable="true" 

1

2

3

dragStart(event,type){

       event.dataTransfer.setData("Text",type);

    },

定义放置区域

1

2

3

4

<div class="grid-content bg-purple-light drag-resize-area"

 @drop.prevent="drop($event)" @dragover.prevent="">

 <div style="height:300px;width:400px" id="'histogram'></div>

</div>

其中drop事件如下:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

drop(event){

      const data=event.dataTransfer.getData("Text");

      if(data === 'histogram'){

 var myChart = echarts.init(document.getElementById('histogram')); // 指定图表的配置项和数据

 var option = {

 title: { text: 'ECharts 入门示例' },

 tooltip: {}, legend: { data:['销量'] },

 xAxis: { data: ["衬衫","羊毛衫","雪纺衫","裤子","高跟鞋","袜子"] },

 yAxis: {}, series: [{ name: '销量', type: 'bar', data: [5, 20, 36, 10, 10, 20] }]

 };

 // 使用刚指定的配置项和数据显示图表。

 myChart.setOption(option);

 }

}

基于自己封装的组件的源码请看github:github地址

效果图如下:

 

拖动功能

此功能用到了上面提到的offsetLeft、offsetTop、clientX,clientY。实现思路如下:

(1)当鼠标刚按下去时,记录当前元素距离带定位的父元素的offsetLeft、offsetTop距离;以及当前鼠标在浏览器可视区的坐标clientX、clientY的距离。

(2)分别计算两者的差值作为偏移常量,如下:

1

2

let disX = e.clientX - el.offsetLeft;

        let disY = e.clientY - el.offsetTop;

(3)监听鼠标的移动事件,获取当前鼠标距离浏览器可是区域的坐标clientX,clientY;然后减去偏移常量,即为当前元素的坐标

1

2

3

4

let tX = e.clientX - disX;

let tY = e.clientY - disY;

el.style.left = tX + 'px';

el.style.top = tY + 'px'

说明:el为当前图表对象

由于本人封装了通用vue组件,详细拖拽方法代码如下:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

      // 初始化可拖拽方法

      initDrag(){

       let el = this.$el;

       el.onmousedown = (e)=>{

            e.preventDefault();

            e.target.style.cursor = 'move'

            //鼠标按下,计算鼠标触点距离元素左侧和顶部的距离

            let disX = e.clientX - el.offsetLeft;

            let disY = e.clientY - el.offsetTop;

            // console.log('22222',document);

            document.onmousemove = function (e) {

              //计算需要移动的距离

              let tX = e.clientX - disX;

              let tY = e.clientY - disY;

              //移动当前元素

              if (tX >= 0 && tX <= window.innerWidth - el.offsetWidth) {

                el.style.left = tX + 'px';

              

              if (tY >= 0 && tY <= window.innerHeight - el.offsetHeight) {

                el.style.top = tY + 'px';

              

            };

            //鼠标松开时,注销鼠标事件,停止元素拖拽。

            document.onmouseup = function (e) {

                document.onmousemove = null;

                document.onmouseup = null;

                e.target.style.cursor = 'default';

            };

       }

     },

如果想看封装的组件,请查看github地址:github地址

拖动效果如下图:

 https://fontsup.com/profile/7m68e40cxhr89-98.html
https://fontsup.com/profile/liked/7m68e40cxhr89-98.html
https://fontsup.com/profile/sent/7m68e40cxhr89-98.html
https://fontsup.com/profile/wnbizmzyaqk22-70.html
https://fontsup.com/profile/liked/wnbizmzyaqk22-70.html
https://fontsup.com/profile/sent/wnbizmzyaqk22-70.html
https://fontsup.com/profile/rlyag544olz98-4.html
https://fontsup.com/profile/liked/rlyag544olz98-4.html
https://fontsup.com/profile/sent/rlyag544olz98-4.html
https://fontsup.com/profile/pftvkcfbxtl62-80.html
https://fontsup.com/profile/liked/pftvkcfbxtl62-80.html
https://fontsup.com/profile/sent/pftvkcfbxtl62-80.html
https://fontsup.com/profile/20bq58d8rny28-24.html
https://fontsup.com/profile/liked/20bq58d8rny28-24.html
https://fontsup.com/profile/sent/20bq58d8rny28-24.html
https://fontsup.com/profile/jy061eansia67-40.html
https://fontsup.com/profile/liked/jy061eansia67-40.html
https://fontsup.com/profile/sent/jy061eansia67-40.html
https://fontsup.com/profile/3p7r8u6qrgk63-15.html
https://fontsup.com/profile/liked/3p7r8u6qrgk63-15.html
https://fontsup.com/profile/sent/3p7r8u6qrgk63-15.html
https://fontsup.com/profile/or82ot1nfcl02-58.html
https://fontsup.com/profile/liked/or82ot1nfcl02-58.html
https://fontsup.com/profile/sent/or82ot1nfcl02-58.html
https://fontsup.com/profile/45qbwtjbcho48-64.html
https://fontsup.com/profile/liked/45qbwtjbcho48-64.html
https://fontsup.com/profile/sent/45qbwtjbcho48-64.html
https://fontsup.com/profile/51jmbdgrfme15-96.html
https://fontsup.com/profile/liked/51jmbdgrfme15-96.html
https://fontsup.com/profile/sent/51jmbdgrfme15-96.html
https://fontsup.com/profile/v9i8bfpbwpa14-7.html
https://fontsup.com/profile/liked/v9i8bfpbwpa14-7.html
https://fontsup.com/profile/sent/v9i8bfpbwpa14-7.html
https://fontsup.com/profile/z8zpf621ksi31-74.html
https://fontsup.com/profile/liked/z8zpf621ksi31-74.html
https://fontsup.com/profile/sent/z8zpf621ksi31-74.html
https://fontsup.com/profile/7pxvsnrvyyg99-6.html
https://fontsup.com/profile/liked/7pxvsnrvyyg99-6.html
https://fontsup.com/profile/sent/7pxvsnrvyyg99-6.html
https://fontsup.com/profile/2x3elx9wyni48-17.html
https://fontsup.com/profile/liked/2x3elx9wyni48-17.html
https://fontsup.com/profile/sent/2x3elx9wyni48-17.html
https://fontsup.com/profile/tw8z86r9emh41-47.html
https://fontsup.com/profile/liked/tw8z86r9emh41-47.html
https://fontsup.com/profile/sent/tw8z86r9emh41-47.html
https://fontsup.com/profile/gmlu47e1asd33-66.html
https://fontsup.com/profile/liked/gmlu47e1asd33-66.html
https://fontsup.com/profile/sent/gmlu47e1asd33-66.html
https://fontsup.com/profile/it1vj5ytyva75-32.html
https://fontsup.com/profile/liked/it1vj5ytyva75-32.html
https://fontsup.com/profile/sent/it1vj5ytyva75-32.html
https://fontsup.com/profile/w6nf0ujvlyp63-93.html
https://fontsup.com/profile/liked/w6nf0ujvlyp63-93.html
https://fontsup.com/profile/sent/w6nf0ujvlyp63-93.html
https://fontsup.com/profile/7jxrtntpokm04-80.html
https://fontsup.com/profile/liked/7jxrtntpokm04-80.html
https://fontsup.com/profile/sent/7jxrtntpokm04-80.html
https://fontsup.com/profile/u40rcnfsyqn84-26.html
https://fontsup.com/profile/liked/u40rcnfsyqn84-26.html
https://fontsup.com/profile/sent/u40rcnfsyqn84-26.html
https://fontsup.com/profile/oznqbkzypma63-15.html
https://fontsup.com/profile/liked/oznqbkzypma63-15.html
https://fontsup.com/profile/sent/oznqbkzypma63-15.html
https://fontsup.com/profile/wziovopjkga37-98.html
https://fontsup.com/profile/liked/wziovopjkga37-98.html
https://fontsup.com/profile/sent/wziovopjkga37-98.html
https://fontsup.com/profile/twzhv425kzh21-70.html
https://fontsup.com/profile/liked/twzhv425kzh21-70.html
https://fontsup.com/profile/sent/twzhv425kzh21-70.html
https://fontsup.com/profile/9zua6al8qzm47-15.html
https://fontsup.com/profile/liked/9zua6al8qzm47-15.html
https://fontsup.com/profile/sent/9zua6al8qzm47-15.html
https://fontsup.com/p

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值