JavaScriptは、ドラッグ効果のあるコンポーネント機能を実現します。


ページ要素ドラッグは非常に実用的な先端効果であり、要素ドラッグに基づいて多くの異なる機能を実現し、クライアントの多くの操作の利便性を高め、ユーザー体験を大幅に向上させます。日常生活の中でこのような効果を見たことがある人は少なくないので、無駄話をせずに直接やりましょう。
所期の目標
Classクラスを実現し、このクラスを通じて、任意のDOM要素(divなど)をドラッグ可能な状態に変更することができ、元の状態に戻すこともできます。

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <style>
    #box1 {
      height: 50px;
      width: 50px;
      background-color: cadetblue;
    }

    #box2 {
      height: 50px;
      width: 50px;
      background-color: blue;
    }

    #box3 {
      height: 50px;
      width: 50px;
      background-color: red;
    }
  </style>
</head>

<body>
  <div id="box1">1</div>
  <a id="box2">2</a>
  <div id="box3">3</div>
</body>
<script type="module">
	//          Class
  import DragElement from './DragElement.js'
  //   3       
  let box1 = new DragElement(document.querySelector("#box1"))
  let box2 = new DragElement(document.querySelector("#box2"))
  let box3 = new DragElement(document.querySelector("#box3"))
  // box2       ,        
  // box2.dragRelease()
</script>
</html>
ありのままの姿
在这里插入图片描述
自由に引っぱる
在这里插入图片描述
一、アルゴリズムの考え方
1.1ドラッグ行為の説明
まず、ドラッグという行為をどう説明するかを考えます。私の考えはこうです。
  • は、まずドラッグという行為を定義します。指定された要素の上でマウスを押した状態を維持すると、この要素はマウスに従って移動します。マウスが離れると、要素はマウスに従って移動しなくなります。移動端であれば、マウスのキャラクターをタッチに変更すればいいです。
  • 定義に基づいて、いくつかの重要な情報を確定できます。
  • マウス移動は、アルゴリズム自体の作用範囲をドラッグすることです。
  • マウスを押して、ドラッグをオンにします。
  • マウスを放し、ドラッグをオフにします。
    完全なドラッグ機能は3つの部分に分けられています。それぞれオン、運転、オフです。マウスの押下、運転、解除にそれぞれ対応します。したがって、イベントのフィードバックとして、対応する3つの関数を設計する必要があります。ここで私はそれぞれドラゴンズ、ドラゴムービー、ドラゴンズと名づけました。
    ここで最初のポイントがあります。ドラッグ機能の状態変化をどう説明しますか?
    明らかにマウスの押しと放しは、DOM元素がドラッグされるかどうかを決定します。これは「状態」の変化です。この状態の変化は符号化において一つの変数によって達成されてもよく、また連続的にエンコーディング関数を追加または除去することによって達成されてもよい。変数を通過すると、マウスが押されていない時にマウス移動イベントも状態判断をトリガします。これは必要ではないので、後者を選択して、マウスを押して放した時に、それぞれドラッグ機能を追加して削除します。
    以上はドラッグ自体の行為であり、また、DOM要素は元の状態とドラッグ可能な状態の間で変換できるので、DOM要素をドラッグ可能な状態にし、もう一つはこれらの状態をアンインストールするための2つの関数が必要です。前者はdragActiveといいます。後者はドラゴレアスといいます。それらのすることは、事件の傍受を追加して解除することです。
    第一の問題を解決しました。第二の問題を解決します。つまり、ドラッグ機能はどうやって実現しますか?
    1.2ドラッグの実現
    まず核心のを見て、ドラッグ自体はどうやって計算しますか?
    同じように、私たちは現実の場面を想像し続けます。マウスを押すと、マウスの座標が(x 0,y 0)点にあると仮定して、マウスが移動し、(x 1,y 1)点に移動したと仮定します。この要素は、自身の初期位置に対して(x 1-x 0,y 1-y 0)距離を移動する。このような自身の移動に対して、CSSで相対的な位置付けができますし、トランスフォーム:translateまたはtranslate 3 dによって実現できます。配置によく使われていますので、指定されたDOM要素はどのような形なのかは分かりません。できるだけ元のレイアウトに影響しないように、tranformを採用します。
    具体的な計算に戻ると、マウスの位置xとyは、イベントコールバック関数によってもたらされるパラメータeventで得られ、PC端にevent.client Xとevent.client.Yがあり、移動端はevent.chaged Touches[0].pageXとevent.changed Touches[0].pageYがあります。mousemioveイベントは連続的に触発され、私達のドラッグも元素をマウスに従って連続的に運動させるため、更新(x 0、y 0)、(x 1、y 1)の値が必要です。小さな運動の中で差計算が行われます。微積分のように。記録と更新を容易にするために、ドラッグに必要な変数を一つのオブジェクトで表現してもいいです。「dragInfo」といいます。document要素にマウントして、このように関数とオブジェクトの間でアクセスできます。
    
    class DragElement {
      constructor(element) {
        this.element = element
        document.dragInfo = {
          element: this.element,
          x0: 0,
          y0: 0,
          x1: 0,
          y1: 0
        }
      }
    }
    elementはドラッグの要素を表し、xとyはそれぞれ計算に必要な変数です。
    マウスの位置の関数を取得:
    
    updateDragPosition = (event) => {
    	return {
    		x: event.clientX || (event.changedTouches ? event.changedTouches[0].pageX : document.dragInfo.x0),
    		y: event.clientY || (event.changedTouches ? event.changedTouches[0].pageY : document.dragInfo.y0)
    	}
    }
    なぜ直接event.client X𞓜event.changed Touches[0].pageXではなく、三元表現を使うのかという疑問があるかもしれません。この理由は、上記の両方が存在しない場合があります。例えば、マウスがブラウザの左端に移動すると、位置が得られません。
    在这里插入图片描述
    マウスの位置の関数を取得して書き終わったら、ドラッグの関数を書くことができます。
    
    dragMoving = (event) => {
    	document.dragInfo.x1 = this.updateDragPosition(event).x - document.dragInfo.x0 + document.dragInfo.x1
    	document.dragInfo.y1 = this.updateDragPosition(event).y - document.dragInfo.y0 + document.dragInfo.y1
    	document.dragInfo.x0 = this.updateDragPosition(event).x
    	document.dragInfo.y0 = this.updateDragPosition(event).y
    	document.dragInfo.element.style.transform = 'translate3d(' + document.dragInfo.x1 + 'px, ' + document.dragInfo.y1 + 'px, 0)';
    }
    しかしこの時問題が来ました。documentには一つのdragInfoしかないので、異なるコンポーネント間の座標の衝突はどう解決しますか?実はこれは簡単で、this.elementにオブジェクトを追加してドラッグした後の位置を記録すればいいです。ドラッグ要素をクリックするたびに、この要素の情報をdocument.dragInfoに注入します。
    
    this.element.dragPostion = {
    	x: 0,
    	y: 0
    }
    以上より、最も核心的なフロー説明とアルゴリズム部分を解決しました。これからはコード化だけでいいです。
    二、コード実現
    前に言った考えによって、自分でコードを読んでください。全体のロジックはまだとてもはっきりしています。もしいくつかの詳細が分からないなら、コメントエリアで提出してもいいです。あるいは暇があったら補充します。
    
    class DragElement {
      constructor(element) {
        this.element = element
        document.dragInfo = {
          element: this.element,
          x0: 0,
          y0: 0,
          x1: 0,
          y1: 0
        }
        document.updateDragPosition = this.updateDragPosition
        this.dragActive()
      }
    
      //       
      updateDragPosition = (event) => {
        return {
          x: event.clientX || (event.changedTouches ? event.changedTouches[0].pageX : document.dragInfo.x0),
          y: event.clientY || (event.changedTouches ? event.changedTouches[0].pageY : document.dragInfo.y0)
        }
      }
    
      //               
      dragActive = () => {
        if (!this.element) return
        this.element.style.display = "block" 
        this.element.addEventListener('mousedown', this.dragStart, false)
        this.element.addEventListener('touchstart', this.dragStart, false)
        this.element.addEventListener('mouseup', this.dragEnd, false) //   
        this.element.addEventListener('touchend', this.dragEnd, false)
        this.element.addEventListener('touchcancel', this.dragEnd, false)
        //           ,      
        this.element.dragPostion = {
          x: 0,
          y: 0
        }
      }
    
      //     
      dragRelease = () => {
        this.element.removeEventListener('mousedown', this.dragStart)
        this.element.removeEventListener('touchstart', this.dragStart)
        this.element.removeEventListener('mouseup', this.dragEnd) //   
        this.element.removeEventListener('touchend', this.dragEnd)
        this.element.removeEventListener('touchcancel', this.dragEnd)
        this.element.style.display = ""
        return this.element
      }
    
      //         ,       
      dragStart = (event) => {
        document.dragInfo.element = this.element
        document.dragInfo.x0 = this.updateDragPosition(event).x
        document.dragInfo.y0 = this.updateDragPosition(event).y
        document.dragInfo.x1 = this.element.dragPostion.x
        document.dragInfo.y1 = this.element.dragPostion.y
        //       
        event.preventDefault();
    
        // mousemove     document  ,               
        document.addEventListener('mousemove', this.dragMoving, false)
        document.addEventListener('touchmove', this.dragMoving, false)
      }
    
      //     、        
      dragMoving = (event) => {
        document.dragInfo.x1 = this.updateDragPosition(event).x - document.dragInfo.x0 + document.dragInfo.x1
        document.dragInfo.y1 = this.updateDragPosition(event).y - document.dragInfo.y0 + document.dragInfo.y1
        document.dragInfo.x0 = this.updateDragPosition(event).x
        document.dragInfo.y0 = this.updateDragPosition(event).y
        document.dragInfo.element.style.transform = 'translate3d(' + document.dragInfo.x1 + 'px, ' + document.dragInfo.y1 + 'px, 0)';
      }
    
      //     
      dragEnd = () => {
        //       
        this.element.dragPostion.x = document.dragInfo.x1
        this.element.dragPostion.y = document.dragInfo.y1
        //   
        document.removeEventListener('touchmove', this.dragMoving)
        document.removeEventListener('mousemove', this.dragMoving)
      }
    }
    
    export default DragElement
    ここでは、JavaScriptのドラッグ効果コンポーネント機能(モバイル端末対応)に関する記事を紹介します。JavaScriptのドラッグ効果コンポーネントの内容については、以前の文章を検索したり、下記の関連記事を閲覧したりしてください。これからもよろしくお願いします。