整合營銷服務商

          電腦端+手機端+微信端=數據同步管理

          免費咨詢熱線:

          純原生javascript實現拖拽效果,簡單實用

          要用到的 JS 事件有:

          onmousedown:鼠標點下事件

          onmousemove:鼠標移動事件

          onmouseup:鼠標放開事件

          具體代碼如下:

          <!doctype html>
          <html lang="en">
          <head>
          <meta charset="UTF-8">
          <title>列拖動</title>
          <style type="text/css">
          body,ul,li {padding: 0; margin: 0;}
          ul, li {list-style: none;}
          .left {width: 300px; float: left;margin: 3px;}
          .right {width: 300px; float: left; margin:3px;}
          .column {width: 200px;height: 30px; line-height: 30px; background-color: #AACCFF; margin: 8px 5px; text-align: center; cursor: pointer;}
          .columnOld {width: 200px; height: 30px; line-height: 30px; background-color: #CCC; margin: 8px 5px; text-align: center;}
          .target {border: 1px solid #CCC; background-color: #FFF5EE;box-shadow: 0 0 8px #CCC; -moz-box-shadow: 0 0 8px #CCC; -webkit-box-shadow: 0 0 8px #CCC;}
          .container {width: 600px; height: 200px; display: block;}
          </style>
          <script type="text/javascript" src="jquery.js"></script>
          <script type="text/javascript">
          window.onload = function(){
          var Lis = document.getElementsByClassName("column");
          var container = document.getElementsByClassName("container")[0];
          for (var i = Lis.length - 1; i >= 0; i--) {
          var obj = Lis[i];
          var source = obj.parentNode;
          var target = document.getElementById("container");
          moveColumn(obj, target, source);
          }
          }
          /**
          * 字段拖拽事件
          */
          function moveColumn(obj, target, source) {
          // 1. 獲取事件
          obj.onmousedown = function(event) {
          var ev = event || window.event;
          // 2. 復制新節點,設置透明度和innerHTML,class
          var newObj = document.createElement("li");
          newObj.className = 'column';
          newObj.style.opacity = '0.5';
          newObj.style.filter = 'alpha(opacity:50)';
          newObj.innerHTML = obj.innerHTML;
          newObj.style.margin = '0';
          newObj.style.position = 'absolute';
          newObj.style.zIndex = '5';
          newObj.source = source;
          // 3. 計算點擊點在 obj 上的位置
          var disH = ev.clientY - obj.offsetTop;
          var disL = ev.clientX - obj.offsetLeft;
          // 4. 設置絕對定位的top和left
          newObj.style.top = obj.offsetTop + 'px';
          newObj.style.left = obj.offsetLeft + 'px';
          // 5. 添加節點
          obj.parentNode.appendChild(newObj);
          // 6. 鼠標移動事件
          document.onmousemove = function(e) {
          // 1. 獲取事件
          var e = e || window.event;
          // 2. 獲取鼠標位置,設置newObj的定位
          var L = e.clientX - disL;
          var T = e.clientY - disH;
          newObj.style.top = T + 'px';
          newObj.style.left = L + 'px';
          // 3. source 背景色和邊框變換
          $(target).addClass("target");
          obj.className = "columnOld";
          }
          // 7. 鼠標松開事件
          document.onmouseup = function() {
          $(target).removeClass("target");
          // target.class = '';
          var not = newObj.offsetTop;
          var nol = newObj.offsetLeft;
          var tot = target.offsetTop;
          var tol = target.offsetLeft;
          if (not >= tot && nol >= tol && not <= tot + target.offsetHeight && nol <= tol + target.offsetWidth) {
          newObj.removeAttribute('style');
          newObj.className = "column";
          newObj.style.float = "left";
          target.appendChild(newObj);
          backColumn(newObj, source, target);
          var id = obj.id;
          newObj.id = id;
          obj.id = id + "_old";
          obj.onmousedown = null;
          } else {
          obj.className = "column";
          obj.parentNode.removeChild(newObj);
          }
          document.onmouseup = null;
          document.onmousemove = null;
          }
          }
          }
          function backColumn(obj, target, source) {
          var Lis = source.getElementsByTagName('li');
          var lineNum = Math.floor(source.offsetWidth / 210);
          var liFirst = Lis[0].offsetTop;
          var liHeight = Lis[0].offsetHeight;
          var liWidth = Lis[0].offsetWidth;
          // 1. 獲取事件
          obj.onmousedown = function(event) {
          var ev = event || window.event;
          // 2. 復制新節點,設置透明度和innerHTML,class
          var newObj = document.createElement("li");
          newObj.className = 'column';
          newObj.style.opacity = '0.5';
          newObj.style.filter = 'alpha(opacity:50)';
          newObj.innerHTML = obj.innerHTML;
          newObj.style.margin = '0';
          newObj.style.position = 'absolute';
          newObj.style.zIndex = '5';
          // 3. 計算點擊點在 obj 上的位置
          var disH = ev.clientY - obj.offsetTop;
          var disL = ev.clientX - obj.offsetLeft;
          // 4. 設置絕對定位的top和left
          newObj.style.top = obj.offsetTop + 'px';
          newObj.style.left = obj.offsetLeft + 'px';
          // 5. 添加節點
          obj.parentNode.appendChild(newObj);
          // 6. 添加空白節點(占位)
          var blank = document.createElement("li");
          blank.className = 'column';
          blank.style.backgroundColor = '#63B8FF';
          blank.style.float = "left";
          // 6. 鼠標移動事件
          document.onmousemove = function(e) {
          // 1. 獲取事件
          var e = e || window.event;
          // 2. 獲取鼠標位置,設置newObj的定位
          var L = e.clientX - disL;
          var T = e.clientY - disH;
          newObj.style.top = T + 'px';
          newObj.style.left = L + 'px';
          // 3. source 背景色和邊框變換
          $(target).addClass("target");
          obj.className = "columnOld";
          // 根據當前拖拽到的位置計算其重新排序后的位置
          var line = lineNum * Math.round((T - liFirst)/liHeight)
          var n = line + Math.floor(L / liWidth);
          // 將空白節點插入到該位置
          // if ()
          source.insertBefore(blank,source.children[n]);
          }
          // 7. 鼠標松開事件
          document.onmouseup = function() {
          $(target).removeClass("target");
          // target.class = '';
          var not = newObj.offsetTop;
          var nol = newObj.offsetLeft;
          var tot = target.offsetTop;
          var tol = target.offsetLeft;
          if (not >= tot && nol >= tol && not <= tot + target.offsetHeight && nol <= tol + target.offsetWidth) {
          var oldObj = document.getElementById(obj.id + '_old');
          oldObj.className = 'column';
          source.removeChild(newObj);
          source.removeChild(obj);
          oldObj.id = obj.id;
          moveColumn(oldObj, source, target);
          obj.onmousedown = null;
          } else {
          obj.className = "column";
          obj.parentNode.removeChild(newObj);
          // 將被拖拽的元素插入到空白節點的位置
          if (blank.parentNode == source) {
          source.insertBefore(obj,blank);
          }
          // 刪除拖拽樣式
          // obj.removeAttribute('style');
          }
          if (blank.parentNode == source) {
          // 刪除空白節點
          source.removeChild(blank);
          }
          document.onmouseup = null;
          document.onmousemove = null;
          }
          }
          }
          function getStyle(obj, attr) {
          if (obj.currentStyle) {
          return obj.currentStyle[attr];
          } else {
          return getComputedStyle(obj, false)[attr];
          }
          }
          </script>
          </head>
          <body>
          <div style="overflow: hidden;">
          <ul class="left">
          <li class="column" id="c1">字段a-1</li>
          <li class="column" id="c2">字段a-2</li>
          <li class="column" id="c3">字段a-3</li>
          <li class="column" id="c4">字段a-4</li>
          <li class="column" id="c5">字段a-5</li>
          </ul>
          <ul class="right">
          <li class="column" id="c6">字段b-1</li>
          <li class="column" id="c7">字段b-2</li>
          <li class="column" id="c8">字段b-3</li>
          <li class="column" id="c9">字段b-4</li>
          <li class="column" id="c10">字段b-5</li>
          </ul>
          </div>
          <div class="container" id="container">
          </div>
          </body>
          </html>
          

          最終效果

          比較簡單,歡迎留言指正,代碼比較冗余,還沒來得及做整理,往見諒。

          看效果圖:

          拖拽前

          拖拽后

          我在header處加了的id 然后通過其點擊事件給其父容器根據鼠標移動來判斷位置,寫的比較簡陋,只能按住黑框部分處才能進行拖拽

          附上代碼:

          ueDraggablePlus:實現靈活拖拽的前端神器

          大家好,我是墩墩大魔王丶,今天我將為大家介紹一款功能強大、靈活易用的前端組件——VueDraggablePlus。作為前端工程師,我們經常會遇到需要實現拖拽功能的場景,而VueDraggablePlus正是為了解決這一痛點而誕生的。讓我們一起來看看它的特點和用法吧!

          VueDraggablePlus是一個功能齊全、無縫遷移、靈活使用的拖拽組件,完全繼承了Sortable.js的所有功能,支持Vue 3和Vue 2,使用TypeScript編寫并提供完整的TS文檔,支持雙向綁定和自定義容器,可以通過組件、指令或函數式調用實現拖拽功能。

          官網: alfred-skyblue.gitee.io/vue-draggab…

          場景化引入:解決拖拽列表痛點

          在日常開發中,我們經常會遇到需要實現拖拽列表的需求,但是傳統的方法往往需要將拖拽功能作為列表的直接子元素來實現,這在一些情況下會受到限制。比如,當我們使用一些組件庫時,如果組件庫中沒有提供列表根元素的插槽,我們就很難實現拖拽列表。這時,VueDraggablePlus就派上了用場!它可以讓你在任何元素上使用拖拽列表,通過指定元素的選擇器,來獲取到列表根元素,然后將列表根元素作為拖拽容器,輕松實現拖拽功能。

          安裝

          npm install vue-draggable-plus
          


          <template>
              <VueDraggable ref="el" v-model="list">
                <div v-for="item in list" :key="item.id">
                  {{ item.name }}
                </div>
              </VueDraggable>
          </template>
          
          <script setup lang="ts">
          import { ref } from 'vue'
          import { VueDraggable } from 'vue-draggable-plus'
          const list = ref([
            {
              name: 'Joao',
              id: 1
            },
            {
              name: 'Jean',
              id: 2
            },
            {
              name: 'Johanna',
              id: 3
            },
            {
              name: 'Juan',
              id: 4
            }
          ])
          </script>
          


          alfred-skyblue.gitee.io/vue-draggab…

          使用說明:多種用法靈活選擇

          VueDraggablePlus提供了多種使用方式,您可以根據自己的需求選擇最適合的方式來實現拖拽功能。您可以使用組件的方式,在需要拖拽的元素上直接添加VueDraggablePlus組件;也可以使用函數的方式,通過調用函數來實現拖拽功能;還可以使用指令的方式,通過指定元素的選擇器來實現拖拽功能??傆幸豢钸m合您!

          <template>
              <div
                v-draggable="[
                  list,
                  {
                    animation: 150,
                  }
                ]"
              >
                <div
                  v-for="item in list"
                  :key="item.id"
                >
                  {{ item.name }}
                </div>
              </div>
          </template>
          
          <script setup lang="ts">
          import { ref } from 'vue'
          import { vDraggable } from 'vue-draggable-plus'
          const list = ref([
            {
              name: 'Joao',
              id: 1
            },
            {
              name: 'Jean',
              id: 2
            },
            {
              name: 'Johanna',
              id: 3
            },
            {
              name: 'Juan',
              id: 4
            }
          ])
          
          function onStart() {
            console.log('start')
          }
          
          function onUpdate() {
            console.log('update')
          }
          </script>
          


          這里我們使用了VueDraggablePlus組件的方式來實現拖拽列表,將列表項包裹在VueDraggablePlus組件內,即可輕松實現拖拽功能。

          解決痛點:完美繼承Sortable.js功能

          VueDraggablePlus完全繼承了Sortable.js的所有功能,讓您可以盡情享受拖拽的樂趣。無論是拖拽排序、拖拽上傳還是拖拽調整布局,VueDraggablePlus都可以輕松應對,讓您的前端開發更加便捷高效。

          演示:多種場景應用

          VueDraggablePlus不僅功能強大,而且還支持多種場景的應用。比如雙列表拖拽、克隆、自定義克隆、指定元素觸發、指定目標容器、內置動畫合并等,為您的項目提供了更多的可能性。


          組件參數和事件

          參數

          參數

          說明

          類型

          默認值

          animation

          拖動時顯示動畫

          Number

          0

          chosenClass

          被選中項的 CSS 類名

          String

          'sortable-chosen'

          delay

          選中拖拽延時

          Number

          0

          delayOnTouchOnly

          touch 事件延遲

          Number

          0

          direction

          拖拽方向,默認自動判斷??蛇x值有horizontal 和 vertical

          String

          -

          disabled

          是否禁止拖拽

          Boolean

          false

          dragClass

          拖拽項類名

          String

          'sortable-drag'

          draggable

          指定元素內的哪些項目應該是可拖動的

          String

          -

          emptyInsertThreshold

          拖動時鼠標必須與空可排序項的距離(以像素為單位),以便將拖動元素插入到該可排序項中, 設置為0禁用此功能。

          Number

          5

          easing

          簡化動畫。

          Easing

          -

          fallbackClass

          當使用forceFallback的時候,被復制的dom的css類名

          String

          sortable-fallback

          fallbackOnBody

          將cloned DOM 元素掛到body元素上。

          Boolean

          false

          fallbackTolerance

          以像素為單位指定鼠標在被視為拖動之前應該移動多遠。

          Number

          0

          filter

          不需要進行拖動的元素

          String

          -

          forceFallback

          忽略 HTML5拖拽行為,強制回退

          Boolean

          false

          ghostClass

          drop placeholder的css類名

          String

          'sortable-ghost'

          group

          要將元素從一個列表拖到另一個列表中,兩個列表必須具有相同的group 值。您還可以定義列表是否可以被移出、或者克隆以及接收其他列表元素。詳情查閱上方TS類型定義

          Group

          -

          handle

          設置可拖拽句柄的css類名,如果不設置,默認對目標元素的子列表操作進行拖拽

          String

          -

          invertSwap

          如果設置為 true,將始終使用反向交換區

          Boolean

          false

          invertedSwapThreshold

          反向交換閾值,默認情況下將設置為swapThreshold 值

          Number

          -

          preventOnFilter

          觸發filter時調用event.preventDefault()

          Boolean

          true

          removeCloneOnHide

          刪除不顯示的克隆元素,而不是僅僅隱藏它

          Boolean

          true

          sort

          定義列表單元是否可以在列表容器內進行拖拽排序

          Boolean

          true

          swapThreshold

          交換區的閾值

          Number

          1

          touchStartThreshold

          在取消延遲拖動事件之前點應該移動多少像素

          Number

          1

          setData

          傳遞一個函數,函數的第一個參數為DataTransfer類型,第二個參數為HTMLElement 類型

          Function

          -

          scroll

          是否啟用滾動

          Boolean or HTMLElement

          true

          scrollFn

          自定義滾動

          ScrollFn

          -

          scrollSensitivity

          鼠標必須離邊緣多近才能開始滾動,單位 px

          Number

          -

          scrollSpeed

          滾動速度(ms/px)

          Number

          -

          bubbleScroll

          將自動滾動應用于所有父元素,以便更輕松地移動

          Boolean

          true

          事件函數

          事件函數名稱

          說明

          類型

          onChoose

          元素被選中時觸發

          ((event: SortableEvent) => void)

          onUnchoose

          元素取消選中時觸發

          ((event: SortableEvent) => void)

          onStart

          拖拽開始時觸發

          ((event: SortableEvent) => void)

          onEnd

          拖拽結束時觸發

          ((event: SortableEvent) => void)

          onAdd

          元素從一個列表拖拽到另一個列表時觸發

          ((event: SortableEvent) => void)

          onUpdate

          元素順序更新時觸發

          ((event: SortableEvent) => void)

          onSort

          列表任何更改都會觸發

          ((event: SortableEvent) => void)

          onRemove

          元素從列表中移除時觸發

          ((event: SortableEvent) => void)

          onFilter

          拖拽一個被過濾元素時觸發

          ((event: SortableEvent) => void)

          onMove

          拖拽移動時觸發

          ((event: MoveEvent,originalEvent: Event) => void)

          onClone

          克隆一個元素時觸發

          ((event: SortableEvent) => void)

          onChange

          拖拽元素改變位置時觸發

          `((event: SortableEvent) =>

          示例

          通過 監聽 onStart 事件, 將當前選中項的背景設置為白透明的白色。

          其中 SortableEvent 的 item 即當前拖拽項, 通過改變它的 style 即可。

          通過 監聽 onEnd 事件, 在拖拽結束時 ,將當前選中項的背景顏色還原。

          <template>
            <VueDraggable ref="el" v-model="list" @start="onStart" @end="onEnd">
              <div v-for="item in list" :key="item.id" class="drag-item">
                <NodejsButton :title="item.name" />
              </div>
            </VueDraggable>
          </template>
          
          <script setup>
          import { ref } from 'vue'
          import NodejsButton from '@/components/button/nodejs-button.vue'
          import { VueDraggable } from 'vue-draggable-plus'
          const list = ref([
            {
              name: 'Aoooooo',
              id: 1
            },
            {
              name: 'Boooooo',
              id: 2
            },
            {
              name: 'Coooooo',
              id: 3
            },
            {
              name: 'Doooooo',
              id: 4
            }
          ])
          
          const onStart = (e) => {
            e.item.style.backgroundColor = '#ffffff22'
          }
          const onEnd = () => {}
          </script>
          
          <style>
          .drag-item {
            width: 240px;
            margin-bottom: 15px;
            cursor: grab;
            &:last-of-type {
              margin-bottom: 0;
            }
          }
          </style>
          


          結語

          通過本文的介紹,相信大家已經對VueDraggablePlus有了初步的了解。作為前端工程師,掌握這樣一款功能強大、靈活易用的前端組件,將會為您的項目開發帶來很大的便利??靵韲L試一下吧,讓拖拽功能變得更加簡單愉快!

          以上就是本次的技術分享,希望對大家有所幫助,謝謝大家的閱讀!


          作者:墩墩大魔王丶
          鏈接:https://juejin.cn/post/7342718848817561612


          主站蜘蛛池模板: 国产成人精品一区在线| 精品乱码一区二区三区四区| 久久se精品动漫一区二区三区| 亚洲熟女综合一区二区三区| 末成年女AV片一区二区| 中文字幕一区二区三区精华液| 午夜性色一区二区三区不卡视频 | 99精品国产一区二区三区2021| 国产成人片视频一区二区| 欧美成人aaa片一区国产精品| 国产精品一区二区毛卡片| 亚洲一区二区三区乱码在线欧洲| 中文字幕一区日韩在线视频| 日韩精品中文字幕无码一区| 夜夜添无码一区二区三区| 中文字幕日本一区| 一区二区三区在线看| 成人区人妻精品一区二区不卡网站| 亚洲AV网一区二区三区| 国产成人一区二区动漫精品| 日韩久久精品一区二区三区| 色综合视频一区二区三区| 变态拳头交视频一区二区| 日本免费一区二区三区 | 日本中文字幕在线视频一区| 国产成人片视频一区二区| 日韩一本之道一区中文字幕| 精品亚洲AV无码一区二区三区| 亚洲国产系列一区二区三区| 日韩经典精品无码一区| 中文字幕一区二区在线播放| 精品无码人妻一区二区三区| 人妖在线精品一区二区三区| 无码精品久久一区二区三区| 久久一区二区明星换脸| 一区二区三区日本视频| 亚洲国产AV无码一区二区三区| 亚洲国产精品一区二区第四页| 亚洲天堂一区二区三区| 成人区人妻精品一区二区不卡视频 | 日本精品3d动漫一区二区|