目錄
只用style完成的程式碼
重點! ! JS
transform和style的結合
瀏覽器的相容寫法
PS:記住createElement()這個方法,下次判斷瀏覽器相容時用得著!
PS:之所以要判斷transformValue是否為none,是因為在初始化狀態是,元素未被設定transform屬性,這樣正規之後的陣列是找不到[4][5] 的,所以我們讓val的兩個屬性為0,也就是稍後會成為的transform的translateX和translateY的值。
注意上面一段程式碼我們修改的的內容,在這裡我們增加了一個判斷:也就是當支援transform屬性的瀏覽器存在時,我們會用transform屬性修改元素的值,把之前在getTranslate中得到的x、y賦值給pos的x、y。
首頁 web前端 js教程 封裝一個自己的模組實例詳解

封裝一個自己的模組實例詳解

Jan 30, 2018 pm 05:16 PM
實例 模組 自己的

試著封裝了一個拖曳模組。過程中經歷了一些曲折,我打算只用style.left的方式,但這個需要設定position:absolute。可能對程式碼造成一定影響。雖然CSS的transform會影響相容,但這裡我還是使用了這個屬性的translate來完成移動。

只用style完成的程式碼

話不多說,直接上程式碼:

#html和css,這裡必須設定position,第一次寫這段程式碼的時候忘了,結果儘管JS寫對了,效果完全出不來....真是短路了

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>学习</title>
    <style>
        *{
            margin: 0;
            padding: 0;
        }
        #box{
            width: 200px;
            height: 200px;
            background: #6f6;
            font-size: 20px;
            cursor:move;
            position: absolute;
        }
    </style>

</head>
<body>
  <p id="box"></p>
  <script src="js/drag_module.js"></script>
</body>
</html>
登入後複製

重點! ! JS

;    //这个分号是为了防止其他的模块最后忘记加分号,导致错误。
(function() {
  
  //构造函数,属于每一个实例
  function Drag(selector) {
    this.elem = typeof selector == 'object' ? selector : document.getElementById(selector);
    //鼠标初始位置
    this.startX = 0;
    this.startY = 0;
    //元素初始位置
    this.sourceX = 0;
    this.sourceY = 0;

    this.init();
  }

  //原型,共有的
  Drag.prototype = {
    constructor: Drag,
    init: function() {
      this.setDrag();
    },

    //用于获取元素当前的位置信息
    getPosition: function() {
      var that = this;
      var pos = {};
      pos = {
        x: that.elem.offsetLeft,
        y: that.elem.offsetTop
      };
      return pos;
    },
    //用来设置当前元素的位置
    setPosition: function(pos) {
      this.elem.style.left = pos.x + 'px';
      this.elem.style.top = pos.y + 'px';
    },

    //该方法用来绑定事件
    setDrag: function() {
      var self = this;
      this.elem.addEventListener('mousedown', start, false);

      function start(event) {

        self.startX = event.pageX;
        self.startY = event.pageY;

        var pos = self.getPosition();

        self.sourceX = pos.x;
        self.sourceY = pos.y;

        document.addEventListener('mousemove', move, false);
        document.addEventListener('mouseup', end, false);
      }

      function move(event) {
        //总体思想:鼠标距浏览器距-鼠标距元素距离
        var currentX = event.pageX; //当前的鼠标x位置
        var currentY = event.pageY; //当前的鼠标y位置

        var distanceX = currentX - self.startX; //鼠标移动的距离x
        var distanceY = currentY - self.startY; //鼠标移动的距离y

        self.setPosition({
          x: self.sourceX + distanceX,
          y: self.sourceY + distanceY
        });

      }

      function end(event) {
        document.removeEventListener('mousemove', move);
        document.removeEventListener('mouseup', end);
      }
    }
  };
  
  //暴露在外
  window.Drag = Drag;
})();


new Drag('box');
登入後複製

這段程式碼是比較好理解的,在一開始看波大神的程式碼時,對於translate的運用其實我沒看太明白,因為沒想到為啥要用到正則.. ....

雖然比較簡單,但我們還是要分析這段程式碼的原理:

1.自執行函式裡有一個建構函式Drag(),在建構子裡我們設定的方法和屬性時每一個建構函式實例獨有的,例如他們的位置資訊等。而在原型裡的有三個方法:分別是取得元素位置資訊的getPosition()、設定元素位置的setPosition()和綁定事件的setDrag(),這三個因為是公用的,為了節省資源,我們就放在原型裡了。

2.這段程式碼執行的原理是:當滑鼠按下時,取得元素初始位置資訊sourceX/Y、滑鼠初始位置資訊startX/Y;當滑鼠移動完成時,取得滑鼠新的位置currentX/Y,兩個滑鼠位置相減就能得到滑鼠移動的距離distanceX/Y,這同時也是元素移動的距離,然後,我們把這個值賦給元素的style.left/top。元素的拖曳就實現了。

transform和style的結合

由於技術的發展,越來越多的設備開始支援CSS3了,加上style的資源佔用的更多,效率方面存在問題,所以我們考慮使用transform。

瀏覽器的相容寫法

我們先在函數Drag()前面加上私有屬性:

var transform = getTransform();
登入後複製

在下面再加上私有方法:

function getTransform() {
    var transform = "",
      pStyle = document.createElement('p').style,
      transformArr = ['transform', 'webkitTransform', 'MozTransform', 'msTransform', 'oTransform'],
      i = 0,
      l = transformArr.length;

    for (; i < l; i++) {
      if (transformArr[i] in pStyle) {
        return transform = transformArr[i];
      }
    }
    return transform;
  }
登入後複製

PS:記住createElement()這個方法,下次判斷瀏覽器相容時用得著!

我們還需要在getPosition()的下面加上一個函數,用同樣的形式:

getTranslate: function() {
      var val = {};
      var transformValue = document.defaultView.getComputedStyle(this.elem, false)[transform];
      if(transformValue=='none'){
        val={x:0,y:0};
      }else{
        var transformArr = transformValue.match(/-?\d+/g);
        val = {
          x: Number(transformArr[4]),
          y: Number(transformArr[5])
        };
      }


      return val;
    },
登入後複製

PS:之所以要判斷transformValue是否為none,是因為在初始化狀態是,元素未被設定transform屬性,這樣正規之後的陣列是找不到[4][5] 的,所以我們讓val的兩個屬性為0,也就是稍後會成為的transform的translateX和translateY的值。

繼續寫程式碼。上面一段我們用來提取translate的X、Y值。看下面一段:

getPosition: function() {
      var that = this;
      var pos = {};
      if(transform){
        var val=this.getTranslate();
        pos={
          x:val.x,
          y:val.y
        };
      }else{
        pos = {
          x: that.elem.offsetLeft,
          y: that.elem.offsetTop
        };
      }
      return pos;
    },
登入後複製

注意上面一段程式碼我們修改的的內容,在這裡我們增加了一個判斷:也就是當支援transform屬性的瀏覽器存在時,我們會用transform屬性修改元素的值,把之前在getTranslate中得到的x、y賦值給pos的x、y。

在上面一段程式碼中,我們會根據瀏覽器的情況,用不同的方法取到相同的值,val的值來自getTranslate(),是我們從元素的transform中提取出來的。同樣,在下面的setPosition()中,我們也要設定if判斷。

setPosition: function(pos) {
      if (transform) {
        this.elem.style[transform] = 'translate(' + pos.x + 'px' + ',' + pos.y + 'px)';
      } else {
        this.elem.style.left = pos.x + 'px';
        this.elem.style.top = pos.y + 'px';
      }
    },
登入後複製

這一段沒什麼好講的,就是用不同的形式賦值而已。

到這裡,這個模組就封裝完畢了。接下來讓我們來看看完整程式碼:

;
(function() {
  //私有属性
  var transform = getTransform();
  //构造函数,属于每一个实例
  function Drag(selector) {
    this.elem = typeof selector == 'object' ? selector : document.getElementById(selector);
    //鼠标初始位置
    this.startX = 0;
    this.startY = 0;
    //元素初始位置
    this.sourceX = 0;
    this.sourceY = 0;

    this.init();
  }

  //原型,共有的
  Drag.prototype = {
    constructor: Drag,
    init: function() {
      this.setDrag();
    },

    //用于获取元素当前的位置信息
    getPosition: function() {
      var that = this;
      var pos = {};
      if(transform){
        var val=this.getTranslate();
        pos={
          x:val.x,
          y:val.y
        };
      }else{
        pos = {
          x: that.elem.offsetLeft,
          y: that.elem.offsetTop
        };
      }
      return pos;
    },

    //获取translate值
    getTranslate: function() {
      var val = {};
      var transformValue = document.defaultView.getComputedStyle(this.elem, false)[transform];
      if(transformValue=='none'){
        val={x:0,y:0};
      }else{
        var transformArr = transformValue.match(/-?\d+/g);
        val = {
          x: Number(transformArr[4]),
          y: Number(transformArr[5])
        };
      }


      return val;
    },
    //用来设置当前元素的位置
    setPosition: function(pos) {
      if (transform) {
        this.elem.style[transform] = 'translate(' + pos.x + 'px' + ',' + pos.y + 'px)';
      } else {
        this.elem.style.left = pos.x + 'px';
        this.elem.style.top = pos.y + 'px';
      }
    },

    //该方法用来绑定事件
    setDrag: function() {
      var self = this;
      this.elem.addEventListener('mousedown', start, false);

      function start(event) {

        self.startX = event.pageX;
        self.startY = event.pageY;

        var pos = self.getPosition();

        self.sourceX = pos.x;
        self.sourceY = pos.y;

        document.addEventListener('mousemove', move, false);
        document.addEventListener('mouseup', end, false);
      }

      function move(event) {
        //总体思想:鼠标距浏览器距-鼠标距元素距离
        var currentX = event.pageX; //当前的鼠标x位置
        var currentY = event.pageY; //当前的鼠标y位置

        var distanceX = currentX - self.startX; //鼠标移动的距离x
        var distanceY = currentY - self.startY; //鼠标移动的距离y

        self.setPosition({
          x: self.sourceX + distanceX,
          y: self.sourceY + distanceY
        });

      }

      function end(event) {
        document.removeEventListener('mousemove', move);
        document.removeEventListener('mouseup', end);
      }
    }
  };
  //私有方法,用来获取transform的兼容写法
  function getTransform() {
    var transform = "",
      pStyle = document.createElement('p').style,
      transformArr = ['transform', 'webkitTransform', 'MozTransform', 'msTransform', 'oTransform'],
      i = 0,
      l = transformArr.length;

    for (; i < l; i++) {
      if (transformArr[i] in pStyle) {
        return transform = transformArr[i];
      }
    }
    return transform;
  }
  //暴露在外
  window.Drag = Drag;
})();


new Drag('box');
登入後複製

相關推薦:

javascript全域變數封裝模組實作程式碼_javascript技巧

#

以上是封裝一個自己的模組實例詳解的詳細內容。更多資訊請關注PHP中文網其他相關文章!

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

<🎜>:泡泡膠模擬器無窮大 - 如何獲取和使用皇家鑰匙
3 週前 By 尊渡假赌尊渡假赌尊渡假赌
北端:融合系統,解釋
3 週前 By 尊渡假赌尊渡假赌尊渡假赌
Mandragora:巫婆樹的耳語 - 如何解鎖抓鉤
3 週前 By 尊渡假赌尊渡假赌尊渡假赌

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

熱門話題

Java教學
1665
14
CakePHP 教程
1423
52
Laravel 教程
1321
25
PHP教程
1269
29
C# 教程
1249
24
WLAN擴充模組已停止[修復] WLAN擴充模組已停止[修復] Feb 19, 2024 pm 02:18 PM

如果您的Windows電腦上的WLAN擴充模組出現問題,可能會導致您與網際網路中斷連線。這種情況常常讓人感到困擾,但幸運的是,本文提供了一些簡單的建議,可以幫助您解決這個問題,讓您的無線連線重新正常運作。修復WLAN擴充模組已停止如果您的Windows電腦上的WLAN可擴充性模組已停止運作,請依照下列建議進行修復:執行網路和Internet故障排除程式停用並重新啟用無線網路連線重新啟動WLAN自動設定服務修改電源選項修改高級電源設定重新安裝網路適配器驅動程式運行一些網路命令現在,讓我們來詳細看

WLAN可擴充性模組無法啟動 WLAN可擴充性模組無法啟動 Feb 19, 2024 pm 05:09 PM

本文詳細介紹了解決事件ID10000的方法,該事件表明無線區域網路擴充模組無法啟動。在Windows11/10PC的事件日誌中可能會顯示此錯誤。 WLAN可擴充性模組是Windows的一個元件,允許獨立硬體供應商(IHV)和獨立軟體供應商(ISV)為使用者提供客製化的無線網路特性和功能。它透過增加Windows預設功能來擴充本機Windows網路元件的功能。在作業系統載入網路元件時,WLAN可擴充性模組會作為初始化的一部分啟動。如果無線區域網路擴充模組遇到問題無法啟動,您可能會在事件檢視器的日誌中看到錯誤消

Python中的SVM實例 Python中的SVM實例 Jun 11, 2023 pm 08:42 PM

Python中的支援向量機(SupportVectorMachine,SVM)是一個強大的監督學習演算法,可以用來解決分類和回歸問題。 SVM在處理高維度資料和非線性問題的時候表現出色,被廣泛地應用於資料探勘、影像分類、文字分類、生物資訊學等領域。在本文中,我們將介紹在Python中使用SVM進行分類的實例。我們將使用scikit-learn函式庫中的SVM模

Ansible運作方式詳解 Ansible運作方式詳解 Feb 18, 2024 pm 05:40 PM

Ansible工作原理從上面的圖可以了解到:管理端支援local、ssh、zeromq三種方式連接被管理端,預設使用基於ssh的連接,這部分對應上面架構圖中的連接模組;可以按應用類型等方式進行HostInventory(主機清單)分類,管理節點透過各類模組實現對應的操作,單一模組,單一指令的批次執行,我們可以稱為ad-hoc;管理節點可以透過playbooks實作多個task的集合實作一類功能,如web服務的安裝部署、資料庫伺服器的批次備份等。 playbooks我們可以簡單的理解為,系統透過

VUE3入門實例:製作一個簡單的影片播放器 VUE3入門實例:製作一個簡單的影片播放器 Jun 15, 2023 pm 09:42 PM

隨著新一代前端框架的不斷湧現,VUE3作為一個快速、靈活、易上手的前端框架備受熱愛。接下來,我們就來一起學習VUE3的基礎知識,製作一個簡單的影片播放器。一、安裝VUE3首先,我們需要在本地安裝VUE3。開啟命令列工具,執行以下命令:npminstallvue@next接著,新建一個HTML文件,引入VUE3:&lt;!doctypehtml&gt;

一文總結特徵增強&個人化在CTR預估中的經典方法與效果對比 一文總結特徵增強&個人化在CTR預估中的經典方法與效果對比 Dec 15, 2023 am 09:23 AM

在CTR預估中,主流都採用特徵embedding+MLP的方式,其中特徵非常關鍵。然而對於相同的特徵,在不同的樣本中,表徵是相同的,這種方式輸入到下游模型,會限制模型的表達能力。為了解決這個問題,CTR預估領域提出了一系列相關工作,稱為特徵增強模組。特徵增強模組根據不同的樣本,對embedding層的輸出結果進行一次矯正,以適應不同樣本的特徵表示,提升模型的表達能力。最近,復旦大學和微軟亞洲研究院合作發布了一篇關於特徵增強工作的綜述,比較了不同特徵增強模組的實現方法及其效果。現在,我們來介紹一

學習Golang指標轉換的最佳實務範例 學習Golang指標轉換的最佳實務範例 Feb 24, 2024 pm 03:51 PM

Golang是一門功能強大且高效的程式語言,可用於開發各種應用程式和服務。在Golang中,指標是一種非常重要的概念,它可以幫助我們更靈活和有效率地操作資料。指標轉換是指在不同類型之間進行指標操作的過程,本文將透過具體的實例來學習Golang中指標轉換的最佳實踐。 1.基本概念在Golang中,每個變數都有一個位址,位址就是變數在記憶體中的位置。

Ansible Ad-Hoc(點對點模式) Ansible Ad-Hoc(點對點模式) Feb 18, 2024 pm 04:48 PM

官方文件:https://docs.ansible.com/ansible/latest/command_guide/intro_adhoc.html簡介Ad-hoc命令是一種臨時輸入並執行的命令,通常用於測試和調試。它們不需要永久保存,簡單來說,ad-hoc就是「即時命令」。常用模組1、command模組(預設模組)預設模組,沒有shell強大,基本上shell模組都可以支援command模組的功能。 【1】幫助ansible-doccommand#推薦使用下面這個ansible-doccomm

See all articles