张延森 3 年之前
父節點
當前提交
5cf0690943
共有 5 個檔案被更改,包括 271 行新增142 行删除
  1. 81
    81
      src/components/Poster/Poster.jsx
  2. 84
    50
      src/components/Poster/index.jsx
  3. 6
    11
      src/components/Poster/sdk.js
  4. 72
    0
      src/components/Poster/useCanvas.js
  5. 28
    0
      src/utils/image.js

+ 81
- 81
src/components/Poster/Poster.jsx 查看文件

@@ -1,94 +1,94 @@
1
-import React, { useEffect, useRef, useState } from 'react'
2
-import Taro from '@tarojs/taro'
3
-import { Canvas, View } from '@tarojs/components'
4
-import { getConfig } from './config'
5
-import posterSDKFactory from './sdk'
1
+// import React, { useEffect, useRef, useState } from 'react'
2
+// import Taro from '@tarojs/taro'
3
+// import { Canvas, View } from '@tarojs/components'
4
+// import { getConfig } from './config'
5
+// import posterSDKFactory from './sdk'
6 6
 
7
-export default (props) => {
8
-  const { dataSource, onStart, onEnd, onError } = props
7
+// export default (props) => {
8
+//   const { dataSource, onStart, onEnd, onError } = props
9 9
 
10
-  const [sdk, setSDK] = useState()
11
-  const processing = useRef(false)
10
+//   const [sdk, setSDK] = useState()
11
+//   const processing = useRef(false)
12 12
 
13
-  const config = useRef()
14
-  config.current = getConfig()
13
+//   const config = useRef()
14
+//   config.current = getConfig()
15 15
 
16
-  useEffect(() => {
17
-    Taro.nextTick(() => {
18
-      posterSDKFactory('#canvas-poster').then((res) => {
19
-        res.initCanvas({
20
-          ...config.current,
21
-        })
22
-        setSDK(res)
23
-      })
24
-    })
25
-  }, [])
16
+//   useEffect(() => {
17
+//     Taro.nextTick(() => {
18
+//       posterSDKFactory('#canvas-poster').then((res) => {
19
+//         res.initCanvas({
20
+//           ...config.current,
21
+//         })
22
+//         setSDK(res)
23
+//       })
24
+//     })
25
+//   }, [])
26 26
 
27
-  useEffect(() => {
28
-    const { poster, miniCode, name, avatar, desc = '长按识别在线看房',  } = dataSource || {}
29
-    if (sdk && poster && !processing.current) {
30
-      onStart()
31
-      processing.current = true
32
-      const conf = config.current
27
+//   useEffect(() => {
28
+//     const { poster, miniCode, name, avatar, desc = '长按识别在线看房',  } = dataSource || {}
29
+//     if (sdk && poster && !processing.current) {
30
+//       onStart()
31
+//       processing.current = true
32
+//       const conf = config.current
33 33
       
34
-      sdk.onError((err) => {
35
-        if (onError) {
36
-          onError(err)
37
-        } else {
38
-          console.error(err)
39
-        }
40
-      })
34
+//       sdk.onError((err) => {
35
+//         if (onError) {
36
+//           onError(err)
37
+//         } else {
38
+//           console.error(err)
39
+//         }
40
+//       })
41 41
 
42
-      // 名称
43
-      sdk.darwText(name, conf.name)
44
-      // 小程序码
45
-      sdk.darwText(desc, conf.desc)
42
+//       // 名称
43
+//       sdk.darwText(name, conf.name)
44
+//       // 小程序码
45
+//       sdk.darwText(desc, conf.desc)
46 46
 
47
-      let cnt = 0
48
-      // 封面
49
-      sdk.getImage(poster).then((posterImg) => {
50
-        sdk.drawImage(posterImg, conf.poster)
51
-        cnt += 1
52
-      }).catch(() => cnt += 1)
53
-      // 头像
54
-      sdk.getImage(avatar).then((avatarImg) => {
55
-        sdk.drawImage(avatarImg, conf.avatar)
56
-        cnt += 1
57
-      }).catch(() => cnt += 1)
58
-      // 小程序码
59
-      sdk.getImage(miniCode).then((miniCodeImg) => {
60
-        sdk.drawImage(miniCodeImg, conf.miniCode)
61
-        cnt += 1
62
-      }).catch(() => cnt += 1)
47
+//       let cnt = 0
48
+//       // 封面
49
+//       sdk.getImage(poster).then((posterImg) => {
50
+//         sdk.drawImage(posterImg, conf.poster)
51
+//         cnt += 1
52
+//       }).catch(() => cnt += 1)
53
+//       // 头像
54
+//       sdk.getImage(avatar).then((avatarImg) => {
55
+//         sdk.drawImage(avatarImg, conf.avatar)
56
+//         cnt += 1
57
+//       }).catch(() => cnt += 1)
58
+//       // 小程序码
59
+//       sdk.getImage(miniCode).then((miniCodeImg) => {
60
+//         sdk.drawImage(miniCodeImg, conf.miniCode)
61
+//         cnt += 1
62
+//       }).catch(() => cnt += 1)
63 63
 
64
-      const ticker = setInterval(() => {
65
-        if (cnt >= 3) {
66
-          // 图片全部处理完
67
-          // // console.log('--------download--------->')
68
-          // sdk.download('canvas-poster').then((tempPath) => {
69
-          //   onEnd(tempPath, sdk)
70
-          //   clearInterval(ticker)
71
-          // }).catch(() => {
72
-          //   clearInterval(ticker)
73
-          // })
64
+//       const ticker = setInterval(() => {
65
+//         if (cnt >= 3) {
66
+//           // 图片全部处理完
67
+//           // // console.log('--------download--------->')
68
+//           // sdk.download('canvas-poster').then((tempPath) => {
69
+//           //   onEnd(tempPath, sdk)
70
+//           //   clearInterval(ticker)
71
+//           // }).catch(() => {
72
+//           //   clearInterval(ticker)
73
+//           // })
74 74
 
75
-          // const image = sdk.toDataURL();
76
-          // Taro.getImageInfo({
77
-          //   src: image,
78
-          //   success: (res => {
79
-          //     onEnd(res.path, sdk)
80
-          //     clearInterval(ticker)
81
-          //   })
82
-          // })
75
+//           // const image = sdk.toDataURL();
76
+//           // Taro.getImageInfo({
77
+//           //   src: image,
78
+//           //   success: (res => {
79
+//           //     onEnd(res.path, sdk)
80
+//           //     clearInterval(ticker)
81
+//           //   })
82
+//           // })
83 83
 
84
-          const image = sdk.toDataURL()
85
-          onEnd(image, sdk)
86
-          clearInterval(ticker)
87
-        }
88
-      }, 200);
84
+//           const image = sdk.toDataURL()
85
+//           onEnd(image, sdk)
86
+//           clearInterval(ticker)
87
+//         }
88
+//       }, 200);
89 89
 
90
-    }
91
-  }, [sdk, dataSource, onStart, onEnd, onError])
90
+//     }
91
+//   }, [sdk, dataSource, onStart, onEnd, onError])
92 92
 
93
-  return <View style={{ width: '1px', height: '1px' }}><Canvas type='2d' id='canvas-poster' /></View>
94
-}
93
+//   return <View style={{ width: '1px', height: '1px' }}><Canvas type='2d' id='canvas-poster' /></View>
94
+// }

+ 84
- 50
src/components/Poster/index.jsx 查看文件

@@ -1,9 +1,10 @@
1
-import React, { useRef, useState } from 'react'
1
+import React, { useEffect, useRef, useState } from 'react'
2 2
 import Taro from '@tarojs/taro'
3
-import { View, Image, Button } from '@tarojs/components'
3
+import { View, Image, Button, Canvas } from '@tarojs/components'
4 4
 import Spin2 from '@/components/Spin/Spin2'
5
-import { save2Album } from '@/utils/image'
6
-import Poster from './Poster'
5
+import { save2Album, base64ToFile } from '@/utils/image'
6
+// import Poster from './Poster'
7
+import useCanvas from './useCanvas'
7 8
 import './style.scss'
8 9
 
9 10
 export default (props) => {
@@ -19,13 +20,19 @@ export default (props) => {
19 20
   const [img, setImg] = useState()
20 21
   const [processing, setProcessing] = useState(false)
21 22
   const [loading, setLoading] = useState(false)
22
-  const sdkRef = useRef()
23
+  const [canvasInited, setCanvasInited] = useState(false)
24
+  const posterRender = useRef()
23 25
 
24
-  const handlePoster = (url, sdk) => {
25
-    setImg(url)
26
-    setProcessing(false)
27
-    sdkRef.current = sdk
28
-  }
26
+  useCanvas('canvas-poster', (fn) => {
27
+    posterRender.current = fn
28
+    setCanvasInited(true)
29
+  })
30
+
31
+  // const handlePoster = (url, sdk) => {
32
+  //   setImg(url)
33
+  //   setProcessing(false)
34
+  //   sdkRef.current = sdk
35
+  // }
29 36
 
30 37
   const handleSave = () => {
31 38
     if (!img) {
@@ -38,57 +45,84 @@ export default (props) => {
38 45
 
39 46
     // 保存到相册
40 47
     setLoading(true)
41
-    // save2Album(img).then(() => {
42
-    //   setLoading(false)
43
-    //   onSuccess()
44
-    //   Taro.showToast({ title: '保存成功', icon: 'none' })
45
-    // }, () => setLoading(false))
46
-    sdkRef.current.download().then((tempPath) => {
47
-      console.log('------poster----tempPath---', tempPath, new Date().valueOf())
48
+    save2Album(img).then(() => {
49
+      setLoading(false)
50
+      onSuccess()
51
+      Taro.showToast({ title: '保存成功', icon: 'none' })
52
+    }, () => setLoading(false))
48 53
 
49
-      Taro.previewImage({
50
-        urls: [tempPath]
51
-      })
54
+    // sdkRef.current.download().then((tempPath) => {
55
+    //   console.log('------poster----tempPath---', tempPath, new Date().valueOf())
52 56
 
53
-      // save2Album(tempPath).then(() => {
54
-      //   setLoading(false)
55
-      //   onSuccess()
56
-      //   Taro.showToast({ title: '保存成功', icon: 'none' })
57
-      // }, () => setLoading(false))
58
-    }).catch((err) => {
59
-      setLoading(false)
60
-      console.error(err)
61
-      const message = err.errMsg || err.message || err
62
-      Taro.showToast({
63
-        title: message,
64
-        icon: 'none',
65
-      })
66
-    })
57
+    //   Taro.previewImage({
58
+    //     urls: [tempPath]
59
+    //   })
60
+
61
+    //   // save2Album(tempPath).then(() => {
62
+    //   //   setLoading(false)
63
+    //   //   onSuccess()
64
+    //   //   Taro.showToast({ title: '保存成功', icon: 'none' })
65
+    //   // }, () => setLoading(false))
66
+    // }).catch((err) => {
67
+    //   setLoading(false)
68
+    //   console.error(err)
69
+    //   const message = err.errMsg || err.message || err
70
+    //   Taro.showToast({
71
+    //     title: message,
72
+    //     icon: 'none',
73
+    //   })
74
+    // })
67 75
   }
68 76
 
69 77
   const handleImage = (e) => {
70 78
     Taro.previewImage({ current: img, urls: [img], showmenu: true })
71 79
   }
72 80
 
81
+  useEffect(() => {
82
+    if (dataSource && canvasInited) {
83
+      const getPoster = posterRender.current
84
+      setProcessing(true)
85
+      getPoster(dataSource).then((image) => {
86
+        // 生成临时文件
87
+        const base64 = image.split('base64,')[1]
88
+        base64ToFile(base64).then((tmpFile) => {
89
+          setImg(tmpFile)
90
+          setProcessing(false)
91
+        }).catch((err) => {
92
+          setProcessing(false)
93
+          Taro.showToast({
94
+            title: err.errMsg,
95
+            icon: 'none',
96
+          })
97
+        })
98
+      }).catch(() => {
99
+        setProcessing(false)
100
+      })
101
+    }
102
+  }, [dataSource, canvasInited])
103
+
73 104
   return (
74 105
     // <Modal title={title} visible={show} onClose={onClose}>
75 106
     // eslint-disable-next-line react/jsx-no-undef
76
-    <page-modal show={show} position='bottom' onClose={onClose} height='70vh'>
77
-      <View className='modal-poster'>
78
-        <View className='modal-poster-img-box'>
79
-          <view>
80
-            {
81
-              !processing
82
-                ? <Image src={img} mode='scaleToFill' className='centerLabel' onClick={handleImage} />
83
-                : <Spin2 className='centerLabel' spinning={processing} size={32} />
84
-            }
85
-          </view>
107
+    <>
108
+      <page-modal show={show} position='bottom' onClose={onClose} height='70vh'>
109
+        <View className='modal-poster'>
110
+          <View className='modal-poster-img-box'>
111
+            <view>
112
+              {
113
+                !processing
114
+                  ? <Image src={img} mode='scaleToFill' className='centerLabel' onClick={handleImage} />
115
+                  : <Spin2 className='centerLabel' spinning={processing} size={32} />
116
+              }
117
+            </view>
118
+          </View>
119
+          <Button className='modal-poster-action' onClick={handleSave} disabled={!img} loading={loading}>
120
+            {btnText}
121
+          </Button>
86 122
         </View>
87
-        <Button className='modal-poster-action' onClick={handleSave} disabled={!img} loading={loading}>
88
-          {btnText}
89
-        </Button>
90
-      </View>
91
-      <Poster dataSource={dataSource} onStart={() => setProcessing(true)} onEnd={handlePoster} />
92
-    </page-modal>
123
+        {/* <Poster dataSource={dataSource} onStart={() => setProcessing(true)} onEnd={handlePoster} /> */}
124
+      </page-modal>
125
+      <View style={{ width: '1px', height: '1px' }}><Canvas type='2d' id='canvas-poster' /></View>
126
+    </>
93 127
   )
94 128
 }

+ 6
- 11
src/components/Poster/sdk.js 查看文件

@@ -1,7 +1,5 @@
1 1
 import Taro from '@tarojs/taro'
2 2
 
3
-const sysInfo = Taro.getSystemInfoSync()
4
-
5 3
 export default function factory(selector) {
6 4
   return new Promise((resolve) => {
7 5
     const query = Taro.createSelectorQuery()
@@ -16,7 +14,7 @@ export default function factory(selector) {
16 14
 
17 15
 export function posterSDK(canvas) {
18 16
   let dpr;
19
-  let onError = (err) => console.error(err);
17
+  let onError = (...err) => console.error(...err);
20 18
   const ctx = canvas.getContext('2d')
21 19
 
22 20
   /**
@@ -100,12 +98,10 @@ export function posterSDK(canvas) {
100 98
 
101 99
   /**
102 100
    * canvas 转为图片
103
-   * @param {*} type 
104
-   * @param {*} encoderOptions 
105 101
    * @returns 
106 102
    */
107
-  function toDataURL(type = 'image/jpeg', encoderOptions = 0.8) {
108
-    return canvas.toDataURL(type, encoderOptions)
103
+  function toDataURL() {
104
+    return canvas.toDataURL()
109 105
   }
110 106
 
111 107
   /**
@@ -113,10 +109,9 @@ export function posterSDK(canvas) {
113 109
    * @param {*} options 
114 110
    * @returns 
115 111
    */
116
-  function download(canvasId) {
112
+  function download() {
117 113
     return new Promise((resovle, reject) => {
118 114
       Taro.canvasToTempFilePath({
119
-        canvasId,
120 115
         canvas,
121 116
         fileType: 'png',
122 117
         quality: 0.9,
@@ -124,8 +119,8 @@ export function posterSDK(canvas) {
124 119
         y: 0,
125 120
         width: canvas.width,
126 121
         height: canvas.height,
127
-        destWidth: canvas.width,
128
-        destHeight: canvas.height,
122
+        destWidth: canvas.width * 750 / dpr,
123
+        destHeight: canvas.height * 750 / dpr,
129 124
         success: (res) => resovle(res.tempFilePath),
130 125
         fail: (err) => {
131 126
           onError('exportImage', err)

+ 72
- 0
src/components/Poster/useCanvas.js 查看文件

@@ -0,0 +1,72 @@
1
+import React, { useCallback, useEffect, useMemo, useRef } from 'react'
2
+import Taro from '@tarojs/taro'
3
+
4
+import { getConfig } from './config'
5
+import posterSDKFactory from './sdk'
6
+
7
+export default (canvasId, callback) => {
8
+
9
+  const config = useMemo(() => getConfig(), [])
10
+  const sdkRef = useRef()
11
+  const cbRef = useRef()
12
+
13
+  cbRef.current = callback
14
+
15
+  const getPoster = useCallback((dataSource) => {
16
+    const sdk = sdkRef.current
17
+    if (!sdk) {
18
+      return Promise.reject('系统未初始化完成, 请重试')
19
+    }
20
+
21
+    return new Promise((resolve, reject) => {
22
+      const { poster, miniCode, name, avatar, desc = '长按识别在线看房',  } = dataSource || {}
23
+
24
+      // 名称
25
+      sdk.darwText(name, config.name)
26
+      // 小程序码
27
+      sdk.darwText(desc, config.desc)
28
+
29
+      let cnt = 0
30
+      // 封面
31
+      sdk.getImage(poster).then((posterImg) => {
32
+        sdk.drawImage(posterImg, config.poster)
33
+        cnt += 1
34
+      }).catch(() => cnt += 1)
35
+      // 头像
36
+      sdk.getImage(avatar).then((avatarImg) => {
37
+        sdk.drawImage(avatarImg, config.avatar)
38
+        cnt += 1
39
+      }).catch(() => cnt += 1)
40
+      // 小程序码
41
+      sdk.getImage(miniCode).then((miniCodeImg) => {
42
+        sdk.drawImage(miniCodeImg, config.miniCode)
43
+        cnt += 1
44
+      }).catch(() => cnt += 1)
45
+
46
+      const ticker = setInterval(() => {
47
+        if (cnt >= 3) {
48
+          const image = sdk.toDataURL()
49
+          clearInterval(ticker)
50
+          resolve(image)
51
+        }
52
+      }, 200);
53
+    })
54
+  }, [config])
55
+
56
+  useEffect(() => {
57
+    Taro.nextTick(() => {
58
+      posterSDKFactory(`#${canvasId}`).then((sdk) => {
59
+        sdk.initCanvas({
60
+          ...config,
61
+        })
62
+        sdkRef.current = sdk
63
+        
64
+        if (cbRef.current) {
65
+          cbRef.current(getPoster)
66
+        }
67
+      })
68
+    })
69
+  }, [canvasId, config, getPoster])
70
+
71
+  return;
72
+}

+ 28
- 0
src/utils/image.js 查看文件

@@ -32,6 +32,34 @@ export function getImgURL(img) {
32 32
   return `${host}${img}`;
33 33
 }
34 34
 
35
+/**
36
+ * base64 转文件
37
+ * @param {*} base64Str 
38
+ * @returns 
39
+ */
40
+export function base64ToFile(base64Str) {
41
+  return new Promise((resolve, reject) => {
42
+    const fileName = (new Date()).valueOf() + '-' + Math.random().toString(36).substring(2) + '.png'
43
+    const filePath = Taro.env.USER_DATA_PATH + '/' + fileName
44
+  
45
+    Taro.getFileSystemManager().writeFile({
46
+      filePath,
47
+      data: base64Str,
48
+      encoding: 'base64',
49
+      success: () => {
50
+        resolve(filePath)
51
+      },
52
+      fail: (err) => {
53
+        console.error(err)
54
+        reject(err)
55
+      },
56
+      complete: (res) => {
57
+        console.log('-----writeFile---', filePath, res)
58
+      }
59
+    })
60
+  })
61
+}
62
+
35 63
 /**
36 64
  * 保存到相册
37 65
  * @param {*} tempPath