js實現元素范圍內拖動


元素拖拽,網上一堆的實現,其中很多是原生js寫的,都不夠簡潔,甚至運行后看不到效果。

於是乎,安靜地想了下,拖動元素貌似就是一個滑動事件的監聽處理,具體操作如下:

1、一個外層DIV,或者直接用根節點代替。

2、一個可拖動的元素,設置一個選擇器,如下設置的是class="obj"。

3、元素css設置絕對定位,相對於影響其定位的父元素做范圍內可拖拽

注:例子中相對於網頁可見高寬的范圍移動,所以用到了document.documentElement的高寬,如果其父元素是swiper插件的滑塊,可以給元素再加個"swiper-no-swiping"類名,具體看swiper禁止切換文檔,以保證拖動時的良好體驗。

  $(".obj").on("touchmove", function(e) {
   e.preventDefault();
     var moveEndX = e.originalEvent.changedTouches[0].pageX;
   var moveEndY = e.originalEvent.changedTouches[0].pageY;

     var xMM = moveEndX - $(this).width() / 2;
     var yMM = moveEndY - $(this).height() / 2;
     if(xMM < document.documentElement.clientWidth - $(this).width() && xMM > 0){
         $(this).css("left",xMM+"px");
     }
     
     if(yMM < document.documentElement.clientHeight - $(this).height() && yMM > 0){
         $(this).css("top",yMM+"px");
     }
     

  });

 

沒錯,就是這么簡單,這是用jquery實現的,別忘了引入jquery庫,以下是關於觸摸事件和手勢事件的一些簡介,多了解下還是很有用的。

內容摘自javaScript高級程序設計手冊:

iOS 版Safari 為了向開發人員傳達一些特殊信息,新增了一些專有事件。因為iOS 設備既沒有鼠標也沒有鍵盤,所以在為移動Safari 開發交互性網頁時,常規的鼠標和鍵盤事件根本不夠用。隨着Android中的WebKit 的加入,很多這樣的專有事件變成了事實標准,導致W3C 開始制定Touch Events 規范(參見https://dvcs.w3.org/hg/webevents/raw-file/tip/touchevents.html)。以下介紹的事件只針對觸摸設備。

1. 觸摸事件

包含iOS 2.0 軟件的iPhone 3G 發布時,也包含了一個新版本的Safari 瀏覽器。這款新的移動Safari提供了一些與觸摸(touch)操作相關的新事件。后來,Android 上的瀏覽器也實現了相同的事件。觸摸事件會在用戶手指放在屏幕上面時、在屏幕上滑動時或從屏幕上移開時觸發。具體來說,有以下幾個觸摸事件。

  • touchstart:當手指觸摸屏幕時觸發;即使已經有一個手指放在了屏幕上也會觸發。
  • touchmove:當手指在屏幕上滑動時連續地觸發。在這個事件發生期間,調用preventDefault()可以阻止滾動。
  • touchend:當手指從屏幕上移開時觸發。
  • touchcancel:當系統停止跟蹤觸摸時觸發。關於此事件的確切觸發時間,文檔中沒有明確說明。

上面這幾個事件都會冒泡,也都可以取消。雖然這些觸摸事件沒有在DOM 規范中定義,但它們卻是以兼容DOM 的方式實現的。因此,每個觸摸事件的event 對象都提供了在鼠標事件中常見的屬性:
bubbles、cancelable、view、clientX、clientY、screenX、screenY、detail、altKey、shiftKey、ctrlKey 和metaKey。
除了常見的DOM屬性外,觸摸事件還包含下列三個用於跟蹤觸摸的屬性。

  • touches:表示當前跟蹤的觸摸操作的Touch 對象的數組。
  • targetTouchs:特定於事件目標的Touch 對象的數組。
  • changeTouches:表示自上次觸摸以來發生了什么改變的Touch 對象的數組。

每個Touch 對象包含下列屬性。

  • clientX:觸摸目標在視口中的x 坐標。
  • clientY:觸摸目標在視口中的y 坐標。
  • identifier:標識觸摸的唯一ID。
  • pageX:觸摸目標在頁面中的x 坐標。
  • pageY:觸摸目標在頁面中的y 坐標。
  • screenX:觸摸目標在屏幕中的x 坐標。
  • screenY:觸摸目標在屏幕中的y 坐標。
  • target:觸摸的DOM 節點目標。

使用這些屬性可以跟蹤用戶對屏幕的觸摸操作。來看下面的例子。

function handleTouchEvent(event) {
    //只跟蹤一次觸摸
    if (event.touches.length == 1) {
        var output = document.getElementById("output");
        switch (event.type) {
        case "touchstart":
            output.innerHTML = "Touch started (" + event.touches[0].clientX + "," + event.touches[0].clientY + ")";
            break;
        case "touchend":
            output.innerHTML += "<br>Touch ended (" + event.changedTouches[0].clientX + "," + event.changedTouches[0].clientY + ")";
            break;
        case "touchmove":
            event.preventDefault(); //阻止滾動
            output.innerHTML += "<br>Touch moved (" + event.changedTouches[0].clientX + "," + event.changedTouches[0].clientY + ")";
            break;
        }
    }
}
EventUtil.addHandler(document, "touchstart", handleTouchEvent);
EventUtil.addHandler(document, "touchend", handleTouchEvent);
EventUtil.addHandler(document, "touchmove", handleTouchEvent);

以上代碼會跟蹤屏幕上發生的一次觸摸操作。為簡單起見,只會在有一次活動觸摸操作的情況下輸出信息。當touchstart 事件發生時,會將觸摸的位置信息輸出到<div>元素中。當touchmove 事件發生時,會取消其默認行為,阻止滾動(觸摸移動的默認行為是滾動頁面),然后輸出觸摸操作的變化信息。而touchend 事件則會輸出有關觸摸操作的最終信息。注意,在touchend 事件發生時,touches集合中就沒有任何Touch 對象了,因為不存在活動的觸摸操作;此時,就必須轉而使用changeTouchs集合。
這些事件會在文檔的所有元素上面觸發,因而可以分別操作頁面的不同部分。在觸摸屏幕上的元素時,這些事件(包括鼠標事件)發生的順序如下:

  • (1) touchstart
  • (2) mouseover
  • (3) mousemove(一次)
  • (4) mousedown
  • (5) mouseup
  • (6) click
  • (7) touchend

支持觸摸事件的瀏覽器包括iOS 版Safari、Android 版WebKit、bada 版Dolfin、OS6+中的BlackBerryWebKit、Opera Mobile 10.1+和LG 專有OS 中的Phantom 瀏覽器。目前只有iOS 版Safari 支持多點觸摸。桌面版Firefox 6+和Chrome 也支持觸摸事件。

2. 手勢事件

iOS 2.0 中的Safari 還引入了一組手勢事件。當兩個手指觸摸屏幕時就會產生手勢,手勢通常會改變顯示項的大小,或者旋轉顯示項。有三個手勢事件,分別介紹如下。

  • gesturestart:當一個手指已經按在屏幕上而另一個手指又觸摸屏幕時觸發。
  • gesturechange:當觸摸屏幕的任何一個手指的位置發生變化時觸發。
  • gestureend:當任何一個手指從屏幕上面移開時觸發。

只有兩個手指都觸摸到事件的接收容器時才會觸發這些事件。在一個元素上設置事件處理程序,意味着兩個手指必須同時位於該元素的范圍之內,才能觸發手勢事件(這個元素就是目標)。由於這些事件冒泡,所以將事件處理程序放在文檔上也可以處理所有手勢事件。此時,事件的目標就是兩個手指都位於其范圍內的那個元素。
觸摸事件和手勢事件之間存在某種關系。當一個手指放在屏幕上時,會觸發touchstart 事件。如果另一個手指又放在了屏幕上,則會先觸發gesturestart 事件,隨后觸發基於該手指的touchstart事件。如果一個或兩個手指在屏幕上滑動,將會觸發gesturechange 事件。但只要有一個手指移開,就會觸發gestureend 事件,緊接着又會觸發基於該手指的touchend 事件。
與觸摸事件一樣,每個手勢事件的event 對象都包含着標准的鼠標事件屬性:bubbles、cancelable、view、clientX、clientY、screenX、screenY、detail、altKey、shiftKey、ctrlKey 和metaKey。此外,還包含兩個額外的屬性:rotation 和scale。其中,rotation 屬性表示手指變化引起的旋轉角度,負值表示逆時針旋轉,正值表示順時針旋轉(該值從0 開始)。而scale屬性表示兩個手指間距離的變化情況(例如向內收縮會縮短距離);這個值從1 開始,並隨距離拉大而增長,隨距離縮短而減小。
下面是使用手勢事件的一個示例。

function handleGestureEvent(event) {
    var output = document.getElementById("output");
    switch (event.type) {
    case "gesturestart":
        output.innerHTML = "Gesture started (rotation=" + event.rotation + ",scale=" + event.scale + ")";
        break;
    case "gestureend":
        output.innerHTML += "<br>Gesture ended (rotation=" + event.rotation + ",scale=" + event.scale + ")";
        break;
    case "gesturechange":
        output.innerHTML += "<br>Gesture changed (rotation=" + event.rotation + ",scale=" + event.scale + ")";
        break;
    }
}
document.addEventListener("gesturestart", handleGestureEvent, false);
document.addEventListener("gestureend", handleGestureEvent, false);
document.addEventListener("gesturechange", handleGestureEvent, false);

與前面演示觸摸事件的例子一樣,這里的代碼只是將每個事件都關聯到同一個函數中,然后通過該函數輸出每個事件的相關信息。

觸摸事件也會返回rotation 和scale 屬性,但這兩個屬性只會在兩個手指與屏幕保持接觸時才會發生變化。一般來說,使用基於兩個手指的手勢事件,要比管理觸摸事件中的所有交互要容易得多。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM