Heim  >  Artikel  >  Web-Frontend  >  So implementieren Sie eine Gestenbibliothek in JavaScript

So implementieren Sie eine Gestenbibliothek in JavaScript

醉折花枝作酒筹
醉折花枝作酒筹nach vorne
2021-05-07 09:25:322473Durchsuche

In diesem Artikel erfahren Sie, wie Sie den Datumsgrößenvergleich in JS implementieren. Es hat einen gewissen Referenzwert. Freunde in Not können sich darauf beziehen. Ich hoffe, es wird für alle hilfreich sein.

So implementieren Sie eine Gestenbibliothek in JavaScript

Startereignis

Zuerst lösen wir ein Startereignis aus, das erste Ereignis, das ausgelöst wird, wenn unser Finger den Bildschirm berührt. Zu diesem Zeitpunkt wird es drei Situationen geben:

  • Lose deine Finger
    • Das Endereignis wird ausgelöst, was ein Tap-Klickverhalten darstellt
    • tap 点击的行为
  • 通过监听 end 事件来实现即可
  • 手指拖动超过 10 px  
    • 这种就是 pan start 拖动的行为
    • 我们可以在 move 事件判断当前与上一个触点的距离
  • 手指停留在当前位置超过 0.5s  
    • 这种就是 press start 按压的行为
    • 我们可以添加一个 setTimeout 来实现
  • Press 事件

    所以我们第一步就是在 start 函数中加入一个 setTimout 的 handler 处理程序。

    let handler;let start = point => {
      handler = setTimeout(() => {
        console.log('presss ');
      }, 500);};

    一般来说 press 是我们比较常见的一个行为。但是实际上这里是 press start 事件,后面还会跟随着一个 press end 的事件。我们也可以统称这个为 press 事件,然后这个手势库的使用者只需要监听这个 press 事件即可,极少的情况下是需要监听 press end 事件的。

    这里我们需要注意的是,当我们触发其他的事件的时候,这个 500 毫秒的 setTimout 是有可能会被取消掉的。所以我们需要给这段逻辑一个 handler,并且放在全局作用域中,让其他事件可以获取到这个变量,并且可使用它取消掉这个处理逻辑。

    Pan 事件

    接下来我们就去监听移动 10px 的 pan 事件,这里就需要我们记录一开始用户触摸屏幕时的 x 和 y 坐标,当用户移动手指的时候,持续计算新移动到的位置与初始位置的距离。如果这个距离超过了 10px 就可以触发我们的 pan start 的事件了。

    所以首先我们需要在 start 函数中加入 startXstartY 的坐标记录,这里要注意的是,因为这两个值都是会在多个地方被使用的,所以也是需要在全局作用域中声明。

    然后在 move 函数中计算当前触点与起点的直径距离。这里我们需要用到数学中的直径运算公式  z 2 x^2 + y^2 = z^2x 2 +y 2 =z 2 ,而这里面的 x 是 当前触点的 x 坐标 - 起点的 x 坐标 的 x 轴的距离, y 就是 当前出点的 y 坐标 - 起点的 y 坐标 运算出来的 y 轴的距离。最终两个距离二次幂相加就是直径距离的二次幂。

     在代码中我们一般都会尽量避免使用根号运算,因为根号运算会对性能有一定的影响。我们知道最终要判断的是直径距离是否是大于一个固定的 10px。那就是说 z = 10,而 z 的二次幂就是 100,所以我们直接判断这个直径距离是否大于 100 即可。

    这里还有一个需要注意的,就是当我们手指移动超过 10px 之后,如果我们手指没有离开屏幕而是往回移动了,这样的话我们距离起点已经不够 10px了。但是这个其实也是算 pan 事件,因为我们确实有移动超过 10px 距离,超过这个距离之后所有的移动都是属于 pan 事件。

    所以我们需要一个 isPan 的状态,第一次移动超出 10px 的时候,就会触发 pan-start 事件,并且把 isPan 置为 true,而后面的所有移动都会触发 pan 事件。

    根据我们上面讲到的 press 事件,如果我们按下手指后 0.5 秒内出现了移动,那么 press 事件就会被取消。所以这里我们就需要 clearTimeoutpressstarthandlerDies kann durch Abhören des Endereignisses erreicht werden

    Mit dem Finger mehr als 10 px ziehen

    Dies ist das Verhalten des Pan-Start-Ziehens

    Wir können den Abstand zwischen dem aktuellen und dem vorherigen Kontaktpunkt im Bewegungsereignis beurteilen🎜 🎜Der Finger bleibt länger als 0,5 Sekunden an der aktuellen Position🎜 🎜🎜Dies ist das Verhalten beim Drücken von Start drücken🎜Wir können ein setTimeout hinzufügen, um 🎜Press-Ereignis🎜🎜 zu implementieren 🎜🎜Also ist unser erster Schritt, start Fügen Sie der Funktion einen <code>setTimout-Handler hinzu. 🎜
    let handler;let startX, startY;let isPan = false;let start = point => {
      (startX = point.clientX), (startY = point.clientY);
    
      isPan = false;
    
      handler = setTimeout(() => {
        console.log(&#39;pressstart&#39;);
      }, 500);};let move = point => {
      let dx = point.clientX - startX,
        dy = point.clientY - startY;
    
      let d = dx ** 2 + dy ** 2;
    
      if (!isPan && d > 100) {
        isPan = true;
        console.log(&#39;pan-start&#39;);
        clearTimeout(handler);
      }
    
      if (isPan) {
        console.log(dx, dy);
        console.log(&#39;pan&#39;);
      }};
    🎜Generell ist drücken ein häufiges Verhalten bei uns. Aber eigentlich handelt es sich hierbei um ein Press-Start-Event, gefolgt von einem Press-Ende-Event. Wir können dies auch gemeinsam als press-Ereignis bezeichnen, und dann müssen Benutzer dieser Gestenbibliothek nur auf dieses press-Ereignis hören Ende drücken Ereignis. 🎜🎜Was wir hier beachten müssen, ist, dass dieses 500-Millisekunden-setTimout möglicherweise abgebrochen wird, wenn wir andere Ereignisse auslösen. Daher müssen wir dieser Logik einen handler geben und ihn in den globalen Bereich einfügen, damit andere Ereignisse diese Variable abrufen und zum Abbrechen dieser Verarbeitungslogik verwenden können. „Pan-Event“: Das pan-Ereignis, das sich um 10 Pixel bewegt. Hier müssen wir die x- und y-Koordinaten aufzeichnen, wenn der Benutzer zu Beginn seinen Finger bewegt Position und die Ausgangsposition. Wenn dieser Abstand 10 Pixel überschreitet, kann unser pan start-Ereignis ausgelöst werden. 🎜🎜Also müssen wir zuerst die Koordinatendatensätze von startX und startY in der Startfunktion hinzufügen. Hierbei ist zu beachten, dass diese beiden Werte vorhanden sind an mehreren Stellen verwendet wird, muss es daher auch im globalen Bereich deklariert werden. 🎜🎜Anschließend berechnen Sie den Durchmesserabstand zwischen dem aktuellen Kontaktpunkt und dem Startpunkt in der Bewegungsfunktion. Hier müssen wir die Durchmesserberechnungsformel in der Mathematik z 2 x^2 + y^2 = z^2x verwenden 2 +y 2 =z 2 , und x ist hier der x-Achsenabstand zwischen der x-Koordinate des aktuellen Kontaktpunkts – der die y-Koordinate des Startpunkts. Die endgültige Summe der beiden Abstände hoch zwei ist der Durchmesserabstand hoch hoch zwei. 🎜🎜 Im Code versuchen wir im Allgemeinen, die Verwendung radikaler Operationen zu vermeiden, da radikale Operationen einen gewissen Einfluss auf die Leistung haben. Wir wissen, dass wir letztendlich beurteilen müssen, ob der Durchmesserabstand größer als feste 10 Pixel ist. Das heißt, z = 10 und die zweite Potenz von z ist 100, sodass wir direkt bestimmen können, ob der Durchmesserabstand größer als 100 ist. 🎜🎜Eine weitere Sache, die hier zu beachten ist, ist, dass wir nicht mehr 10 Pixel vom Startpunkt entfernt sind, wenn sich unser Finger um mehr als 10 Pixel bewegt, wenn unser Finger den Bildschirm nicht verlässt, sondern sich zurückbewegt. Dabei handelt es sich jedoch tatsächlich um ein Pan-Ereignis, da wir uns über eine Distanz von mehr als 10 Pixel bewegt haben und alle Bewegungen nach dieser Distanz Pan-Ereignisse sind. 🎜🎜Wir benötigen also einen isPan-Status. Wenn die erste Bewegung 10 Pixel überschreitet, wird das pan-start-Ereignis ausgelöst und isPan > auf gesetzt wahr, und alle nachfolgenden Bewegungen lösen das pan-Ereignis aus. 🎜🎜Gemäß dem oben erwähnten press-Ereignis wird das press-Ereignis abgebrochen, wenn innerhalb von 0,5 Sekunden nach dem Drücken unseres Fingers eine Bewegung erfolgt. Hier benötigen wir also clearTimeout, um den handler von pressstart zu löschen. 🎜
    let handler;let startX, startY;let isPan = false,
      isPress = false,
      isTap = false;let start = point => {
      (startX = point.clientX), (startY = point.clientY);
    
      isPan = false;
      isTap = true;
      isPress = false;
    
      handler = setTimeout(() => {
        isPan = false;
        isTap = false;
        isPress = true;
        console.log(&#39;press-start&#39;);
        handler = null;
      }, 500);};let move = point => {
      let dx = point.clientX - startX,
        dy = point.clientY - startY;
    
      let d = dx ** 2 + dy ** 2;
    
      if (!isPan && d > 100) {
        isPan = true;
        isTap = false;
        isPress = false;
        console.log(&#39;pan-start&#39;);
        clearTimeout(handler);
      }
    
      if (isPan) {
        console.log(dx, dy);
        console.log(&#39;pan&#39;);
      }};let end = point => {
      if (isTap) {
        console.log(&#39;tap&#39;);
        clearTimeout(handler);
      }};
    🎜Tap-Event🎜🎜🎜🎜

    Tap 的这个逻辑我们可以在 end 事件里面去检查。首先我们默认有一个 isTap 等于 true 的状态,如果我们触发了 pan 事件的话,那就不会去触发 tap 的逻辑了,所以 tap 和 pan 是互斥的关系。但是为了不让它们变得很耦合,所以我们不使用原有的 isPan 作为判断状态,而是另外声明一个 isTap 的状态来记录。

    这里我们 tap 和 pan 都有单独的状态,那么我们 press 也不例外,所以也给 press 加上一个 isPress 的状态,它的默认值是 false。如果我们 0.5 秒的定时器被触发了,isPress 也就会变成 true。

    既然我们给每个事件都加入了状态,那么这里我们就给每一个事件触发的时候设置好这些状态的值。

    • press 时  
      • isTap = false
      • isPan = false
      • isPress = true
    • pan 时  
      • isTap = false
      • isPan = true
      • isPress = false
    • tap 时  
      • isTap = true
      • isPan = false
      • isPress = false

    如果我们发现用户没有移动,也没有按住触屏超过 0.5 秒,当用户离开屏幕时就会调用 end 函数,这个时候我们就可以认定用户的操作就是 tap。这里我们要注意的是,我们 press 的 0.5 秒定时器是没有被关闭的,所以我们在 isTap 的逻辑中需要 clearTimeout(handler)

    说到取消 press 定时器,其实我们 handler 的回调函数中,也需要做一个保护代码逻辑,在触发了 press-start 之后,我们需要保证每次点击屏幕只会触发一次,所以在 setTimout 的回调函数中的最后,我们需要加上 handler = null。这样只要 press-start 触发了,就不会再被触发。

    let handler;let startX, startY;let isPan = false,
      isPress = false,
      isTap = false;let start = point => {
      (startX = point.clientX), (startY = point.clientY);
    
      isPan = false;
      isTap = true;
      isPress = false;
    
      handler = setTimeout(() => {
        isPan = false;
        isTap = false;
        isPress = true;
        console.log(&#39;press-start&#39;);
        handler = null;
      }, 500);};let move = point => {
      let dx = point.clientX - startX,
        dy = point.clientY - startY;
    
      let d = dx ** 2 + dy ** 2;
    
      if (!isPan && d > 100) {
        isPan = true;
        isTap = false;
        isPress = false;
        console.log(&#39;pan-start&#39;);
        clearTimeout(handler);
      }
    
      if (isPan) {
        console.log(dx, dy);
        console.log(&#39;pan&#39;);
      }};let end = point => {
      if (isTap) {
        console.log(&#39;tap&#39;);
        clearTimeout(handler);
      }};

    End 事件

    到了最后这里我们要处理的就是所有的结束时间,包括 press-endpan-end

    这两个 end 事件都会在 end 函数中判断所得,如果在用户操作的过程中触发了 pan-start 或者 press-start 事件,到了 end 函数这里,对应的状态就会是 true。

    所以我们对 end 函数做了以下改造:

    let end = point => {
      if (isTap) {
        console.log(&#39;tap&#39;);
        clearTimeout(handler);
      }
    
      if (isPan) {
        console.log(&#39;pan-end&#39;);
      }
    
      if (isPress) {
        console.log(&#39;press-end&#39;);
      }};

    最后我们需要在 cancel 事件触发的时候,清楚掉 press 事件的 setTimeout。既然我们的操作被打断了,那也不可能会触发我们的长按事件了。

    // 加入 cancellet cancel = point => {
      clearTimeout(handler);
      console.log(&#39;cancel&#39;);};

    我们除了 flick 的逻辑,我们已经完成所有手势库里面的事件了。并且也能正确的区分这几种手势操作了。

    【推荐学习:javascript高级教程

    Das obige ist der detaillierte Inhalt vonSo implementieren Sie eine Gestenbibliothek in JavaScript. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

    Stellungnahme:
    Dieser Artikel ist reproduziert unter:csdn.net. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen