欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

純 JS 實現(xiàn)放大縮小拖拽功能(完整代碼)

 更新時間:2019年11月25日 10:30:40   作者:ZooTeam  
這篇文章主要介紹了純js實現(xiàn)放大縮小拖拽功能,文中給大家提到了在開發(fā)過程中遇到的一些問題及解決方法,需要的朋友可以參考下

前言

最近團隊需要做一個智能客服懸浮窗功能,需要支持拖動、放大縮小等功能,因為這個是全局插件,為了兼容性考慮全部使用原生 JS 實現(xiàn),不引用任何第三方庫或者插件。開發(fā)過程中遇到的一些問題及解決方法,在這里和大家分享交流一下。

注:下文出現(xiàn)的“采寶”二字,為這個功能的產(chǎn)品名。

先看效果

 

看這個效果,相信大部分開發(fā)都會覺得實現(xiàn)起來比較容易。在實際開發(fā)中,筆者總結(jié)了三個主要的坑點,及其解決方案。

三個坑點

  • 拖拽采寶時會導(dǎo)致采寶放大縮小
  • 采寶顯示在屏幕邊界時被遮擋顯示不全
  • 采寶放大和縮小后,位置發(fā)生變化

(一)拖拽時會導(dǎo)致采寶放大縮小

我們在操作采寶時,不管是鼠標拖動還是點擊放大縮小,我們的事件都需要綁定在采寶頭部的圖標上,這樣我們就需要在圖標上同時綁定點擊和拖拽事件。但是當我們直接添加 click 事件和 mousedown 事件的時候,我們發(fā)現(xiàn)在觸發(fā) mousedown 事件的時候,也會去觸發(fā) click 事件。這樣就會出現(xiàn)在拖動采寶的時候,采寶會放大和縮小。

 

這個效果是我們不想看到的,所以我們就需要區(qū)分開采寶上的 click 事件和 mousedown 事件,想辦法使兩個事件的觸發(fā)相互不影響。

所以我們在同一個 DIV 上同時綁定 mousedown 事件和 click 事件,然后通過控制臺輸出每個事件,查看過程中的每個事件的觸發(fā)順序。

const moveBox = document.querySelector('.move');
moveBox.onmousedown = function (evt) {
 console.log('觸發(fā)鼠標按下')
 moveBox.onmousemove = function (evt) {
 console.log('觸發(fā)鼠標拖動')
 }
}
function moveBoxClick(e) {
 console.log('觸發(fā)click')
}
moveBox.onmouseup = function () {
 console.log('觸發(fā)鼠標抬起')
}

然后我們得到的結(jié)果是:

 

通過控制臺的輸出情況,我們就可以看到鼠標點擊后的各個事件觸發(fā)情況:首先執(zhí)行的是 mousedown 事件,然后是 mousemove 事件,再然后是 mouseup 事件,最后是 click 事件。

知道了事件的觸發(fā)順序,我們就可以通過設(shè)置一個變量 isMove 來區(qū)分開鼠標的拖動事件和點擊事件,每次鼠標按下的時候我們將 isMove 復(fù)原,鼠標移動的時候?qū)?isMove 的狀態(tài)改變。

因為每次觸發(fā) click 事件的時候也都會去先去觸發(fā) mousedown 事件,所以我們在 click 事件里增加一個判斷,鼠標移動時,不觸發(fā) click 事件。這樣就可以把 click 事件和 mousedown 事件區(qū)分開來,實現(xiàn) mousedown 和 click 事件的隔離。

click 事件增加判斷

function moveBoxClick(e) {
 // 點擊采寶
 const target = document.querySelector(".move");
 const smallImg = document.querySelector(".small-img");
 const magnifyImg = document.querySelector(".magnify-img");
 // 點擊move盒子
 if (!isMove) {
 if (isBig) {
  smallImg.style.display = "block";
  magnifyImg.style.display = "none";
  target.style.width = "32px";
 } else {
  smallImg.style.display = "none";
  magnifyImg.style.display = "block";
  target.style.width = "130px";
 }
 isBig = !isBig;
 }
}
mousedown 事件重置 isMove 和 mousemove 改變 isMove
let isMove = false; // 是否是拖動
let isBig = false; // 是否是變大的盒子
let isMove = false; // 判斷是否移動采寶
smallImg.onmousedown = magnifyImg.onmousedown = function(evt) {
 isMove = false; // 每次鼠標按下時,重置isMove
 document.onmousemove = function(e) {
 isMove = true; // 每次鼠標移動時,改變isMove
 };
};

通過 isMove 的狀態(tài),我們就可以區(qū)分開 mousemove 事件和 click 事件,使得我們在拖動采寶的時候,可以不去觸發(fā)采寶放大縮小。

(二)采寶顯示在屏幕邊界時被遮擋顯示不全

我們在拖動采寶時,判斷采寶拖動的當前定位坐標是否超出了當前顯示屏的高度和寬度,我們需要限制采寶拖動的最大距離。小采寶在點擊放大時,也需要做一下處理,把采寶全部顯示出來。

拖動時

const moveBox = document.querySelector(".move");
const smallImg = document.querySelector(".move .small-img");
const magnifyImg = document.querySelector(".move .magnify-img");
let isMove = false; // 是否是拖動
let isBig = false; // 是否是變大的盒子

smallImg.onmousedown = magnifyImg.onmousedown = function(evt) {
 // 拖動div盒子
 const clientX = evt.clientX;
 const clientY = evt.clientY;
 const pageX = moveBox.offsetLeft;
 const pageY = moveBox.offsetTop;
 const x = clientX - pageX;
 const y = clientY - pageY;

 document.onmousemove = function(e) {
 // 拖動后采寶的坐標
 let _x = e.clientX - x;
 let _y = e.clientY - y;
 const boxWidth = moveBox.offsetWidth;
 const boxHeight = moveBox.offsetHeight;
 if (_x < 0) {
  _x = 0;
 }
 // X坐標的最大值
 if (_x > window.screen.width - boxWidth) {
  _x = window.screen.width - boxWidth;
 }
 if (_y < 0) {
  _y = 0;
 }
 // Y坐標的最大值
 if (_y > document.documentElement.clientHeight - boxHeight) {
  _y = document.documentElement.clientHeight - boxHeight;
 }
 };
};
小采寶在邊界放大時
// 點擊時,判斷采寶是否超出顯示屏
function autoPotion () {
 let x = moveBox.offsetLeft;
 let y = moveBox.offsetTop;

 if (x < 0) {
  x = 0;
 } else if (x > document.documentElement.clientWidth - moveBox.offsetWidth) {
  x = document.documentElement.clientWidth - moveBox.offsetWidth;
 }

 if (y < 0) {
  y = 0;
 } else if (y > document.documentElement.clientHeight - moveBox.offsetHeight) {
  y = document.documentElement.clientHeight - moveBox.offsetHeight;
 }

 moveBox.style.left = x + "px";
 moveBox.style.top = y + "px";
}

效果如下

 

(三)采寶放大和縮小后,位置發(fā)生變化

通過上圖,我們可以看到,當小采寶處在顯示屏邊界時,點擊放大后再點擊縮小,我們發(fā)現(xiàn)采寶的位置發(fā)生了變化。這個是因為采寶是根據(jù)左上角的坐標來定位的,當小采寶移動到右下角時,點擊放大以后,采寶左上角的坐標發(fā)生了變化,這樣就使得采寶在放大縮小時,位置在發(fā)生變化。所以,我們在采寶移動完成時需要記錄采寶左上角的坐標,在點擊時,需要將采寶上次移動完成的坐標重新賦值給采寶,這樣就使得采寶在放大縮小時,位置不會發(fā)生變化。

 

這樣,我們把每次 mouseup 事件的時候記錄下采寶的位置,這樣我們解決了采寶放大縮小時位置發(fā)生變化的問題。

完整的代碼

HTML:

<div class="box">
 <div class="move">
 <img
  onclick="moveBoxClick()"
  class="small-img"
  draggable="false"
  src="https://zcy-cdn.oss-cn-shanghai.aliyuncs.com/f2e-assets/103bbf76-6248-421c-a3d6-28a525c459db.png"
  alt=""
 />
 <img
  onclick="moveBoxClick()"
  class="magnify-img"
  draggable="false"
  src="https://zcy-cdn.oss-cn-shanghai.aliyuncs.com/f2e-assets/90e26f49-9824-4443-b4aa-8aa64a3c8690.png"
  alt=""
 />
 <div class="content"></div>
 </div>
</div>
JavaScript
const moveBox = document.querySelector(".move");
const smallImg = document.querySelector(".move .small-img");
const magnifyImg = document.querySelector(".move .magnify-img");
var initX = 0; // 記錄小采寶的x坐標
var initY = 0; // 記錄小采寶的y坐標
let isMove = false; // 是否是拖動
let isBig = false; // 是否是變大的盒子

smallImg.onmousedown = magnifyImg.onmousedown = function(evt) {
  // 拖動div盒子
 const clientX = evt.clientX;
 const clientY = evt.clientY;
 const pageX = moveBox.offsetLeft;
 const pageY = moveBox.offsetTop;
 const x = clientX - pageX;
 const y = clientY - pageY;

 isMove = false;

 document.onmousemove = function(e) {
 const boxWidth = moveBox.offsetWidth;
 const boxHeight = moveBox.offsetHeight;
 let _x = e.clientX - x;
 let _y = e.clientY - y;
 if (_x < 0) {
  _x = 0;
 }
 if (_x > window.screen.width - boxWidth) {
  _x = window.screen.width - boxWidth;
 }
 if (_y < 0) {
  _y = 0;
 }
 if (_y > document.documentElement.clientHeight - boxHeight) {
  _y = document.documentElement.clientHeight - boxHeight;
 }

 if (isBig) {
  initX = _x;
  initY = _y;
 }

 moveBox.style.left = _x + "px";
 moveBox.style.top = _y + "px";

 isMove = true;
 };
};


document.onmouseup = function() {
 if (isMove) {
 initX = moveBox.offsetLeft;
 initY = moveBox.offsetTop;
 }
 document.onmousemove = null;
};

function moveBoxClick(e) {
 const target = document.querySelector(".move");
 const smallImg = document.querySelector(".small-img");
 const magnifyImg = document.querySelector(".magnify-img");
 // 點擊move盒子
 if (!isMove) {
 if (isBig) {
  smallImg.style.display = "block";
  magnifyImg.style.display = "none";
  target.style.width = "32px";
  target.style.left = initX + 'px';
  target.style.top = initY + 'px';
 } else {
  smallImg.style.display = "none";
  magnifyImg.style.display = "block";
  target.style.width = "130px";
 }
 isBig = !isBig;

 setTimeout(() => {
  autoPotion();
 }, 100)
 }
}

// 點擊時,判斷采寶是否超出顯示屏
function autoPotion () {
 let x = moveBox.offsetLeft;
 let y = moveBox.offsetTop;

 if (x < 0) {
 x = 0;
 } else if (x > document.documentElement.clientWidth - moveBox.offsetWidth) {
 x = document.documentElement.clientWidth - moveBox.offsetWidth;
 }

 if (y < 0) {
 y = 0;
 } else if (y > document.documentElement.clientHeight - moveBox.offsetHeight) {
 y = document.documentElement.clientHeight - moveBox.offsetHeight;
 }

 moveBox.style.left = x + "px";
 moveBox.style.top = y + "px";
}

總結(jié)

以上所述是小編給大家介紹的純 JS 實現(xiàn)放大縮小拖拽功能,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回復(fù)大家的。在此也非常感謝大家對腳本之家網(wǎng)站的支持!
如果你覺得本文對你有幫助,歡迎轉(zhuǎn)載,煩請注明出處,謝謝!

相關(guān)文章

  • JS函數(shù)基本定義與用法示例

    JS函數(shù)基本定義與用法示例

    這篇文章主要介紹了JS函數(shù)基本定義與用法,結(jié)合實例形式分析了JavaScript函數(shù)基本定義、參數(shù)、返回值等相關(guān)使用技巧,需要的朋友可以參考下
    2020-01-01
  • 頁面圖片浮動左右滑動效果的簡單實現(xiàn)案例

    頁面圖片浮動左右滑動效果的簡單實現(xiàn)案例

    本篇文章主要是對頁面圖片浮動左右滑動效果的簡單實現(xiàn)案例進行了介紹,需要的朋友可以過來參考下,希望對大家有所幫助
    2014-02-02
  • JS實現(xiàn)上傳文件顯示進度條

    JS實現(xiàn)上傳文件顯示進度條

    這篇文章主要為大家詳細介紹了JS實現(xiàn)上傳文件顯示進度條,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-07-07
  • JS實現(xiàn)的四級密碼強度檢測功能示例

    JS實現(xiàn)的四級密碼強度檢測功能示例

    這篇文章主要介紹了JS實現(xiàn)的四級密碼強度檢測功能,具有實時檢測輸入密碼強度的功能,涉及javascript針對字符串的正則判定相關(guān)操作技巧,需要的朋友可以參考下
    2017-05-05
  • 微信小程序日歷插件代碼實例

    微信小程序日歷插件代碼實例

    這篇文章主要介紹了微信小程序日歷插件代碼實例,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2019-12-12
  • JavaScript中的細節(jié)分析

    JavaScript中的細節(jié)分析

    高山登不上,不是因為體力不支,只因鞋里一粒。學習也是如此,因而有必要把JavaScript中常見的和與其它語言不同的那些細節(jié)學習一下
    2012-06-06
  • JavaScript Event學習第十一章 按鍵的檢測

    JavaScript Event學習第十一章 按鍵的檢測

    檢測用戶的按鍵是事件處理程序的一個很特別的環(huán)節(jié)。這一章我們著力解決一些非常棘手的問題,并且制定一個完備的表格。
    2010-02-02
  • 關(guān)于Javascript模塊化和命名空間管理的問題說明

    關(guān)于Javascript模塊化和命名空間管理的問題說明

    最近閑下來的時候,稍微想了想這個問題。關(guān)于Javascript模塊化和命名空間管理
    2010-12-12
  • 在IE8上JS實現(xiàn)combobox支持拼音檢索功能

    在IE8上JS實現(xiàn)combobox支持拼音檢索功能

    這篇文章主要介紹了在IE8上JS實現(xiàn)combobox支持拼音檢索功能的相關(guān)資料,本文介紹的非常詳細,具有參考借鑒價值,需要的朋友可以參考下
    2016-05-05
  • 深入理解JavaScript系列(16) 閉包(Closures)

    深入理解JavaScript系列(16) 閉包(Closures)

    本章我們將介紹在JavaScript里大家經(jīng)常來討論的話題 —— 閉包(closure)。閉包其實大家都已經(jīng)談爛了。盡管如此,這里還是要試著從理論角度來討論下閉包,看看ECMAScript中的閉包內(nèi)部究竟是如何工作的
    2012-04-04

最新評論