中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

javascript中怎么封裝一個拖拽類

發布時間:2021-06-17 15:56:55 來源:億速云 閱讀:95 作者:Leah 欄目:web開發

這篇文章將為大家詳細講解有關javascript中怎么封裝一個拖拽類,文章內容質量較高,因此小編分享給大家做個參考,希望大家閱讀完這篇文章后對相關知識有一定的了解。

引入js和對應的css

import Drag from '../../static/dragger.js'
import './assets/css/dragger.css'

之后,實例化

new Drag({
  id: 'box-dragger',
  showAngle: true,
  isScale: false,
  showBorder: false
})
new Drag({
  id: 'box-dragger2',
  canZoom: false,
  canRotate: false
})
new Drag({
  id: 'img-box',
  showAngle: true,
  showPosition: true
  })
new Drag({
  id: 'test'
})

具體實現(封裝細節)

功能細節整理:

  1. 旋轉

  2. 縮放

  3. 平移

技術難點:

  1. 旋轉時要注意盒子每一個點的位置發生了變化

  2. 針對拖拽后的盒子的left和top都有變化,計算其left和top時需將其按照中心軸旋轉擺正,再進行計算

  3. 當且僅有一個盒子是被選中的盒子,點擊哪個選中哪個。(當前頁面多個實例化Drag對象時,如何保證操作互不影響)

  4. 實現的兩種不同方式:

可以選中某元素,直接給該元素內部加上操作的點
有一個pannel,選中某元素時,將這個pannel定位到該元素的位置上

這兩種方式都實現過一次,第一種比較簡單,但是第一種,不好控制選中某個元素才讓操作點展示。

如何封裝:

考慮如何讓用戶快速上手使用,可參考的點:

  1. 用戶需要傳入什么必須的參數

  2. 暴露給用戶什么可設置的參數和方法

實現過程:

可配置參數

字段說明是否必填默認值
id目標元素id
container父容器idbody
canRotate是否可以旋轉true
canZoom是否可以縮放true
canPull是否可以拉升true
canMove是否可以平移true
showAngle展示角度false
showPosition展示位置false
isScale是否等比例縮放true
showBorder是否展示pannel的borderfalse

屬性

  1. canRotate

  2. canZoom

  3. canPull

  4. canMove

  5. showAngle

  6. isScale

  7. id

  8. container

  9. targetObj

  10. pannelDom 操作divdom

  11. ...

具體看圖:

javascript中怎么封裝一個拖拽類

代碼解說

初始化參數

初始化目標dom對象的位置:記錄其:

  1. left平距左

  2. top

  3. width

  4. height

  5. angle

  6. rightBottomPoint 目標dom對象右下坐標

  7. rightTopPoint 目標dom對象右上坐標

  8. leftTopPoint 目標dom對象左上坐標

  9. leftBottomPoint 目標dom對象左下坐標

  10. leftMiddlePoint 目標dom對象左中坐標

  11. rightMiddlePoint 目標dom對象右中坐標

  12. topMiddlePoint 目標dom對象上中坐標

  13. bottomMiddlePoint 目標dom對象下中坐標

  14. centerPos 目標dom對象中心點坐標

初始化pannel結構

當前的父容器中只有一個pannel結構,每次實例化對象時,會判斷一下如果當前這個父容器里已經存在id為pannel的結構,就將其子節點清空,按照當前實例化對象傳進來的屬性重新渲染pannel子結構。如果沒有id為pannel的結構,就創建。

初始化事件

  1. 給pannelDom和targetObj綁定mousedown事件

  2. 給document綁定mousemove和mouseup事件

initEvent () {
  document.addEventListener('mousemove', e => {
    e.preventDefault && e.preventDefault()
    this.moveChange(e, this.targetObj)
  })
  document.addEventListener('mouseup', e => {
    this.moveLeave(this.targetObj)
  })
  if (this.canMove) {
    // 外層給this.pannelDom添加mousedown事件,是在所有實例化結束后,panneldom被展示在最后一個實例化對象上,鼠標按下它時,觸發moveInit事件
    this.pannelDom.onmousedown = e => {
      e.stopPropagation()
      this.moveInit(9, e, this.targetObj)
    }
    this.targetObj.onmousedown = e => {
      e.stopPropagation()
      this.moveInit(9, e, this.targetObj)
      this.initPannel()
      // 在點擊其他未被選中元素時,pannel定位到該元素上,重寫pannelDom事件,因為此時的this.pannelDom已經根據新的目標元素被重寫
      this.pannelDom.onmousedown= e => {
        this.moveInit(9, e, this.targetObj)
      }
    }
  }
}

dom操作

旋轉操作

鼠標按下時,記錄當前鼠標位置距離box中心位置的y/x的反正切函數A1。 

this.mouseInit = {
  x: Math.floor(e.clientX),
  y: Math.floor(e.clientY)
}
this.preRadian = Math.atan2(this.mouseInit.y - this.centerPos.y, this.mouseInit.x - this.centerPos.x)

鼠標移動時,記錄再次計算鼠標位置距離box中心位置的y/x的反正切函數A2。

this.rotateCurrent = {
  x: Math.floor(e.clientX),
  y: Math.floor(e.clientY)
}
this.curRadian = Math.atan2(this.rotateCurrent.y - this.centerPos.y, this.rotateCurrent.x - this.centerPos.x)

求A2-A1,求出移動的弧度

this.tranformRadian = this.curRadian - this.preRadian

求出最后box的旋轉角度,this.getRotate(target)是js中獲取某dom元素的旋轉角度的方法(粘貼過來的,親測好使)

this.angle = this.getRotate(target) + Math.round(this.tranformRadian * 180 / Math.PI)
this.preRadian = this.curRadian //鼠標移動的每一下都計算這個角度,所以每一下移動前的弧度值都上一次移動后的弧度值

計算旋轉后box每個點的坐標,根據余弦公式,傳入:旋轉前每點坐標,旋轉中心坐標和旋轉角度

let disAngle = this.angle - this.initAngle
this.rightBottomPoint = this.getRotatedPoint(this.initRightBottomPoint, this.centerPos, disAngle)
this.rightTopPoint = this.getRotatedPoint(this.initRightTopPoint, this.centerPos, disAngle)
this.leftTopPoint = this.getRotatedPoint(this.initLeftTopPoint, this.centerPos, disAngle)
this.leftBottomPoint = this.getRotatedPoint(this.initLeftBottomPoint, this.centerPos, disAngle)
this.leftMiddlePoint = this.getRotatedPoint(this.initLeftMiddlePoint, this.centerPos, disAngle)
this.rightMiddlePoint = this.getRotatedPoint(this.initRightMiddlePoint, this.centerPos, disAngle)
this.topMiddlePoint = this.getRotatedPoint(this.initTopMiddlePoint, this.centerPos, disAngle)
this.bottomMiddlePoint = this.getRotatedPoint(this.initBottomMiddlePoint, this.centerPos, disAngle)

沿著一個方向拉升操作。

沿著一個角縮放操作。 這兩個操作,主要參考了一個大佬的拖拽思想實現的 github wiki地址

優化,mousemove事件添加節流函數

function throttle(fn, interval) {
  let canRun = true;
  return function () {
    if (!canRun) return;
    canRun = false;
    setTimeout(() => {
      fn.apply(this, arguments);
      canRun = true;
    }, interval);
  };
}
let that = this
document.addEventListener('mousemove', throttle(function (e) {
  e.preventDefault && e.preventDefault()
  that.moveChange(e, that.targetObj)
}, 10))

關于javascript中怎么封裝一個拖拽類就分享到這里了,希望以上內容可以對大家有一定的幫助,可以學到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

尉氏县| 白山市| 龙井市| 固镇县| 青海省| 太保市| 汾阳市| 临潭县| 湖南省| 华容县| 枣强县| 东山县| 忻城县| 乌鲁木齐县| 榆林市| 普兰店市| 通河县| 湘乡市| 金堂县| 泸西县| 曲水县| 洛隆县| 河池市| 于都县| 大同县| 鄂温| 江陵县| 清水河县| 安顺市| 新民市| 湾仔区| 句容市| 岑溪市| 吉安县| 兴安县| 安泽县| 竹山县| 辰溪县| 易门县| 漾濞| 秦安县|