見出し画像

Stamp コードのご紹介:マウスイベントをタッチイベントに変換するフック

個人で開発したアプリ Stamp のコードを紹介しようというシリーズ

Stamp の URL はこちら。

Stamp の紹介記事はこちら

Stamp のパレットでは、react-color-palette を使っています

画像1

ですがこれ、タッチイベントは拾ってくれません

スマホで色と濃淡を変えようとしても、タッチイベントを拾ってくれないので変えられません。

カスタムフックでタッチイベントをマウスイベントに変換するようにしました

import { useEffect, useRef } from 'react'

export const useTouchToMouse = (children) => {
   const ref = useRef(null)

   useEffect(() => {
       const target = children
                           ? ref.current.children[0]
                           : ref.current

       const touchStartToMouseDown = (event) => {

           const touchMoveToMouseMove = (event) => {
               event.clientX = event.changedTouches[0].clientX
               event.clientY = event.changedTouches[0].clientY

               document.dispatchEvent(new MouseEvent('mousemove', event))
           }
       
           const touchEndToMouseUp = (event) => {
               event.clientX = event.changedTouches[0].clientX
               event.clientY = event.changedTouches[0].clientY
               document.dispatchEvent(new MouseEvent('mouseup', event))

               document.removeEventListener('touchmove', touchMoveToMouseMove, {passive: true})
               document.removeEventListener('touchend', touchEndToMouseUp, {passive: false})
               // Suppresses mouse events that fire after tapping.
               event.preventDefault()
           }
   
           document.addEventListener('touchmove', touchMoveToMouseMove, {passive: true})
           document.addEventListener('touchend', touchEndToMouseUp, {passive: false})

           event.clientX = event.changedTouches[0].clientX
           event.clientY = event.changedTouches[0].clientY

           target.dispatchEvent(new MouseEvent('mousedown', event))

       }

       target.addEventListener('touchstart', touchStartToMouseDown, {passive: true})
       

       return () => {
           target.removeEventListener('touchstart', touchStartToMouseDown, {passive: true})
       }
   },[])
   
   return ref
}

使う側

フックから返却される ref を対象の ref 属性にセットします。
ここでは react-color-palette の Hue コンポーネントの入れ物、 Material-UI の Box の ref 属性に設定しています。

const touchableHueRef = useTouchToMouse(true)

中略

<Box pt={2} ref={touchableHueRef}>
    <Hue
       width={sliderRect.width}
       color={conf.backgroundColor.color}
       onChange={handleChangeBackgroundColor}
       />
</Box>

基本的な作り

touchstart イベントを拾ったら、touchmove, touchend のイベントリスナーを登録して、mousedown イベントを発生させます。

touchmove, touchend のイベントリスナーに設定されているコールバック関数は、touchstart のときと同様、それぞれ mousemove, mouseup イベントを発生させます。

ポイント

touchstart イベントを拾ったら、touchmove, touchend のイベントリスナーを登録するところです。

タッチされてなければ、指が移動したことや指が離れたことは別に気にしなくてもいいですもんね。

Stamp のコードは GitHub で公開しています

パレットで色や形を変えて、いろいろスタンプしてみてください!

いい感じの絵ができたら画面下の SHARE ボタンで Twitter シェアお願いします!

この記事があなたのお役に立ちましたら、よろしければサポートをお願いいたします! より良い記事をお届けできるよう、活動費に充てさせていただきます。