Skip to content

Instantly share code, notes, and snippets.

@jonathanmarvens
Forked from mutewinter/README.md
Created September 18, 2017 05:28
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jonathanmarvens/ce6542d78dc87116fa29a2687328afed to your computer and use it in GitHub Desktop.
Save jonathanmarvens/ce6542d78dc87116fa29a2687328afed to your computer and use it in GitHub Desktop.
Prevent Double Tap Zoom in React for Rapidly Tapped Buttons

Prevent Double Tap Zoom in React for Rapidly Tapped Buttons

Touch delay is a thing of the past, but accidental zooming is here to ruin your day. Ever tapped a button quickly on iOS and experienced a zoom instead of two taps? You're in the right place.

Before

Before

After

After

Code

Just use this helper function to preventDefault on double taps, while still allowing for pinch to zoom and rapid scrolling.

// Ensure touches occur rapidly
const delay = 500
// Sequential touches must be in close vicinity
const minZoomTouchDelta = 10

// Track state of the last touch
let lastTapAt = 0
let lastClientX = 0
let lastClientY = 0

export default function preventDoubleTapZoom(event) {
  // Exit early if this involves more than one finger (e.g. pinch to zoom)
  if (event.touches.length > 1) {
    return
  }

  const tapAt = new Date().getTime()
  const timeDiff = tapAt - lastTapAt
  const { clientX, clientY } = event.touches[0]
  const xDiff = Math.abs(lastClientX - clientX)
  const yDiff = Math.abs(lastClientY - clientY)
  if (
    xDiff < minZoomTouchDelta &&
    yDiff < minZoomTouchDelta &&
    event.touches.length === 1 &&
    timeDiff < delay
  ) {
    event.preventDefault()
    // Trigger a fake click for the tap we just prevented
    event.target.click()
  }
  lastClientX = clientX
  lastClientY = clientY
  lastTapAt = tapAt
}

Example Use

const TapAsFastAsYouWantButton = (children, ...rest) =>
  <button {...props} onTouchStart={preventDoubleTapZoom}>
    {children}
  </button>

const Game = () =>
  <TapAsFastAsYouWantButton onClick={fireLasers}>
    Fire Lasers
  </TapAsFastAsYouWantButton>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment