這篇文章將為大家詳細(xì)講解有關(guān)javascript中怎么封裝一個(gè)拖拽類,文章內(nèi)容質(zhì)量較高,因此小編分享給大家做個(gè)參考,希望大家閱讀完這篇文章后對(duì)相關(guān)知識(shí)有一定的了解。
為定興等地區(qū)用戶提供了全套網(wǎng)頁(yè)設(shè)計(jì)制作服務(wù),及定興網(wǎng)站建設(shè)行業(yè)解決方案。主營(yíng)業(yè)務(wù)為成都網(wǎng)站制作、網(wǎng)站設(shè)計(jì)、定興網(wǎng)站設(shè)計(jì),以傳統(tǒng)方式定制建設(shè)網(wǎng)站,并提供域名空間備案等一條龍服務(wù),秉承以專業(yè)、用心的態(tài)度為用戶提供真誠(chéng)的服務(wù)。我們深信只要達(dá)到每一位用戶的要求,就會(huì)得到認(rèn)可,從而選擇與我們長(zhǎng)期合作。這樣,我們也可以走得更遠(yuǎn)!引入js和對(duì)應(yīng)的css
import Drag from '../../static/dragger.js' import './assets/css/dragger.css'
之后,實(shí)例化
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' })
具體實(shí)現(xiàn)(封裝細(xì)節(jié))
功能細(xì)節(jié)整理:
旋轉(zhuǎn)
縮放
平移
技術(shù)難點(diǎn):
旋轉(zhuǎn)時(shí)要注意盒子每一個(gè)點(diǎn)的位置發(fā)生了變化
針對(duì)拖拽后的盒子的left和top都有變化,計(jì)算其left和top時(shí)需將其按照中心軸旋轉(zhuǎn)擺正,再進(jìn)行計(jì)算
當(dāng)且僅有一個(gè)盒子是被選中的盒子,點(diǎn)擊哪個(gè)選中哪個(gè)。(當(dāng)前頁(yè)面多個(gè)實(shí)例化Drag對(duì)象時(shí),如何保證操作互不影響)
實(shí)現(xiàn)的兩種不同方式:
可以選中某元素,直接給該元素內(nèi)部加上操作的點(diǎn)
有一個(gè)pannel,選中某元素時(shí),將這個(gè)pannel定位到該元素的位置上
這兩種方式都實(shí)現(xiàn)過(guò)一次,第一種比較簡(jiǎn)單,但是第一種,不好控制選中某個(gè)元素才讓操作點(diǎn)展示。
如何封裝:
考慮如何讓用戶快速上手使用,可參考的點(diǎn):
用戶需要傳入什么必須的參數(shù)
暴露給用戶什么可設(shè)置的參數(shù)和方法
實(shí)現(xiàn)過(guò)程:
可配置參數(shù)
字段 | 說(shuō)明 | 是否必填 | 默認(rèn)值 |
---|---|---|---|
id | 目標(biāo)元素id | 是 | 無(wú) |
container | 父容器id | 否 | body |
canRotate | 是否可以旋轉(zhuǎn) | 否 | true |
canZoom | 是否可以縮放 | 否 | true |
canPull | 是否可以拉升 | 否 | true |
canMove | 是否可以平移 | 否 | true |
showAngle | 展示角度 | 否 | false |
showPosition | 展示位置 | 否 | false |
isScale | 是否等比例縮放 | 否 | true |
showBorder | 是否展示pannel的border | 否 | false |
屬性
canRotate
canZoom
canPull
canMove
showAngle
isScale
id
container
targetObj
pannelDom 操作divdom
...
具體看圖:
代碼解說(shuō)
初始化參數(shù)
初始化目標(biāo)dom對(duì)象的位置:記錄其:
left平距左
top
width
height
angle
rightBottomPoint 目標(biāo)dom對(duì)象右下坐標(biāo)
rightTopPoint 目標(biāo)dom對(duì)象右上坐標(biāo)
leftTopPoint 目標(biāo)dom對(duì)象左上坐標(biāo)
leftBottomPoint 目標(biāo)dom對(duì)象左下坐標(biāo)
leftMiddlePoint 目標(biāo)dom對(duì)象左中坐標(biāo)
rightMiddlePoint 目標(biāo)dom對(duì)象右中坐標(biāo)
topMiddlePoint 目標(biāo)dom對(duì)象上中坐標(biāo)
bottomMiddlePoint 目標(biāo)dom對(duì)象下中坐標(biāo)
centerPos 目標(biāo)dom對(duì)象中心點(diǎn)坐標(biāo)
初始化pannel結(jié)構(gòu)
當(dāng)前的父容器中只有一個(gè)pannel結(jié)構(gòu),每次實(shí)例化對(duì)象時(shí),會(huì)判斷一下如果當(dāng)前這個(gè)父容器里已經(jīng)存在id為pannel的結(jié)構(gòu),就將其子節(jié)點(diǎn)清空,按照當(dāng)前實(shí)例化對(duì)象傳進(jìn)來(lái)的屬性重新渲染pannel子結(jié)構(gòu)。如果沒(méi)有id為pannel的結(jié)構(gòu),就創(chuàng)建。
初始化事件
給pannelDom和targetObj綁定mousedown事件
給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事件,是在所有實(shí)例化結(jié)束后,panneldom被展示在最后一個(gè)實(shí)例化對(duì)象上,鼠標(biāo)按下它時(shí),觸發(fā)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() // 在點(diǎn)擊其他未被選中元素時(shí),pannel定位到該元素上,重寫pannelDom事件,因?yàn)榇藭r(shí)的this.pannelDom已經(jīng)根據(jù)新的目標(biāo)元素被重寫 this.pannelDom.onmousedown= e => { this.moveInit(9, e, this.targetObj) } } } }
dom操作
旋轉(zhuǎn)操作
鼠標(biāo)按下時(shí),記錄當(dāng)前鼠標(biāo)位置距離box中心位置的y/x的反正切函數(shù)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)
鼠標(biāo)移動(dòng)時(shí),記錄再次計(jì)算鼠標(biāo)位置距離box中心位置的y/x的反正切函數(shù)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,求出移動(dòng)的弧度
this.tranformRadian = this.curRadian - this.preRadian
求出最后box的旋轉(zhuǎn)角度,this.getRotate(target)是js中獲取某dom元素的旋轉(zhuǎn)角度的方法(粘貼過(guò)來(lái)的,親測(cè)好使)
this.angle = this.getRotate(target) + Math.round(this.tranformRadian * 180 / Math.PI) this.preRadian = this.curRadian //鼠標(biāo)移動(dòng)的每一下都計(jì)算這個(gè)角度,所以每一下移動(dòng)前的弧度值都上一次移動(dòng)后的弧度值
計(jì)算旋轉(zhuǎn)后box每個(gè)點(diǎn)的坐標(biāo),根據(jù)余弦公式,傳入:旋轉(zhuǎn)前每點(diǎn)坐標(biāo),旋轉(zhuǎn)中心坐標(biāo)和旋轉(zhuǎn)角度
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)
沿著一個(gè)方向拉升操作。
沿著一個(gè)角縮放操作。 這兩個(gè)操作,主要參考了一個(gè)大佬的拖拽思想實(shí)現(xiàn)的 github wiki地址
優(yōu)化,mousemove事件添加節(jié)流函數(shù)
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))
關(guān)于javascript中怎么封裝一個(gè)拖拽類就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,可以學(xué)到更多知識(shí)。如果覺得文章不錯(cuò),可以把它分享出去讓更多的人看到。
另外有需要云服務(wù)器可以了解下創(chuàng)新互聯(lián)scvps.cn,海內(nèi)外云服務(wù)器15元起步,三天無(wú)理由+7*72小時(shí)售后在線,公司持有idc許可證,提供“云服務(wù)器、裸金屬服務(wù)器、高防服務(wù)器、香港服務(wù)器、美國(guó)服務(wù)器、虛擬主機(jī)、免備案服務(wù)器”等云主機(jī)租用服務(wù)以及企業(yè)上云的綜合解決方案,具有“安全穩(wěn)定、簡(jiǎn)單易用、服務(wù)可用性高、性價(jià)比高”等特點(diǎn)與優(yōu)勢(shì),專為企業(yè)上云打造定制,能夠滿足用戶豐富、多元化的應(yīng)用場(chǎng)景需求。