iT邦幫忙

2024 iThome 鐵人賽

DAY 15
0
自我挑戰組

30 天 vueuse 原始碼閱讀與實作系列 第 15

[Day 15] useDeviceOrientation & useScreenOrientation

  • 分享至 

  • xImage
  •  

這兩個 API 都跟行動裝置有關,先從 useDeviceOrientation 開始吧~

useDeviceOrientation

官方 Demo:https://vueuse.org/core/useDeviceOrientation/

Chrome DevTools

用電腦或 iOS 瀏覽器打開的話 alpha, beta, gamma 應該都會是 null。為了方便觀察,可以用 chrome 的開發者工具選擇 sernsor,會出現手機裝置可以讓我們自由的旋轉、傾斜(對截圖的裝置區域按住不放)。
https://ithelp.ithome.com.tw/upload/images/20240929/20169419LRsz2QPNea.png

source code

// src/compositions/useDeviceOrientation.js

import { ref } from 'vue'
import { defaultWindow } from '@/helper'
import { useSupported } from '@/compositions/useSupported'
import { useEventListener } from '@/compositions/useEventListener'

export function useDeviceOrientation(options = {}) {
  const { window = defaultWindow } = options
  const isSupported = useSupported(() => window && 'DeviceOrientationEvent' in window)

  const isAbsolute = ref(false)
  const alpha = ref(null)
  const beta = ref(null)
  const gamma = ref(null)

  if (window && isSupported.value) {
    useEventListener(window, 'deviceorientation', (event) => {
      isAbsolute.value = event.absolute
      alpha.value = event.alpha
      beta.value = event.beta
      gamma.value = event.gamma
    })
  }

  return {
    isSupported,
    isAbsolute,
    alpha,
    beta,
    gamma,
  }
}

isAbsolute 之後沒什麼用到,先跳過這個東西 XD 來看一下重點 alpha, beta, gamma

  • alpha (α): 繞 Z 軸旋轉的角度,範圍 0° 到 360°。想像將裝置平放在桌上,然後旋轉手機。
  • beta (β): 繞 X 軸旋轉的角度,範圍 -180° 到 180°。以 90 度為例:當裝置平放時為 0 度,豎直向上時為 90 度,豎直向下時為 -90 度。
  • gamma (γ): 繞 Y 軸旋轉的角度,範圍 -90° 到 90°。當裝置平放時為 0 度,向左傾斜時為負值,向右傾斜時為正值。

這三個數值是未來要實作 Day 7 提到的 useParallax 重要的關鍵。

GitHub PR:https://github.com/RhinoLee/30days_vue/pull/13/files

useScreenOrientation

官方 Demo:https://vueuse.org/core/useScreenOrientation/

Chrome DevTools

可以用下圖紅匡處的按鈕,來切換裝置的方向,但目前只有 portrait-primary(縱向模式)、landscape-primary(橫向模式)可切換。
https://ithelp.ithome.com.tw/upload/images/20240929/20169419CpnpoRPGSE.png

source code

// src/compositions/useScreenOrientation.js

import { ref } from 'vue'
import { defaultWindow } from '@/helper'
import { useSupported } from '@/compositions/useSupported'
import { useEventListener } from '@/compositions/useEventListener'

export function useScreenOrientation(options = {}) {
  const {
    window = defaultWindow,
  } = options

  const isSupported = useSupported(() => window && 'screen' in window && 'orientation' in window.screen)

  const screenOrientation = (isSupported.value ? window.screen.orientation : {})

  // portrait-primary, portrait-secondary, landscape-primary, or landscape-secondary
  const orientation = ref(screenOrientation.type)
  // document's current orientation angle.
  const angle = ref(screenOrientation.angle || 0)

  if (isSupported.value) {
    useEventListener(window, 'orientationchange', () => {
      orientation.value = screenOrientation.type
      angle.value = screenOrientation.angle
    })
  }

  const lockOrientation = (type) => {
    if (isSupported.value && typeof screenOrientation.lock === 'function')
      return screenOrientation.lock(type)

    return Promise.reject(new Error('Not supported'))
  }

  const unlockOrientation = () => {
    if (isSupported.value && typeof screenOrientation.unlock === 'function')
      screenOrientation.unlock()
  }

  return {
    isSupported,
    orientation,
    angle,
    lockOrientation,
    unlockOrientation,
  }
}

orientation:有四種方向,以下用圖文說明比較清楚:

  • portrait-primary:主要縱向模式
    https://ithelp.ithome.com.tw/upload/images/20240929/20169419Z277MiXkkZ.png
  • portrait-secondary:次要縱向模式
    https://ithelp.ithome.com.tw/upload/images/20240929/20169419t9rQXjDLkB.png
  • landscape-primary:主要橫向模式
    https://ithelp.ithome.com.tw/upload/images/20240929/20169419puL9oO1ZDD.png
  • landscape-secondary:次要橫向模式
    https://ithelp.ithome.com.tw/upload/images/20240929/2016941993qEBm6cFz.png

angle:document 目前的角度,像是如果 orientation 是 landscape-primary 模式,angle 就會是 90 度。

lockOrientationunlockOrientation: 這兩個主要是用來鎖定、解鎖方向的,這個目前支援度比較低,參考 caniuse

GitHub PR:https://github.com/RhinoLee/30days_vue/pull/14/files


useDeviceOrientation & useScreenOrientation 到這邊告一段落,明天終於可以開始看 Day 7 提到的 useParallax 了,怎麼好像繞了非常大圈 XD


上一篇
[Day 14] useMounted & useSupported
下一篇
[Day 16] useParallax - source code
系列文
30 天 vueuse 原始碼閱讀與實作30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言