実装方法が分かるまで迷うことが多かったので、方法を大雑把に共有します。
re-natalに関する記事ですが、react-nativeで作られる場合も参考になる部分があると思います。
使ったもの
- re-natalで作っているアプリ
re-natalとはreact-nativeをclojurescriptで開発できるフレームワークです。
re-natal-esp32control-appを開発しています。 - 上記アプリの開発環境
$ re-natal --version 0.4.0 $ react-native -v react-native-cli: 2.0.1 react-native: 0.43.4
コード
ジョイスティックのコードです。触れた場所によって、左上だと {:x -1 :y -1}、中心だと {x: 0 :y 0}、右上だと {:x 1 :y 0}のような値を、第1引数のon-moveに渡して実行します。
画面から手を離すと、第2引数のon-releaseを実行します。
(def ReactNative (js/require "react-native")) (def view (r/adapt-react-class (.-View ReactNative))) (def image (r/adapt-react-class (.-Image ReactNative))) (defn rate-x-y [p-x p-y view-x view-y view-w view-h] (let [harf-w (/ view-w 2) harf-h (/ view-h 2) rate-x (/ (- p-x view-x harf-w) harf-w) rate-y (/ (- p-y view-y harf-h) harf-h)] {:x rate-x :y rate-y})) (defn joystick [on-move on-release] (let [view-x (r/atom nil) view-y (r/atom nil) view-w 300 view-h 300 joystick-ref (r/atom nil) update-view-x-y #(.measure @joystick-ref (fn [fx fy w h px py] (reset! view-x px) (reset! view-y py))) action (fn [evt] (-> (rate-x-y (.-pageX (.-nativeEvent evt)) (.-pageY (.-nativeEvent evt)) @view-x @view-y view-w view-h) (on-move)))] (r/create-class {:reagent-render (fn [] [image {:source joystick-img :style {:resize-mode "cover" :background-color "#beb" :align-self "center"}} [view {:ref "joystickArea" :style {:width view-w :height view-h} :on-layout #(update-view-x-y) :on-start-should-set-responder (fn [] true) :on-move-should-set-responder (fn [] true) :on-responder-grant #(action %) :on-responder-move #(action %) :on-responder-release #(on-release)}]]) :component-did-mount #(reset! joystick-ref (-> (.-refs %) (.-joystickArea)))}))) (defn joystick-action [{:keys [x y]}] (prn :x x) (prn :y y)) (defn [] some-page .. [joystick joystick-action #(joystick-action {:x 0 :y 0})])
参考コミット
Add joystick
Add image for joystick
実装時の注意点: androidにおけるlocationXの不具合
react-native0.43.4のandroid環境では、on-responder-moveなどのイベントに含まれるnativeEventのlocationXとlocationYが更新されない不具合があります。[Android] onResponderMove nativeEvent locationX does not change
そのため、joystickの左上の座標をon-layoutで取得し、それを使ってpageXとpageYからlocationXとlocatoinYに相当する値を計算しています。
まとめ
viewのresponcer-moveを利用として、ジョイスティックを実現しました。locationXに関する不具合が解決すれば6行くらいコードを短くできますが、とりあえず欲しい機能を作れたので満足です。
共有する情報は以上です。
参考
Gesture Responder SystemReactNativeソースコードリーディング <View>
View
React-Native Tinder like cards
React Native: Getting the position of an element
[Orientation] Re-Layout on orientation change
0 件のコメント :
コメントを投稿