使用JavaScript實現(xiàn)一個拖拽縮放效果
前言
在寫一個簡單的H5頁面時,需要實現(xiàn)如下的一個拖拽效果,找了半天未能找到符合要求的,含淚手寫
先來看一下我們要是實現(xiàn)一個怎樣的效果

基本思路
- 鼠標摁下,記錄元素的初始位置以及寬高
- 監(jiān)聽鼠標的移動,根據(jù)鼠標的移動不斷改變自己的位置/寬高
- 是否存在邊界限制
拖拽實現(xiàn)
我們常見的改變元素位置的方式有
- 定位
- 使用translate進行偏移
那我們現(xiàn)在用那種方式那實現(xiàn)拖拽呢?
從功能實現(xiàn)上來看,這兩個方式都能很好的實現(xiàn)我們的需求
從性能上來看,translate天生就是用來制作動畫效果的,所以translate的性能以及流暢度都是要優(yōu)于定位的。
開始操作??!
<style>
.box{
margin: 50px;
width: 500px;
height: 300px;
border: 1px solid black;
position: relative;
}
.drag{
height: 100px;
width: 100px;
background-color: #cbd;
}
</style>
<div class="box">
<div class="drag"></div>
</div>
<script>
let dragEl = document.querySelector(".drag")
let container = document.querySelector(".box")
let width, height, maxWidth, maxHeight, tx, ty, startX, startY
// 初始化
function init() {
// 為目標元素設(shè)置初始的偏移,避免在第一次獲取偏移時為空的問題
dragEl.style.transform = "translate(0px,0px)"
// 獲取父元素寬高
maxWidth = container.clientWidth
maxHeight = container.clientHeight
}
function getInfo(e) {
// 獲取元素當(dāng)前的寬高
width = dragEl.clientWidth
height = dragEl.clientHeight
// 獲取元素當(dāng)前的偏移量
let translateStr = dragEl.style.transform
const reg = /\d+/g
let translateArr = translateStr.match(reg)
tx = Number(translateArr[0])
ty = Number(translateArr[1])
// 記錄鼠標的起始位置
startX = e.clientX
startY = e.clientY
}
function drag() {
dragEl.addEventListener("mousedown", (e) => {
getInfo(e)
document.onmousemove = (e) => {
let distanceX = tx + e.clientX - startX
let distanceY = ty + e.clientY - startY
dragEl.style.transform = `translate(${distanceX}px, ${distanceY}px)`
}
document.onmouseup = () => {
document.onmousemove = null
}
})
}
init()
drag()
</script>通過上述代碼,我們已經(jīng)完成了元素的拖動,接下來需要考慮的就是,如果有邊界限制,我們又該如何實現(xiàn)
從上訴例子中,我們可以觀察出,元素偏移的最小值為0,最大值為父元素的寬高 - 目標元素的寬高
所以在有邊界限制的情形下偏移量的計算方式為
let distanceX = Math.max(0, Math.min(tx + e.clientX - startX, maxWidth - width)) let distanceY = Math.max(0, Math.min(ty + e.clientY - startY, maxHeight - height))
縮放實現(xiàn)
這里我們以向左縮放為例
- 首先我們需要為目標元素添加一個邊框,用來進行縮放的操作
<style>
.box{
margin: 50px;
width: 500px;
height: 300px;
border: 1px solid black;
position: relative;
}
.drag{
height: 100px;
width: 100px;
background-color: #cbd;
}
.left{
width: 10px;
height: calc(100% - 14px);
margin: 7px 0px;
position: absolute;
background-color: #000;
cursor: col-resize;
top: 0;
left: -5px;
}
</style>
<script>
function addLeft() {
left = document.createElement("div")
left.className = "left"
dragEl.append(left)
}
init()
drag()
addLeft()
</script>2.為左側(cè)的邊框添加縮放功能,因為是左側(cè)的縮放,所以在寬度變化的同時,需要不斷調(diào)整元素的位置,令其符合視覺效果
function leftZoom() {
left.addEventListener("mousedown", (e) => {
e.stopPropagation()
getInfo(e)
document.onmousemove = (e) => {
// 注意這里是?
newWidth = width - (e.clientX - startX)
let distanceX = tx + (e.clientX - startX)
dragEl.style.width = `${newWidth}px`
dragEl.style.transform = `translate(${distanceX}px, ${ty}px)`
}
document.onmouseup = () => {
document.onmousemove = null
}
})
}
init()
drag()
addLeft()
leftZoom()- 限制元素縮放的最小值
let minWidth = 30 newWidth = Math.max(minWidth, width - (e.clientX - startX))
- 現(xiàn)在我們已經(jīng)完成了縮放,但是當(dāng)元素向右縮小到最小值時,元素會向右移動,顯然這是不符合邏輯的,所以我們需要對偏移進行限制
// 最大偏移為已經(jīng)偏移的距離 + 目標元素的寬度 - 最小寬度 let distanceX = Math.min(tx + width - minWidth, tx + (e.clientX - startX))
4.如果縮放的尺寸需要限制在父元素內(nèi),我們需要繼續(xù)完善代碼
// 最大寬度為元素當(dāng)前偏移量 + 最初的寬度,最小寬度為minWidth newWidth = Math.min(tx + width, Math.max(minWidth, width - (e.clientX - startX))) // 最大偏移為已經(jīng)偏移的距離 + 目標元素的寬度 - 最小寬度,最小偏移為0 let distanceX = Math.max(0,Math.min(tx + width - minWidth, tx + (e.clientX - startX)))
其他是三邊以及四個角的實現(xiàn)方式基本相同,就不在這里一一贅述了
最后
雖然我們完成了元素的拖拽與縮放,但是我們在使用時,還是存在許多的限制,比如
- 目標元素不能被定位,如果使用定位對元素進行了偏移,我們所做的限制就會不生效
- 同理目標元素也不能存在邊距
雖然存在限制,但是我們可以根據(jù)自己的實際需求進行調(diào)整
到此這篇關(guān)于如何使用JS實現(xiàn)一個這樣的拖拽縮放效果的文章就介紹到這了,更多相關(guān)js拖拽縮放內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
js實現(xiàn)完全自定義可帶多級目錄的網(wǎng)頁鼠標右鍵菜單方法
這篇文章主要介紹了js實現(xiàn)完全自定義可帶多級目錄的網(wǎng)頁鼠標右鍵菜單方法,實例分析了javascript實現(xiàn)自定義網(wǎng)頁鼠標右鍵彈出菜單的技巧,非常具有實用價值,需要的朋友可以參考下2015-02-02
js仿土豆網(wǎng)帶縮略圖的焦點圖片切換效果實現(xiàn)方法
這篇文章主要介紹了js仿土豆網(wǎng)帶縮略圖的焦點圖片切換效果實現(xiàn)方法,涉及javascript操作圖片特效的技巧,具有一定參考借鑒價值,需要的朋友可以參考下2015-02-02
javascript實現(xiàn)圖像循環(huán)明暗變化的方法
這篇文章主要介紹了javascript實現(xiàn)圖像循環(huán)明暗變化的方法,實例分析了javascript操作css樣式的技巧,具有一定參考借鑒價值,需要的朋友可以參考下2015-02-02
javascript getElementsByClassName函數(shù)
今天在腳本中應(yīng)用到了根據(jù)類名取元素的方法,卻對其效率不甚滿意。于是,小幅修改了其探測元素類名的方法,提升了約3成的效率.2010-04-04
js 連接數(shù)據(jù)庫如何操作數(shù)據(jù)庫中的數(shù)據(jù)
JS中怎么連接數(shù)據(jù)庫,和提取數(shù)據(jù)庫中的數(shù)據(jù),本文將以此問題詳細介紹,需要的朋友可以了解下2012-11-11

