Skip to content

Mobile gesture scaling suggestions (plugin implementation scheme) #362

@SrdptsClue

Description

@SrdptsClue
import { MindElixirInstance } from "mind-elixir"

export function TouchFixPlugin(me: MindElixirInstance) {
  if (me.plugins.touchFix?.state) {
    return
  }

  me.plugins.touchFix = { state: true }

  let lastDistance: number | null = null
  const activePointers = new Map<number, { x: number; y: number }>()

  const getDistance = (p1: { x: number; y: number }, p2: { x: number; y: number }) => {
    const dx = p1.x - p2.x
    const dy = p1.y - p2.y
    return Math.sqrt(dx * dx + dy * dy)
  }

  const handlePointerStart = (e: PointerEvent) => {
    if (e.pointerType !== "touch") return

    // Record current touch point
    activePointers.set(e.pointerId, { x: e.clientX, y: e.clientY })

    // Only intercept the original logic when there are 2+ fingers
    if (activePointers.size >= 2) {
      e.stopImmediatePropagation()

      // Initialize distance when the second finger touches down
      if (activePointers.size === 2) {
        const [p1, p2] = Array.from(activePointers.values())
        lastDistance = getDistance(p1, p2)
      }
    }
  }

  const handlePointerMove = (e: PointerEvent) => {
    if (e.pointerType !== "touch") return
    if (!activePointers.has(e.pointerId)) return

    // Update current touch point position
    activePointers.set(e.pointerId, { x: e.clientX, y: e.clientY })

    // Only handle pinch zoom when there are 2+ fingers
    if (activePointers.size < 2) return

    const [p1, p2] = Array.from(activePointers.values())
    const newDistance = getDistance(p1, p2)

    if (lastDistance == null) {
      lastDistance = newDistance
      return
    }

    const delta = newDistance - lastDistance
    const THRESHOLD = 8 // Only trigger when distance changes enough to avoid over-sensitivity

    if (Math.abs(delta) > THRESHOLD) {
      if (delta > 0) {
        // Fingers moving apart -> zoom in
        document.getElementById("zoomin")?.click()
      } else {
        // Fingers pinching -> zoom out
        document.getElementById("zoomout")?.click()
      }

      lastDistance = newDistance
    }

    // Intercept original pointermove behavior (e.g., single-finger drag logic)
    e.stopImmediatePropagation()
  }

  const handlePointerEnd = (e: PointerEvent) => {
    if (e.pointerType !== "touch") return

    activePointers.delete(e.pointerId)

    // End this zoom gesture when fewer than 2 fingers remain
    if (activePointers.size < 2) {
      lastDistance = null
    }
  }

  const container = me.el

  container.addEventListener("pointerdown", handlePointerStart, { capture: true })
  container.addEventListener("pointermove", handlePointerMove, { capture: true })
  container.addEventListener("pointerup", handlePointerEnd, { capture: true })
  container.addEventListener("pointercancel", handlePointerEnd, { capture: true })
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions