张延森 3 years ago
parent
commit
8165b45e1e

+ 1
- 0
config/index.js View File

@@ -17,6 +17,7 @@ const config = {
17 17
   alias: {
18 18
     '@/': path.resolve(__dirname, '..', 'src/'),
19 19
     '@/components': path.resolve(__dirname, '..', 'src/components'),
20
+    '@/hooks': path.resolve(__dirname, '..', 'src/hooks'),
20 21
     '@/utils': path.resolve(__dirname, '..', 'src/utils'),
21 22
   },
22 23
   copy: {

+ 1
- 0
jsconfig.json View File

@@ -8,6 +8,7 @@
8 8
     "paths": {      
9 9
       "@/assets/*": ["./src/assets/*"],
10 10
       "@/components/*": ["./src/components/*"],
11
+      "@/hooks/*": ["./src/hooks/*"],
11 12
       "@/utils/*": ["./src/utils/*"],
12 13
     }
13 14
   }

+ 1
- 0
src/components/Counter/index.jsx View File

@@ -25,6 +25,7 @@ const ShakeCount = (props) => {
25 25
       })
26 26
 
27 27
       isReady.current = true
28
+      S.performAction(value)
28 29
     }
29 30
   }, [])
30 31
 

+ 0
- 53
src/components/Shake/index.jsx View File

@@ -1,53 +0,0 @@
1
-import { View, Canvas } from '@tarojs/components'
2
-import Taro, { useDidHide, useDidShow } from '@tarojs/taro'
3
-import { useCallback, useEffect, useMemo, useRef, useState } from 'react'
4
-import Counter from '@/components/Counter'
5
-import { throttle } from '@/utils'
6
-import newShake from '@/utils/shake'
7
-import S from '@/utils/shape-shifter'
8
-
9
-import './style.less'
10
-
11
-const { onShake } = newShake()
12
-
13
-const ShakeCount = (props) => {
14
-  const { className, onTimes } = props
15
-  const classNames = useMemo(() => [className, 'shake-count'].filter(Boolean).join(' '), [className])
16
-
17
-  const [times, setTimes] = useState(0)
18
-  const timesRef = useRef(times)
19
-
20
-  // eslint-disable-next-line react-hooks/exhaustive-deps
21
-  const handleShake = useCallback(throttle((times) => {
22
-    setTimes(times)
23
-
24
-    if (onTimes) {
25
-      onTimes(times)
26
-    }
27
-  }, 500, { trailing: true, immediate: true }), [])
28
-
29
-  useDidShow(() => {
30
-    Taro.startAccelerometer()
31
-
32
-    Taro.onAccelerometerChange((e) => {
33
-      onShake(e, () => {
34
-        timesRef.current += 1
35
-        console.log('---times: ', timesRef.current)
36
-        handleShake(timesRef.current)
37
-        // S.performAction(timesRef.current)
38
-      })
39
-    })
40
-  })
41
-
42
-  useDidHide(() => {
43
-    Taro.startAccelerometer()
44
-  })
45
-
46
-  return (
47
-    <View className={classNames}>
48
-      <Counter value={times} />
49
-    </View>
50
-  )
51
-}
52
-
53
-export default ShakeCount;

+ 0
- 17
src/components/Shake/style.less View File

@@ -1,17 +0,0 @@
1
-.shake-count {
2
-  width: 100%;
3
-  height: 100%;
4
-
5
-  canvas {
6
-    width: 100%;
7
-    height: 100%;
8
-    position: absolute;
9
-    top: 0;
10
-    left: 0;
11
-
12
-    &.canvas-shape {
13
-      top: -200vw;
14
-      left: -200vh;
15
-    }
16
-  }
17
-}

+ 33
- 0
src/hooks/useInterval.jsx View File

@@ -0,0 +1,33 @@
1
+import { useCallback, useEffect, useRef } from "react"
2
+
3
+/**
4
+ * 定时器
5
+ * 执行一系列的函数
6
+ * @param {*} interval 
7
+ * @returns
8
+ */
9
+export default function useInterval(interval) {
10
+
11
+  // 待执行函数列表
12
+  const fnListRef = useRef([])
13
+
14
+  // 暴露出一个方法来添加待执行函数
15
+  const push = useCallback((fn) => {
16
+    fnListRef.current.push(fn)
17
+
18
+    return () => {
19
+      const inx = fnListRef.current.indexOf(fn)
20
+      fnListRef.current.splice(inx)
21
+    }
22
+  }, [])
23
+
24
+  useEffect(() => {
25
+    const ticker = setInterval(() => {
26
+      console.log('-----------interval---------')
27
+      fnListRef.current.forEach(fn => fn())
28
+    }, interval)
29
+    return () => clearInterval(ticker)
30
+  }, [])
31
+
32
+  return [push]
33
+}

+ 22
- 0
src/pages/index/hooks/useCountDown.js View File

@@ -0,0 +1,22 @@
1
+import { useCallback, useRef, useState } from "react";
2
+
3
+export default function useCountDown() {
4
+
5
+  const [val, setVal] = useState()
6
+  const numRef = useRef()
7
+
8
+  const countDown = useCallback(() => {
9
+    if (numRef.current <= 0) {
10
+      return
11
+    }
12
+    numRef.current -= 1
13
+    setVal(numRef.current)
14
+  }, [])
15
+
16
+  const start = useCallback((startNum) => {
17
+    numRef.current = startNum
18
+    setVal(startNum)
19
+  }, [])
20
+
21
+  return [val, countDown, start]
22
+}

+ 69
- 0
src/pages/index/hooks/useShake.js View File

@@ -0,0 +1,69 @@
1
+
2
+import { useState, useRef, useMemo, useCallback, useEffect } from 'react'
3
+import Taro, { useDidHide, useDidShow } from '@tarojs/taro'
4
+import { throttle } from '@/utils'
5
+import newShake from '@/utils/shake'
6
+
7
+export default function useShake() {
8
+  const [times, setTimes] = useState(0)
9
+  const timesRef = useRef(times)
10
+  const isReadyRef = useRef(false)
11
+  const lastTimeRef = useRef()
12
+
13
+  const onShake = useMemo(() => newShake().onShake, [])
14
+
15
+  // eslint-disable-next-line react-hooks/exhaustive-deps
16
+  const handleShake = useCallback(throttle((val) => {
17
+    setTimes(val)
18
+  }, 1000, { trailing: true, immediate: true }), [])
19
+
20
+  const start = useCallback(() => {
21
+    isReadyRef.current = true
22
+    timesRef.current = 0
23
+    setTimes(0)
24
+  }, [])
25
+
26
+  const handleEndRef = useRef()
27
+  const onEnd = useCallback(callback => handleEndRef.current = callback, []) 
28
+
29
+  useEffect(() => {
30
+    const interval = setInterval(() => {
31
+      if (isReadyRef.current) {
32
+        const now = new Date()
33
+
34
+        // 超过 1s 就算停止摇动了
35
+        if (lastTimeRef.current && now - lastTimeRef.current >= 1000) {
36
+          if (handleEndRef.current) {
37
+            setTimes(timesRef.current)
38
+            handleEndRef.current()
39
+            lastTimeRef.current = undefined
40
+          }
41
+          isReadyRef.current = false
42
+        }
43
+      }
44
+    }, 1000)
45
+
46
+    return () => clearInterval(interval)
47
+  },[])
48
+  
49
+  useDidShow(() => {
50
+    Taro.startAccelerometer()
51
+
52
+    Taro.onAccelerometerChange((e) => {
53
+      if (isReadyRef.current) {
54
+        onShake(e, () => {
55
+          timesRef.current += 1
56
+          console.log('--->times: ', timesRef.current)
57
+          handleShake(timesRef.current)
58
+          lastTimeRef.current = new Date()
59
+        })
60
+      }
61
+    })
62
+  })
63
+
64
+  useDidHide(() => {
65
+    Taro.startAccelerometer()
66
+  })
67
+
68
+  return [times, start, onEnd]
69
+}

+ 56
- 4
src/pages/index/index.jsx View File

@@ -1,18 +1,70 @@
1
+
2
+import { useEffect, useMemo, useRef, useState } from 'react';
1 3
 import { View } from '@tarojs/components'
2
-import ShakeCount from '@/components/Shake'
4
+import Counter from '@/components/Counter'
3 5
 import { Button } from '@antmjs/vantui';
6
+import useInterval from '@/hooks/useInterval';
4 7
 import TopBar from './components/TopBar'
5
-
8
+import useCountDown from './hooks/useCountDown';
9
+import useShake from './hooks/useShake';
6 10
 import './index.less'
7 11
 
8 12
 const IndexPage = (props) => {
13
+  const modRef = useRef('ready')
14
+  const [num, setNum] = useState(0)
15
+  const [btnDisable, setBtnDisable] = useState(false)
16
+
17
+  // 定时器
18
+  const [add2TickerList] = useInterval(1000)
19
+
20
+  // 倒计时
21
+  const [count, countFn, startCount] = useCountDown();
22
+  useMemo(() => add2TickerList(countFn), [])
23
+
24
+  // 摇一摇
25
+  const [times, startShake, onShakeEnd] = useShake()
26
+  onShakeEnd(() => {
27
+    // 摇一摇结束
28
+    modRef.current = 'ready'
29
+    setBtnDisable(false)
30
+    // do something
31
+  })
32
+
33
+  const handleStart = () => {
34
+    modRef.current = 'countdown'
35
+    startCount(3)
36
+    setBtnDisable(true)
37
+  }
38
+
39
+  useEffect(() => {
40
+    if (modRef.current === 'countdown') {
41
+      setNum(count)
42
+    } else {
43
+      setNum(times)
44
+    }
45
+  }, [count, times])
46
+
47
+  useEffect(() => {
48
+    if (modRef.current === 'countdown') {
49
+      if (count === 0) {
50
+        modRef.current = 'shake'
51
+        startShake()
52
+      }
53
+    }
54
+  }, [count])
9 55
 
10 56
   return (
11 57
     <View className='page-wrapper page-index'>
12
-      <ShakeCount className='shake-bg' />
58
+      <Counter className='shake-bg' value={num} />
13 59
       <TopBar />
14 60
       <View style={{ width: '80vw', position: 'fixed', bottom: '2em', left: '10vw' }} >
15
-        <Button block round color='linear-gradient(to right, rgb(255, 96, 52), rgb(238, 10, 36))'>开 始</Button>
61
+        <Button
62
+          block
63
+          round
64
+          color='linear-gradient(to right, rgb(255, 96, 52), rgb(238, 10, 36))'
65
+          onClick={handleStart}
66
+          disabled={btnDisable}
67
+        >开 始</Button>
16 68
       </View>      
17 69
     </View>
18 70
   )