最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

vue基于Echarts的拖拽數(shù)據(jù)可視化功能實現(xiàn)

 更新時間:2020年12月04日 10:42:29   作者:奔跑的五花肉888  
這篇文章主要給大家介紹了關(guān)于vue基于Echars的拖拽數(shù)據(jù)可視化功能實現(xiàn)的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧

背景

我司產(chǎn)品提出了一個需求,做一個數(shù)據(jù)基于Echars的可拖拽縮放的數(shù)據(jù)可視化,上網(wǎng)百度了一番,結(jié)果出現(xiàn)了兩種結(jié)局,一種花錢買成熟產(chǎn)品(公司不出錢),一種沒有成熟代碼,只能自己寫了,故事即將開始,敬請期待......。  不,還是先上一張效果圖吧,請看......

前期知識點

1. offset(偏移量)

定義:當(dāng)前元素在屏幕上占用的空間,如下圖:

其中:

offsetHeight: 該元素在垂直方向上的占用的空間,單位為px,不包括margin。

offsetWidth:該元素在水平方向上的占用空間,單位為px,不包括margin。

offsetLeft: 該元素距離左側(cè)并且是定位過(relative || absolute)的父元素內(nèi)邊框的距離。注意:如果父元素中沒有一個是定位的,則是距離body元素的距離。

offsetTop:該元素距離頂部并且是定位過(relative || absolute)的父元素內(nèi)邊框的距離。注意:如果父元素中沒有一個是定位的,則是距離body元素的距離。

2. 鼠標(biāo)事件

2.1 當(dāng)前鼠標(biāo)的坐標(biāo)點

clientX:返回鼠標(biāo)觸點相對于瀏覽器可視區(qū)域的X坐標(biāo),單位為px,這個屬性值可以根據(jù)用戶對可視區(qū)的縮放行為發(fā)生變化。

clientY:返回鼠標(biāo)觸點相對于瀏覽器可視區(qū)域的Y坐標(biāo),單位為px,這個屬性值可以根據(jù)用戶對可視區(qū)的縮放行為發(fā)生變化。

2.2 相關(guān)的鼠標(biāo)事件

ondragstart: 規(guī)定當(dāng)元素被拖動時,發(fā)生什么,該屬性調(diào)用一個函數(shù),drag(event),它規(guī)定了被拖動的數(shù)據(jù)??赏ㄟ^dataTransfer.setData() 方法設(shè)置被拖數(shù)據(jù)的數(shù)據(jù)類型和值:

function drag(ev)
{
 ev.dataTransfer.setData("Text",ev.target.id);
}

ondragover: 規(guī)定在何處放置被拖動的數(shù)據(jù),默認(rèn)地,無法將數(shù)據(jù)/元素放置到其他元素中。如果需要設(shè)置允許放置,我們必須阻止對元素的默認(rèn)處理方式。這要通過調(diào)用 ondragover 事件的 event.preventDefault() 方法:

event.preventDefault()

ondrop:當(dāng)放置被拖數(shù)據(jù)時,會發(fā)生 drop 事件。ondrop 屬性調(diào)用了一個函數(shù),drop(event):

function drop(ev)
{ 
 // 避免瀏覽器對數(shù)據(jù)的默認(rèn)處理(drop 事件的默認(rèn)行為是以鏈接形式打開)
 ev.preventDefault();
 // 獲得被拖的數(shù)據(jù)。該方法將返回在 setData() 方法中設(shè)置為相同類型的任何數(shù)據(jù)。
 var data=ev.dataTransfer.getData("Text");
 // 把被拖元素追加到放置元素(目標(biāo)元素)中
 ev.target.appendChild(document.getElementById(data));
}

onMouseDown: 鼠標(biāo)上的按鈕被按下時觸發(fā)的事件

onMouseMove:鼠標(biāo)移動時觸發(fā)的事件

onmouseup:鼠標(biāo)按下后,松開時激發(fā)的事件

拖拽功能

本功能以Echarts圖表中柱狀圖為例,進行講解:

先定義可拖拽元素

<div>
    <el-button class="drag-button" type="success" draggable="true" 
 @dragstart.native="dragStart($event,'histogram')">
 柱狀圖
 </el-button>
 </div>

注意:元素默認(rèn)是不能進行拖拽的,需要將draggable屬性設(shè)置為"true",即draggable="true" 

 dragStart(event,type){
       event.dataTransfer.setData("Text",type);
    },

定義放置區(qū)域

<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事件如下:

drop(event){
      const data=event.dataTransfer.getData("Text");
      if(data === 'histogram'){ 
 var myChart = echarts.init(document.getElementById('histogram')); // 指定圖表的配置項和數(shù)據(jù)
 var option = { 
 title: { text: 'ECharts 入門示例' }, 
 tooltip: {}, legend: { data:['銷量'] },
 xAxis: { data: ["襯衫","羊毛衫","雪紡衫","褲子","高跟鞋","襪子"] },
 yAxis: {}, series: [{ name: '銷量', type: 'bar', data: [5, 20, 36, 10, 10, 20] }] 
 }; 
 // 使用剛指定的配置項和數(shù)據(jù)顯示圖表。 
 myChart.setOption(option);
 }
}

基于自己封裝的組件的源碼請看github:github地址

效果圖如下:

拖動功能

此功能用到了上面提到的offsetLeft、offsetTop、clientX,clientY。實現(xiàn)思路如下:

(1)當(dāng)鼠標(biāo)剛按下去時,記錄當(dāng)前元素距離帶定位的父元素的offsetLeft、offsetTop距離;以及當(dāng)前鼠標(biāo)在瀏覽器可視區(qū)的坐標(biāo)clientX、clientY的距離。

(2)分別計算兩者的差值作為偏移常量,如下:

 let disX = e.clientX - el.offsetLeft;
        let disY = e.clientY - el.offsetTop;

(3)監(jiān)聽鼠標(biāo)的移動事件,獲取當(dāng)前鼠標(biāo)距離瀏覽器可是區(qū)域的坐標(biāo)clientX,clientY;然后減去偏移常量,即為當(dāng)前元素的坐標(biāo)

 let tX = e.clientX - disX;
 let tY = e.clientY - disY; 
 el.style.left = tX + 'px'; 
 el.style.top = tY + 'px';

說明:el為當(dāng)前圖表對象

由于本人封裝了通用vue組件,詳細(xì)拖拽方法代碼如下:

      // 初始化可拖拽方法
      initDrag(){
       let el = this.$el;
       el.onmousedown = (e)=>{
            e.preventDefault();
            e.target.style.cursor = 'move'; 
            //鼠標(biāo)按下,計算鼠標(biāo)觸點距離元素左側(cè)和頂部的距離
            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;
              //移動當(dāng)前元素
              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';
              } 
            };
            //鼠標(biāo)松開時,注銷鼠標(biāo)事件,停止元素拖拽。
            document.onmouseup = function (e) {
                document.onmousemove = null;
                document.onmouseup = null;
                e.target.style.cursor = 'default';
            };
       }
     },

如果想看封裝的組件,請查看github地址:github地址

拖動效果如下圖:

縮放功能

此功能用到了上面提到的 offsetWidth、offsetHeight、offsetLeft、offsetTop、clientX,clientY。實現(xiàn)思路如下:

(1)先設(shè)置可縮放的四個拖拽方框

<div v-show="isResize && resizeFlag" ref="resizeDivTag" id="resizeDivTag">
        <span class="br"></span>
        <span class="bl"></span>
        <span class="tr"></span>
        <span class="tl"></span> 
    </div>

其中isResize 與 resizeFlag表示是否可縮放以及是否可拖拽

(2)為每個可可縮放方框設(shè)置縮放函數(shù),請看注釋

// 初始化可縮放
      initResize(){
        let el = this.$el; //獲取當(dāng)前元素
        let spanNodes = this.$refs.resizeDivTag.childNodes;
        for(let i=0;i<spanNodes.length;i++){
          this.resizeElementFun(spanNodes[i],el); // 分別為四個縮放方框設(shè)置監(jiān)聽事件
        }
      },
      resizeElementFun(element,el){
        element.onmousedown = function(ev){
          console.log('我是按下的元素')
          let oEv = ev || event;
          oEv.stopPropagation();
          let oldWidth = el.offsetWidth; // 當(dāng)前元素的寬度
          let oldHeight  = el.offsetHeight; // 當(dāng)前元素的高度
          console.log('-----'+ oldWidth+'----'+oldHeight);
          let oldX = oEv.clientX; // 當(dāng)前鼠標(biāo)對于瀏覽器可視區(qū)域的X坐標(biāo)
          let oldY = oEv.clientY; // 當(dāng)前鼠標(biāo)對于瀏覽器可視區(qū)域的Y坐標(biāo)
          let oldLeft = el.offsetLeft; // 當(dāng)前元素對于父級定位元素的寬度
          let oldTop = el.offsetTop; // 當(dāng)前元素對于父級定位元素的高度
          console.log('--zuo---'+ oldLeft+'--gao--'+oldTop);
          document.onmousemove = function(ev){
            // oEv.stopPropagation();
            let oEv = ev || event;
            let disY = (oldTop + (oEv.clientY - oldY)); // 當(dāng)前縮放的元素距離定位父元素的高度
            // let disX = (oldLeft + (oEv.clientX - oldLeft));
            let disX = (oldLeft + (oEv.clientX - oldX)); // 當(dāng)前縮放的元素距離定位父元素的寬度
            if(disX>oldLeft+oldWidth){
                disX=oldLeft+oldWidth
            }
            if(disY>oldTop+oldHeight){
                disY=oldTop+oldHeight
            }
            if(element.className == 'tl'){ // 左上縮放時
              el.style.width = oldWidth - (oEv.clientX - oldX) + 'px'; 
 // 元素寬度= 縮放前寬度-鼠標(biāo)當(dāng)前坐標(biāo)與原始坐標(biāo)差值
              el.style.height = oldHeight - (oEv.clientY - oldY) + 'px';
 // 元素寬度= 縮放前高度-鼠標(biāo)當(dāng)前坐標(biāo)與原始坐標(biāo)差值
              el.style.left = disX + 'px';
 // 元素距離父元素的距離 = 
              el.style.top = disY + 'px';
            } else if (element.className == 'bl'){ // 左下
              el.style.width = oldWidth - (oEv.clientX - oldX) + 'px';
              el.style.height = oldHeight + (oEv.clientY - oldY) + 'px';
              el.style.left = disX + 'px';
              // el.style.bottom = oldTop + (oEv.clientY + oldY) + 'px';
            } else if (element.className == 'tr'){ //右上
              el.style.width = oldWidth + (oEv.clientX - oldX) + 'px';
              el.style.height = oldHeight - (oEv.clientY - oldY) + 'px';
              el.style.right = oldLeft - (oEv.clientX - oldX) + 'px';
              el.style.top = disY + 'px';
            } else if (element.className == 'br'){ //右下
              el.style.width = oldWidth + (oEv.clientX - oldX) + 'px';
              el.style.height = oldHeight + (oEv.clientY - oldY) + 'px';
              el.style.right = oldLeft - (oEv.clientX - oldX) + 'px';
              // el.style.bottom = oldTop + (oEv.clientY + oldY) + 'px';
            }
          }
          document.onmouseup = function(){
            document.onmousemove = null;
          };
          return false;
        }
      },

如果想看封裝的組件,請查看github地址:github地址

縮放效果如下圖:

Echarts縮放中存在的問題

vue中使用echarts圖表自適應(yīng)的幾種基本解決方案,此處不再進行贅述,詳情請參考如下鏈接:echarts圖表自適應(yīng)

結(jié)束語

本文只是粗略的記錄了數(shù)據(jù)可視化簡單demo的實現(xiàn)思路,如果您覺得對您有幫助,請下載源碼  github地址

喜歡的小伙伴給個star,謝謝

參考文獻(xiàn)

http://www.fzitv.net/article/201371.htm

http://www.fzitv.net/article/201349.htm

到此這篇vue基于Echarts的拖拽數(shù)據(jù)可視化功能實現(xiàn)的文章就介紹到這了,更多相關(guān)vue基于Echarts拖拽數(shù)據(jù)可視化內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • vue中el-form-item展開項居中的實現(xiàn)方式

    vue中el-form-item展開項居中的實現(xiàn)方式

    這篇文章主要介紹了vue中el-form-item展開項居中的實現(xiàn)方式,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2023-10-10
  • 詳解vue之頁面緩存問題(基于2.0)

    詳解vue之頁面緩存問題(基于2.0)

    本篇文章主要介紹了vue之頁面緩存問題(基于2.0),小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-01-01
  • vue axios同步請求解決方案

    vue axios同步請求解決方案

    這篇文章主要介紹了vue axios同步請求解決方案,需要的朋友可以參考下
    2017-09-09
  • vue腳手架創(chuàng)建項目時報catch錯誤及解決

    vue腳手架創(chuàng)建項目時報catch錯誤及解決

    這篇文章主要介紹了vue腳手架創(chuàng)建項目時報catch錯誤及解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-01-01
  • vue-cli在 history模式下的配置詳解

    vue-cli在 history模式下的配置詳解

    這篇文章主要介紹了vue-cli在 history模式下的配置詳解,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-11-11
  • vue實現(xiàn)隨機驗證碼功能的實例代碼

    vue實現(xiàn)隨機驗證碼功能的實例代碼

    這篇文章主要介紹了vue實現(xiàn)隨機驗證碼功能的實例代碼,代碼簡單易懂,非常不錯,具有一定的參考借鑒價值,需要的朋友可以參考下
    2019-04-04
  • vue3組件化開發(fā)之可復(fù)用性的應(yīng)用實例詳解

    vue3組件化開發(fā)之可復(fù)用性的應(yīng)用實例詳解

    不斷把公共的、可以獨立拆分出來的抽出來作為一個獨立可復(fù)用的組件來向上提供調(diào)用,這樣讓我們的代碼更加方便組織和管理,并且擴展性也更強,下面這篇文章主要給大家介紹了關(guān)于vue3組件化開發(fā)之可復(fù)用性應(yīng)用的相關(guān)資料,需要的朋友可以參考下
    2022-06-06
  • vue中el-message的封裝使用

    vue中el-message的封裝使用

    本文主要介紹了vue中el-message的封裝使用,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-02-02
  • Vue3?中的?readonly?特性及函數(shù)使用詳解

    Vue3?中的?readonly?特性及函數(shù)使用詳解

    readonly是Vue3中提供的一個新特性,用于將一個響應(yīng)式對象變成只讀對象,這篇文章主要介紹了Vue3?中的?readonly?特性詳解,需要的朋友可以參考下
    2023-04-04
  • vue中的keep-alive詳解與應(yīng)用場景

    vue中的keep-alive詳解與應(yīng)用場景

    keep-alive是vue中的內(nèi)置組件,能在組件切換過程中將狀態(tài)保留在內(nèi)存中,防止重復(fù)渲染DOM,本文給大家介紹vue中的keep-alive詳解與應(yīng)用場景,感興趣的朋友一起看看吧
    2023-11-11

最新評論

灵台县| 高安市| 灵璧县| 历史| 轮台县| 集贤县| 凤台县| 陕西省| 铁岭市| 周宁县| 勃利县| 和政县| 岢岚县| 兴文县| 铁岭县| 红河县| 南雄市| 孟连| 宾川县| 肇源县| 南华县| 姜堰市| 疏勒县| 蕲春县| 都兰县| 科尔| 广水市| 江城| 枣庄市| 措勤县| 隆林| 玉环县| 宜城市| 油尖旺区| 北川| 平遥县| 五常市| 濮阳市| 南华县| 曲靖市| 象州县|