From 8b8330dda9fbbc02c9f75c44dbf4369485f66a63 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=88=98=E5=AE=87=E7=90=B3?= Date: Wed, 3 Mar 2021 20:25:44 +0800 Subject: [PATCH 1/7] =?UTF-8?q?feat:=20=E6=B7=BB=E5=8A=A0audio=E7=BB=84?= =?UTF-8?q?=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../discuz-design/components/audio/README.md | 22 +++ .../audio/__examples__/mini/index.jsx | 8 + .../audio/__examples__/web/base.tsx | 10 ++ .../audio/__examples__/web/border.tsx | 21 +++ .../audio/__examples__/web/custom.tsx | 24 +++ .../audio/__examples__/web/image.tsx | 55 ++++++ .../components/audio/adapters/index.ts | 14 ++ .../components/audio/adapters/mini.ts | 1 + .../components/audio/adapters/web.ts | 1 + .../discuz-design/components/audio/index.tsx | 21 +++ .../components/audio/interface.ts | 19 ++ .../audio/layouts/images/loading.gif | Bin 0 -> 3796 bytes .../audio/layouts/images/paused.png | Bin 0 -> 583 bytes .../components/audio/layouts/images/play.png | Bin 0 -> 583 bytes .../components/audio/layouts/index.tsx | 13 ++ .../components/audio/layouts/mini/index.tsx | 167 ++++++++++++++++++ .../components/audio/layouts/mini/utils.js | 44 +++++ .../components/audio/layouts/web/index.tsx | 0 .../components/audio/layouts/web/utils.js | 55 ++++++ .../components/audio/layouts/web/web.js | 133 ++++++++++++++ .../components/audio/styles/index.scss | 39 ++++ .../components/audio/styles/mixin.scss | 0 .../components/audio/styles/var.scss | 22 +++ .../discuz-design/site/mini/src/app.config.js | 3 +- .../site/mini/src/componentList.json | 3 + .../site/mini/src/pages/audio/index.config.js | 3 + .../site/mini/src/pages/audio/index.jsx | 22 +++ packages/discuz-design/styles/index.scss | 1 + 28 files changed, 700 insertions(+), 1 deletion(-) create mode 100644 packages/discuz-design/components/audio/README.md create mode 100644 packages/discuz-design/components/audio/__examples__/mini/index.jsx create mode 100644 packages/discuz-design/components/audio/__examples__/web/base.tsx create mode 100644 packages/discuz-design/components/audio/__examples__/web/border.tsx create mode 100644 packages/discuz-design/components/audio/__examples__/web/custom.tsx create mode 100644 packages/discuz-design/components/audio/__examples__/web/image.tsx create mode 100644 packages/discuz-design/components/audio/adapters/index.ts create mode 100644 packages/discuz-design/components/audio/adapters/mini.ts create mode 100644 packages/discuz-design/components/audio/adapters/web.ts create mode 100644 packages/discuz-design/components/audio/index.tsx create mode 100644 packages/discuz-design/components/audio/interface.ts create mode 100644 packages/discuz-design/components/audio/layouts/images/loading.gif create mode 100644 packages/discuz-design/components/audio/layouts/images/paused.png create mode 100644 packages/discuz-design/components/audio/layouts/images/play.png create mode 100644 packages/discuz-design/components/audio/layouts/index.tsx create mode 100644 packages/discuz-design/components/audio/layouts/mini/index.tsx create mode 100644 packages/discuz-design/components/audio/layouts/mini/utils.js create mode 100644 packages/discuz-design/components/audio/layouts/web/index.tsx create mode 100644 packages/discuz-design/components/audio/layouts/web/utils.js create mode 100644 packages/discuz-design/components/audio/layouts/web/web.js create mode 100644 packages/discuz-design/components/audio/styles/index.scss create mode 100644 packages/discuz-design/components/audio/styles/mixin.scss create mode 100644 packages/discuz-design/components/audio/styles/var.scss create mode 100644 packages/discuz-design/site/mini/src/pages/audio/index.config.js create mode 100644 packages/discuz-design/site/mini/src/pages/audio/index.jsx diff --git a/packages/discuz-design/components/audio/README.md b/packages/discuz-design/components/audio/README.md new file mode 100644 index 00000000..39381396 --- /dev/null +++ b/packages/discuz-design/components/audio/README.md @@ -0,0 +1,22 @@ +# Card + +## 组件说明 +基础的容器组件,可以容纳任意内容。 + +## 示例 + +### WEB示例 +[基础用法](./__examples__/web/base.tsx) +[自定义头尾](./__examples__/web/custom.tsx) +[带边框](./__examples__/web/border.tsx) +[图片展示](./__examples__/web/image.tsx) + +### 小程序示例 +[基础用法](./__examples__/mini/base.tsx) +[自定义头尾](./__examples__/mini/custom.tsx) +[带边框](./__examples__/mini/border.tsx) +[图片展示](./__examples__/mini/image.tsx) + +## API参数 +[API参数](./interface.ts) + diff --git a/packages/discuz-design/components/audio/__examples__/mini/index.jsx b/packages/discuz-design/components/audio/__examples__/mini/index.jsx new file mode 100644 index 00000000..32db2ca3 --- /dev/null +++ b/packages/discuz-design/components/audio/__examples__/mini/index.jsx @@ -0,0 +1,8 @@ +import React from "react"; +import { View, Text } from "@tarojs/components"; +import CustomAudio from '../../layouts/mini/index'; + +export default function FlexExample() { + return +} + diff --git a/packages/discuz-design/components/audio/__examples__/web/base.tsx b/packages/discuz-design/components/audio/__examples__/web/base.tsx new file mode 100644 index 00000000..2c65874b --- /dev/null +++ b/packages/discuz-design/components/audio/__examples__/web/base.tsx @@ -0,0 +1,10 @@ +import Card from '../../index'; +import React from 'react'; + +export default function Example1() { + return ( + +

描述内容

+
+ ); +} diff --git a/packages/discuz-design/components/audio/__examples__/web/border.tsx b/packages/discuz-design/components/audio/__examples__/web/border.tsx new file mode 100644 index 00000000..b45589a9 --- /dev/null +++ b/packages/discuz-design/components/audio/__examples__/web/border.tsx @@ -0,0 +1,21 @@ +import Card from '../../index'; +import React from 'react'; +import Button from '../../../button/index'; + +export default function Example1() { + return ( + + 卡片名称 + + + } + > +

描述内容

+
+ ); +} diff --git a/packages/discuz-design/components/audio/__examples__/web/custom.tsx b/packages/discuz-design/components/audio/__examples__/web/custom.tsx new file mode 100644 index 00000000..da804380 --- /dev/null +++ b/packages/discuz-design/components/audio/__examples__/web/custom.tsx @@ -0,0 +1,24 @@ +import Card from '../../index'; +import React from 'react'; +import Icon from '../../../icon/index'; +import Button from '../../../button/index'; + +export default function Example1() { + return ( + + + + + + + } + footer={} + > +

描述内容

+
+ ); +} diff --git a/packages/discuz-design/components/audio/__examples__/web/image.tsx b/packages/discuz-design/components/audio/__examples__/web/image.tsx new file mode 100644 index 00000000..8ae03400 --- /dev/null +++ b/packages/discuz-design/components/audio/__examples__/web/image.tsx @@ -0,0 +1,55 @@ +import Card from '../../index'; +import React from 'react'; + +export default function Example1() { + const footer = ( +
+ 下载 + + 查看 + +
+ ); + + return ( + <> + 设置fullBody来铺满内容区域} footer={footer}> + bg + + + + } + footer={footer} + > + 设置fullHeader来铺满头部区域 + + + 标题} + footer={ + bg + } + > + 设置fullFooter来铺满底部区域 + + + ); +} diff --git a/packages/discuz-design/components/audio/adapters/index.ts b/packages/discuz-design/components/audio/adapters/index.ts new file mode 100644 index 00000000..0c254ebe --- /dev/null +++ b/packages/discuz-design/components/audio/adapters/index.ts @@ -0,0 +1,14 @@ +import { baseAdapterFactory } from '../../../extends/baseAdapter'; + +export const LogicalAdapter = baseAdapterFactory({ + defaultAdapter: {}, + adapterImplement() { + if (process.env.DISCUZ_ENV === 'web') { + return require('./web').WebAdapter; + } + + if (process.env.DISCUZ_ENV === 'mini') { + return require('./mini').MiniAdapter; + } + }, +}); diff --git a/packages/discuz-design/components/audio/adapters/mini.ts b/packages/discuz-design/components/audio/adapters/mini.ts new file mode 100644 index 00000000..a09c6698 --- /dev/null +++ b/packages/discuz-design/components/audio/adapters/mini.ts @@ -0,0 +1 @@ +export const MiniAdapter = {}; diff --git a/packages/discuz-design/components/audio/adapters/web.ts b/packages/discuz-design/components/audio/adapters/web.ts new file mode 100644 index 00000000..efb906fd --- /dev/null +++ b/packages/discuz-design/components/audio/adapters/web.ts @@ -0,0 +1 @@ +export const WebAdapter = {}; diff --git a/packages/discuz-design/components/audio/index.tsx b/packages/discuz-design/components/audio/index.tsx new file mode 100644 index 00000000..e8a85db6 --- /dev/null +++ b/packages/discuz-design/components/audio/index.tsx @@ -0,0 +1,21 @@ +import React from 'react'; +import { baseComponentFactory } from '../../extends/baseComponent'; +import { ViewAdapter } from './layouts/index'; +import { LogicalAdapter } from './adapters/index'; +import { CardProps } from './interface'; + +interface CardState {} + +interface CardLayoutProps {} + +interface CardAdapter {} + +export default class Card extends baseComponentFactory({ + viewAdapter: ViewAdapter, + logicalAdapter: LogicalAdapter, +}) { + render() { + const { RenderComponent } = this; + return {this.props.children}; + } +} diff --git a/packages/discuz-design/components/audio/interface.ts b/packages/discuz-design/components/audio/interface.ts new file mode 100644 index 00000000..c5d7ffe6 --- /dev/null +++ b/packages/discuz-design/components/audio/interface.ts @@ -0,0 +1,19 @@ +import { StyledProps } from 'utils/_type/StyledProps'; + +export interface StateInterface { + audioCtx: Taro.InnerAudioContext + audioImg: string + currentTime: number + duration: number +} + +export interface PropsInterface { + audioSrc: string +} + +export interface CustomAudio extends StyledProps { + /** + * 卡片主体内容 + */ + audioSrc: string +} diff --git a/packages/discuz-design/components/audio/layouts/images/loading.gif b/packages/discuz-design/components/audio/layouts/images/loading.gif new file mode 100644 index 0000000000000000000000000000000000000000..6eae6f6db9047e42d54930b74d21bd8089dfe7c0 GIT binary patch literal 3796 zcmZvfcR1VazsDod9z`F!wi>Nn6fLD%YHvEURc+BlOO2|gs1++lj3PFPm4t*CF=Edc z5wp~a+M_l#I-KbFo#*Luo%6k~>-)W~`@j2jecrG4{na>G*eM!Q zqHi0`-NWWMy&$f>tQ$^0Z3IhES}fDAaePDlSed3x8CeIjdzrp@CFFN2fCmz+5b781 z>J=pw?HL>ACisCpEGapKKaDjEn)&`CGK4Q9KO$1TfF~E1^%w&yj43DB@@AjL))XNm zOVWwWEe`eVIUSuSv{uhwWqq~YtPPA!BmJ#oL(Id}t_qGS5*!R%1IiQ+s&Gs?y%t(u zm)Mf|X8lxck>9~S<+|tIs4EXCCa964w=KS_p?I3%xgsY}_Svs+`__;f6T;hogoAnPn13fQJ$_nR2CVh-xD;W`q zylBLb1+iI%proo;KnOe9bWy8bKxD`LuP%8&`|*m?fZ@~GCPlS?eJma zyXjhvyD1kAUr%>(rY^!7XXLy^JbA(LfzmE~A)#S>LG0l7QBR@15&lZvKD;rkajGz$ z43S$H3|k%+#ht@kQd-7FV9e5F#3`KTsnkdb!WLXKVY-v#Zv;2Zu?g=y@!rM8?J@0u;N1rmcwvM-zOarKF|hcRBCXOMEwX^1<)jWnt1 z(*gbiN`nUK25lW1l2zbPq0_J+9XmnxCMQe4&Y)r)UMf1O<6tr_8%};JSp9ODAAu9u za3C-^f@aKdHpA|`HK}kTmqFO>%Px0<7Ge*mCvMt{eQzUGlwhqArx8o}!tc5t1$#i& z2A}ct5%#t85BTu(C6v*F(F+zG_%`ZeOx(wKkx0MP@QV<*94HT@9weEcua;9#Sg2AY ziYMSqqzFW`jS#UWi@%|tXB)(R8XiH7vW`!7^?n&3%~Dzx z+R4i+d8-?nTiZLk-}d$o4iD*n{yGAHfXd>Ke@QD>IwG0_J_;F~>vcso2c2PI z@0J8vX#Ii39KcFT*fe10{9Sz@&n-hj{h+qNk+2YJs5K)bp2;819FUUmB0UR%%+ATp%SWLx(jY9Z zs2E>-sid4xBv(;QC?wWZiq|)RYMY5wZ53r5B?Uc{-oE~U!68NZ5&GQE0k>#wV8>l2$>BRjh*yI<}ee*dw5Fp^-*9iCP3CVSq};1AK51J3^kz|wJZ z%8>vCwa#YU>b+SKdbX;tXI|mxYJ2Q=EBw`u<(>mobu${B@*MHZ0kvWmQ96W_XaUZf zsaqzW3KY6lz3Qim!6tI46q^7q@@wK)X@yVEqrUZR4qukDn@2z|e{WBShg*n?11&nR z=$P2JkBp#1&~tdola%x%+l*rb4|5QC`588tfXU_;>E(ehEA#7*X4iTaHyW|ZF{LaL2Dh`fMZxL)*Pgf7!_C zM;-nuvHU&dpz5e0%hf=ZFPfC&-r=N{*^BaEWW9G{aQJPipmY5Q?&J?HeUfb{$ka+{ z#Q7c9qeRNm-S2{DJ-4?#{j9tK^+2H@6+fM@uyC+;RFt|$Y+R_OQz9Ii{FaR#K`)S& zq-Dd0MCRn0V=(-=c_u{#c&uqTqOj7qI=cp5RV`Lh)*{+gN9w3GsHa^aDBa{Vqu#zw z{m-MrgXQvLx)YO4<3sati(jT^Zp=xoYi({(b#|9wvrBRdKUO_W?DveKAwHh0otBFs z2)%BRl&AbV|xeKMk&?s#;)3!=es+q z9ccoknVSZz-X0vF5D<^=I~fx;$b;a}5NNn%bPQWu97lMBZZuCyXuPi>9Dxi=OV5Px zqA>-znps6?zQXI}C}d@VIz2&@Q;JxPA{Oy1g?jxVOJ5I&))(Db_rb-{sX!PUS@?J%8|#UJZKM ziL+IbN&XiJ#cBCp?XXMN0)s@{XCq#ULxYUb!he(w)4w>G#Z=O!Mzw-eel*n{b<-h3 z=FAMvPuqR-7t&gU67Fciq+2etwP*@T3JhDTUM$8g2PaYsZN z(>R62`VrFv&A^ zpg8a}PO8@e(?r~JA_K*vuFk~%5iZc*;o4=;9RIa}reR8IBR~8#H56sz5cpI&y)d^< zN5-6nX&1bHK={AmGSWDWgJ77uhEgi03RO5xM$6A_B*)1W(K+v_;jRskzo~!2QWw7a z_y@dG2ZjLkyl8`@>v26YQpZ^Kw{fCP;glz ziJ5Gt;VbW+WmEjZ)O-}JWl+Cc2HVw$FYL?tFq0&=#X|jyfz2~acZMEa2uM96pv;*1 zm-nZ~;(tgM@jsF!&?M{GxBiC9mqlgs2=xC*)&ZCZ{715n5g9be-p@x_VRCO_kwwLD zbZKHCA+w~^hM-8-KzF7_uCb8|d%3NRGyhswI~lJ=YnqB1Lk;$$O?DHLwiDws)X~|Y zCv(#a^Q&K%);2eK7k9sP?RRhO?HnAA4Uz}mJi zx}0I+h|I4pK^iw=jia}s#=Imb8YXg*0_+#s#Gv^>=Tc!3%A)B&%s}R)&LHMGh|n3p z$(7={9c-5Y(e7)ocaQX)d5_zqK#KWyUkiU1KghEOA)!{#=fRO-(J_z*?*8!!V7PNo zO6uc38deQhc-*i>3iz^eoFt*DT%x+RM69k6SkqKn*-9uS;W6a@G%ST~m@a!{ENg7? zGn_gZKTWloo3>b7GF_QBTAQK$8Z7S&ukKB4@7&sZ@DqR=2$CCAw;V5|-Q?B(8%*tQ Au>b%7 literal 0 HcmV?d00001 diff --git a/packages/discuz-design/components/audio/layouts/images/paused.png b/packages/discuz-design/components/audio/layouts/images/paused.png new file mode 100644 index 0000000000000000000000000000000000000000..c937bc5bb1b22641935e948c351b87b613030fa5 GIT binary patch literal 583 zcmeAS@N?(olHy`uVBq!ia0vp^1|ZDA3?vioaBc-sfdM`tu0XoIy}h%uvkMG*dU}8~ zgaiu0#UZjlZg+P#gpG@2+VFt|XsA?4kY6x^L&Kq5)l~5_oEF<7KF#)*TUByx;*-18 zodyeqMLii97`r`P978;g&kcP!t672Ph|=_!xYFo*{~fQlg|1m};GFy)lgU1O%v}m^ zy!Fmmo;`cxiw3jX(lYl46YtFUzPZdW?#-!vwYyZ*W|^oTUbg5hhj7!xKCkDByKmg9 z`o2dsUMc#W=G&Y5K0fPwa3xqy^S7Yt$H#UHHr5tL_I`eD{v!Q_5Q~Ij@e2N(xf)Z- zi&suc^-%fQY-3@QZm`a+`v!A?$O41Zx^)|z7;C00?$189rTEqPiD~V1Id!{(8`551 zO4d*1NWA`;b>SwK`@EayU9S38*_7WVR^Soh0#;2F)OX&?o-a_N`qO4LsB>v z)HPZrrLufGDP<&>%JMMmPji6cN#R$Mu4Sy#)n1!D$MJpF#Si$OWOzvrd(1v^T#PM)4>5qk766Z>;>fr|4MnwS1>pWs*> zyZ9I*XQaoU1$JLtEZuh;?D+KVRhdiB5{ zTB#xW>bR`%>YGZbI|9OYyF|_9=uq1j_R@ESqS?{+5_S`2S^v4`n#1U}MJ#jbtUv~x zA6=ZAzIRxD5~|<3;O#Rfh7I?pKDy$1Q*8btCkON8rTcGMa5A5LpUKJ8b4>Y6;zZt8 z3j>W*7d*(0nQWW7R#9RF2a}V}za^bqs)hb5CM-}skzR&-RHMqgA&{7T>o0?(k4P s@{jYx`Zu5W%l=($thY>zum8u880y`<&*+IKFy { + + constructor(props) { + super(props) + + this.state = { + audioCtx: Taro.createInnerAudioContext(), + audioImg: iconLoading, + currentTime: 0, + duration: 0 + } + + this.playOrStopAudio = this.playOrStopAudio.bind(this) + } + + componentWillMount() { + const { + audioCtx, + audioImg + } = this.state + + audioCtx.src = this.props.audioSrc + + // 当播放的时候通过TimeUpdate的回调去更改当前播放时长和总时长(总时长更新放到onCanplay回调中会出错) + audioCtx.onTimeUpdate(() => { + if (audioCtx.currentTime > 0 && audioCtx.currentTime <= 1) { + this.setState({ + currentTime: 1 + }) + } else if (audioCtx.currentTime !== Math.floor(audioCtx.currentTime)) { + this.setState({ + currentTime: Math.floor(audioCtx.currentTime) + }) + } + + const tempDuration = Math.ceil(audioCtx.duration) + if (this.state.duration !== tempDuration) { + this.setState({ + duration: tempDuration + }) + } + }) + + // 当音频可以播放就将状态从loading变为可播放 + audioCtx.onCanplay(() => { + if (audioImg === iconLoading) { + this.setAudioImg(iconPaused) + + // 获取音频时长 + audioCtx.duration; + setTimeout(() => { + this.setState({ + duration: audioCtx.duration + }) + }, 10) + } + }) + + // 当音频在缓冲时改变状态为加载中 + audioCtx.onWaiting(() => { + if (audioImg !== iconLoading) { + this.setAudioImg(iconLoading) + } + }) + + // 开始播放后更改图标状态为播放中 + audioCtx.onPlay(() => { + console.log('onPlay') + this.setAudioImg(iconPlaying) + }) + + // 暂停后更改图标状态为暂停 + audioCtx.onPause(() => { + console.log('onPause') + this.setAudioImg(iconPaused) + afterAudioPlay() + }) + + // 播放结束后更改图标状态 + audioCtx.onEnded(() => { + console.log('onEnded') + if (audioImg !== iconPaused) { + this.setAudioImg(iconPaused) + } + afterAudioPlay() + }) + + // 音频加载失败时 抛出异常 + audioCtx.onError((e) => { + Taro.showToast({ + title: '音频加载失败', + icon: 'none' + }) + throw new Error(e.errMsg) + }) + } + + componentWillReceiveProps(nextProps) { + const newSrc = nextProps.audioSrc || '' + console.log('componentWillReceiveProps', nextProps) + if (this.props.audioSrc !== newSrc && newSrc !== '') { + const audioCtx = this.state.audioCtx + if (!audioCtx.paused) { // 如果还在播放中,先进行停止播放操作 + audioCtx.stop() + } + + audioCtx.src = nextProps.audioSrc + + // 重置当前播放时间和总时长 + this.setState({ + currentTime: 0, + duration: 0, + }) + } + + } + + componentWillUnmount() { + console.log('componentWillUnmount') + + this.state.audioCtx.stop() + this.state.audioCtx.destroy() + afterAudioPlay() + } + + setAudioImg(newImg: string) { + this.setState({ + audioImg: newImg + }) + } + + playOrStopAudio() { + const audioCtx = this.state.audioCtx + if (audioCtx.paused) { + if (beforeAudioPlay()) { + audioCtx.play() + } + } else { + audioCtx.pause() + } + } + + render () { + const { + audioImg, + duration + } = this.state + + return( + + + 约{Math.floor(duration)}秒 + + ) + } +} + +export default CustomAudio \ No newline at end of file diff --git a/packages/discuz-design/components/audio/layouts/mini/utils.js b/packages/discuz-design/components/audio/layouts/mini/utils.js new file mode 100644 index 00000000..1caaeb8f --- /dev/null +++ b/packages/discuz-design/components/audio/layouts/mini/utils.js @@ -0,0 +1,44 @@ +import Taro from '@tarojs/taro' + +// 每次在一个音源暂停或者停止播放的时候将全局标识audioPlaying重置为false,用以让后续的音频可以播放 + +export function afterAudioPlay() { + + try { + Taro.setStorageSync('audioPlaying', false) + } catch (e) { } +} + +// 在每次播放音频之前检查全局变量audioPlaying是否为true,如果是true,当前音频不能播放,需要之前的音频结束或者手动去暂停或者停止之前的音频播放,如果是false,返回true,并将audioPlaying置为true + +export function beforeAudioPlay() { + + let audioPlaying = '' + try { + var value = Taro.getStorageSync('audioPlaying') + if (value) { + audioPlaying = value + } + } catch (e) { } + + if (audioPlaying) { + + Taro.showToast({ + + title: '请先暂停其他音频播放', + + icon: 'none' + + }) + + return false + + } else { + try { + Taro.setStorageSync('audioPlaying', true) + } catch (e) { } + + return true + } + +} \ No newline at end of file diff --git a/packages/discuz-design/components/audio/layouts/web/index.tsx b/packages/discuz-design/components/audio/layouts/web/index.tsx new file mode 100644 index 00000000..e69de29b diff --git a/packages/discuz-design/components/audio/layouts/web/utils.js b/packages/discuz-design/components/audio/layouts/web/utils.js new file mode 100644 index 00000000..69e6476b --- /dev/null +++ b/packages/discuz-design/components/audio/layouts/web/utils.js @@ -0,0 +1,55 @@ +export const createCallbackManager = () => { + const callbacks = [] + + /** + * 添加回调 + * @param {{ callback: function, ctx: any } | function} opt + */ + const add = (opt) => { + callbacks.push(opt) + } + + /** + * 移除回调 + * @param {{ callback: function, ctx: any } | function} opt + */ + const remove = (opt) => { + let pos = -1 + callbacks.forEach((callback, k) => { + if (callback === opt) { + pos = k + } + }) + if (pos > -1) { + callbacks.splice(pos, 1) + } + } + + /** + * 获取回调函数数量 + * @return {number} + */ + const count = () => callbacks.length + + /** + * 触发回调 + * @param {...any} args 回调的调用参数 + */ + const trigger = (...args) => { + callbacks.forEach(opt => { + if (typeof opt === 'function') { + opt(...args) + } else { + const { callback, ctx } = opt + callback.call(ctx, ...args) + } + }) + } + + return { + add, + remove, + count, + trigger + } + } \ No newline at end of file diff --git a/packages/discuz-design/components/audio/layouts/web/web.js b/packages/discuz-design/components/audio/layouts/web/web.js new file mode 100644 index 00000000..3d6680bd --- /dev/null +++ b/packages/discuz-design/components/audio/layouts/web/web.js @@ -0,0 +1,133 @@ +import { createCallbackManager } from './utils'; +/** + * @typedef {object} InnerAudioContext + * @property {string} src 音频资源的地址,用于直接播放。2.2.3 开始支持云文件ID + * @property {number} [startTime=0] 开始播放的位置(单位:s),默认为 0 + * @property {boolean} [autoplay=false] 是否自动开始播放,默认为 false + * @property {boolean} [loop=false] 是否循环播放,默认为 false + * @property {boolean} [obeyMuteSwitch=true] 是否遵循系统静音开关,默认为 true。当此参数为 false 时,即使用户打开了静音开关,也能继续发出声音。从 2.3.0 版本开始此参数不生效,使用 wx.setInnerAudioOption 接口统一设置。 + * @property {number} [volume=1] 音量。范围 0~1。默认为 1 + * @property {number} duration 当前音频的长度(单位 s)。只有在当前有合法的 src 时返回(只读) + * @property {number} currentTime 当前音频的播放位置(单位 s)。只有在当前有合法的 src 时返回,时间保留小数点后 6 位(只读) + * @property {boolean} paused 当前是是否暂停或停止状态(只读) + * @property {number} buffered 音频缓冲的时间点,仅保证当前播放时间点到此时间点内容已缓冲(只读) + * @property {() => void} play() 播放 + * @property {() => void} pause() 暂停。暂停后的音频再播放会从暂停处开始播放 + * @property {() => void} stop() 停止。停止后的音频再播放会从头开始播放。 + * @property {(position: number) => void} seek(number position) 跳转到指定位置 + * @property {() => void} destroy() 销毁当前实例 + * @property {(callback: function) => void} offCanplay(function callback) 取消监听音频进入可以播放状态的事件 + * @property {(callback: function) => void} offEnded(function callback) 取消监听音频自然播放至结束的事件 + * @property {(callback: function) => void} offError(function callback) 取消监听音频播放错误事件 + * @property {(callback: function) => void} offPause(function callback) 取消监听音频暂停事件 + * @property {(callback: function) => void} offPlay(function callback) 取消监听音频播放事件 + * @property {(callback: function) => void} offSeeked(function callback) 取消监听音频完成跳转操作的事件 + * @property {(callback: function) => void} offSeeking(function callback) 取消监听音频进行跳转操作的事件 + * @property {(callback: function) => void} offStop(function callback) 取消监听音频停止事件 + * @property {(callback: function) => void} offTimeUpdate(function callback) 取消监听音频播放进度更新事件 + * @property {(callback: function) => void} offWaiting(function callback) 取消监听音频加载中事件 + * @property {(callback: function) => void} onCanplay(function callback) 监听音频进入可以播放状态的事件。但不保证后面可以流畅播放 + * @property {(callback: function) => void} onEnded(function callback) 监听音频自然播放至结束的事件 + * @property {(callback: function) => void} onError(function callback) 监听音频播放错误事件 + * @property {(callback: function) => void} onPause(function callback) 监听音频暂停事件 + * @property {(callback: function) => void} onPlay(function callback) 监听音频播放事件 + * @property {(callback: function) => void} onSeeked(function callback) 监听音频完成跳转操作的事件 + * @property {(callback: function) => void} onSeeking(function callback) 监听音频进行跳转操作的事件 + * @property {(callback: function) => void} onStop(function callback) 监听音频停止事件 + * @property {(callback: function) => void} onTimeUpdate(function callback) 监听音频播放进度更新事件 + * @property {(callback: function) => void} onWaiting(function callback) 监听音频加载中事件。当音频因为数据不足,需要停下来加载时会触发 + */ + +/** + * 创建内部 audio 上下文 InnerAudioContext 对象。 + * @returns {InnerAudioContext} + */ +export const createInnerAudioContext = () => { + /** @type {HTMLAudioElement} */ + let audioEl = new Audio() + + /** @type {InnerAudioContext} */ + const iac = {} + + const callbackManagers = { + error: createCallbackManager(), + stop: createCallbackManager() + } + + iac.play = () => audioEl.play() + iac.pause = () => audioEl.pause() + iac.stop = () => { + iac.pause() + iac.seek(0) + callbackManagers.stop.trigger() + } + iac.seek = position => { + audioEl.currentTime = position + } + /** + * @todo destroy得并不干净 + */ + iac.destroy = () => { + iac.stop() + document.body.removeChild(audioEl) + audioEl = null + } + + const simpleProperties = ['src', 'autoplay', 'loop', 'volume', 'duration', 'currentTime', 'buffered', 'paused'] + simpleProperties.forEach(propertyName => { + Object.defineProperty(iac, propertyName, { + get: () => audioEl[propertyName], + set (value) { audioEl[propertyName] = value } + }) + }) + + Object.defineProperty(iac, 'startTime', { + value: 0 + }) + Object.defineProperty(iac, 'obeyMuteSwitch', { + value: true + }) + + const simpleEvents = [ + 'Canplay', + 'Ended', + 'Pause', + 'Play', + 'Seeked', + 'Seeking', + 'TimeUpdate', + 'Waiting' + ] + const simpleListenerTuples = [ + ['on', audioEl.addEventListener], + ['off', audioEl.removeEventListener] + ] + + simpleEvents.forEach(eventName => { + simpleListenerTuples.forEach(([eventNamePrefix, listenerFunc]) => { + Object.defineProperty(iac, `${eventNamePrefix}${eventName}`, { + get () { + return callback => listenerFunc.call(audioEl, eventName.toLowerCase(), callback) + } + }) + }) + }) + + const customEvents = ['Stop', 'Error'] + const customListenerTuples = [ + ['on', 'add'], + ['off', 'remove'] + ] + + customEvents.forEach(eventName => { + customListenerTuples.forEach(([eventNamePrefix, actionName]) => { + Object.defineProperty(iac, `${eventNamePrefix}${eventName}`, { + get () { + return callback => callbackManagers[eventName.toLowerCase()][actionName](callback) + } + }) + }) + }) + + return iac +} diff --git a/packages/discuz-design/components/audio/styles/index.scss b/packages/discuz-design/components/audio/styles/index.scss new file mode 100644 index 00000000..732a8926 --- /dev/null +++ b/packages/discuz-design/components/audio/styles/index.scss @@ -0,0 +1,39 @@ +.custom-audio { + + border-radius: 8vw; + + border: #CCC 1px solid; + + background: #F3F6FC; + + color: #333; + + display: flex; + + flex-flow: row nowrap; + + align-items: center; + + justify-content: space-between; + + padding: 2vw; + + font-size: 4vw; + + .audio-btn { + + width: 10vw; + + height: 10vw; + + white-space: nowrap; + + display: flex; + + align-items: center; + + justify-content: center; + + } + +} diff --git a/packages/discuz-design/components/audio/styles/mixin.scss b/packages/discuz-design/components/audio/styles/mixin.scss new file mode 100644 index 00000000..e69de29b diff --git a/packages/discuz-design/components/audio/styles/var.scss b/packages/discuz-design/components/audio/styles/var.scss new file mode 100644 index 00000000..a350745e --- /dev/null +++ b/packages/discuz-design/components/audio/styles/var.scss @@ -0,0 +1,22 @@ +// 组件变量 +// 名称可按如下规则定义: +// -[type]-[attrtype]--[status] + +// component:组件名,如button, +// type: 组件类型,如 button 的次要按钮(line) +// attrtype: 属性的具体应用场景。如颜色,用于背景(bg)、文本(text)、边框(boder)等 +// attr: 属性名称,如color、height、radius等 +// status: 表示组件状态或尺寸,如 hover、disabled、s、l 等 + +// 如:$button-line-bg-color-hover +// 如:$button-line-height-s + +$color-white: #fff; + +$card-text-color: var(--color-text-primary); +$card-border-border: var(--border-border); +$card-border-color: var(--border-color); +$card-border-radius: var(--border-radius-small); +$card-box-shadow: var(--box-shadow); + +$card-padding: 20px; \ No newline at end of file diff --git a/packages/discuz-design/site/mini/src/app.config.js b/packages/discuz-design/site/mini/src/app.config.js index c1bcab92..70dd109a 100644 --- a/packages/discuz-design/site/mini/src/app.config.js +++ b/packages/discuz-design/site/mini/src/app.config.js @@ -11,7 +11,8 @@ export default { 'pages/scrollView/renderBottom/index', 'pages/scrollView/virtualList/index', 'pages/toast/index', - 'pages/flex/index' + 'pages/flex/index', + 'pages/audio/index' ], window: { backgroundTextStyle: 'light', diff --git a/packages/discuz-design/site/mini/src/componentList.json b/packages/discuz-design/site/mini/src/componentList.json index 0a097e7d..0d289db7 100644 --- a/packages/discuz-design/site/mini/src/componentList.json +++ b/packages/discuz-design/site/mini/src/componentList.json @@ -23,6 +23,9 @@ }, "flex": { "url": "flex" + }, + "audio": { + "url": "audio" } } } \ No newline at end of file diff --git a/packages/discuz-design/site/mini/src/pages/audio/index.config.js b/packages/discuz-design/site/mini/src/pages/audio/index.config.js new file mode 100644 index 00000000..28f34239 --- /dev/null +++ b/packages/discuz-design/site/mini/src/pages/audio/index.config.js @@ -0,0 +1,3 @@ +export default { + navigationBarTitleText: 'audio' +} diff --git a/packages/discuz-design/site/mini/src/pages/audio/index.jsx b/packages/discuz-design/site/mini/src/pages/audio/index.jsx new file mode 100644 index 00000000..ed6eaea9 --- /dev/null +++ b/packages/discuz-design/site/mini/src/pages/audio/index.jsx @@ -0,0 +1,22 @@ +import React, { Component } from "react"; +import Taro from '@tarojs/taro'; +import { View, Button } from "@tarojs/components"; +import Audio from "../../../../../components/audio/__examples__/mini/index"; + +export default class Index extends Component { + componentWillMount() {} + + componentDidMount() {} + + componentWillUnmount() {} + + componentDidShow() {} + + componentDidHide() {} + + render() { + return ( + + ); + } +} diff --git a/packages/discuz-design/styles/index.scss b/packages/discuz-design/styles/index.scss index 2dc43bd5..52218c50 100644 --- a/packages/discuz-design/styles/index.scss +++ b/packages/discuz-design/styles/index.scss @@ -7,6 +7,7 @@ @import '../components/card/styles/index.scss'; @import '../components/toast/styles/index.scss'; @import '../components/flex/styles/index.scss'; +@import '../components/audio/styles/index.scss'; page, [data-dzq-theme='light'] { -- Gitee From ed4658ef851e85cbf511acd23c9b9d2548e126df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=88=98=E5=AE=87=E7=90=B3?= Date: Thu, 4 Mar 2021 20:26:03 +0800 Subject: [PATCH 2/7] =?UTF-8?q?feat:=20=E8=A1=A5=E5=85=85=E7=BB=84?= =?UTF-8?q?=E4=BB=B6=E5=8A=9F=E8=83=BD=E5=8F=8A=E7=A4=BA=E4=BE=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../audio/__examples__/mini/index.jsx | 31 ++- .../audio/__examples__/web/base.tsx | 10 - .../audio/__examples__/web/border.tsx | 21 -- .../audio/__examples__/web/custom.tsx | 24 --- .../audio/__examples__/web/image.tsx | 55 ------ .../audio/__examples__/web/index.jsx | 30 +++ .../discuz-design/components/audio/index.tsx | 10 +- .../components/audio/interface.ts | 37 +++- .../components/audio/layouts/index.tsx | 4 +- .../components/audio/layouts/mini/index.tsx | 67 ++++--- .../components/audio/layouts/web/index.tsx | 184 ++++++++++++++++++ .../components/audio/layouts/web/web.js | 2 +- .../components/audio/styles/index.scss | 22 +-- .../components/audio/styles/var.scss | 22 --- packages/discuz-design/components/index.ts | 3 +- .../site/mini/src/pages/audio/index.jsx | 2 - .../discuz-design/site/web/pages/audio.js | 20 ++ 17 files changed, 344 insertions(+), 200 deletions(-) delete mode 100644 packages/discuz-design/components/audio/__examples__/web/base.tsx delete mode 100644 packages/discuz-design/components/audio/__examples__/web/border.tsx delete mode 100644 packages/discuz-design/components/audio/__examples__/web/custom.tsx delete mode 100644 packages/discuz-design/components/audio/__examples__/web/image.tsx create mode 100644 packages/discuz-design/components/audio/__examples__/web/index.jsx create mode 100644 packages/discuz-design/site/web/pages/audio.js diff --git a/packages/discuz-design/components/audio/__examples__/mini/index.jsx b/packages/discuz-design/components/audio/__examples__/mini/index.jsx index 32db2ca3..5a80c61a 100644 --- a/packages/discuz-design/components/audio/__examples__/mini/index.jsx +++ b/packages/discuz-design/components/audio/__examples__/mini/index.jsx @@ -1,8 +1,31 @@ -import React from "react"; -import { View, Text } from "@tarojs/components"; -import CustomAudio from '../../layouts/mini/index'; +import React, { useState } from "react"; +import { View } from "@tarojs/components"; +import Audio from '../../index'; export default function FlexExample() { - return + const [src, setSrc] = useState('https://demo.dj63.com//2016/CLUB商业/club中文/20140101/夏日香气_主题曲_左右为难_电视剧歌曲_韩语.mp3') + const [audio, setAudio] = useState(null) + + const onClick = () => { + console.log(audio); + + setSrc('https://demo.dj63.com//2016/串烧舞曲/20150101/佛山DJ宅神[磁性_男声_女声]歌曲连版串烧[专辑1].mp3') + } + + const onPlay = () => { + console.log('正在播放'); + } + + const getCurrentTime = () => { + console.log(audio.state.currentTime); + } + + return ( + + 点击切换音频 + + ); } diff --git a/packages/discuz-design/components/audio/__examples__/web/base.tsx b/packages/discuz-design/components/audio/__examples__/web/base.tsx deleted file mode 100644 index 2c65874b..00000000 --- a/packages/discuz-design/components/audio/__examples__/web/base.tsx +++ /dev/null @@ -1,10 +0,0 @@ -import Card from '../../index'; -import React from 'react'; - -export default function Example1() { - return ( - -

描述内容

-
- ); -} diff --git a/packages/discuz-design/components/audio/__examples__/web/border.tsx b/packages/discuz-design/components/audio/__examples__/web/border.tsx deleted file mode 100644 index b45589a9..00000000 --- a/packages/discuz-design/components/audio/__examples__/web/border.tsx +++ /dev/null @@ -1,21 +0,0 @@ -import Card from '../../index'; -import React from 'react'; -import Button from '../../../button/index'; - -export default function Example1() { - return ( - - 卡片名称 - - - } - > -

描述内容

-
- ); -} diff --git a/packages/discuz-design/components/audio/__examples__/web/custom.tsx b/packages/discuz-design/components/audio/__examples__/web/custom.tsx deleted file mode 100644 index da804380..00000000 --- a/packages/discuz-design/components/audio/__examples__/web/custom.tsx +++ /dev/null @@ -1,24 +0,0 @@ -import Card from '../../index'; -import React from 'react'; -import Icon from '../../../icon/index'; -import Button from '../../../button/index'; - -export default function Example1() { - return ( - - - - - - - } - footer={} - > -

描述内容

-
- ); -} diff --git a/packages/discuz-design/components/audio/__examples__/web/image.tsx b/packages/discuz-design/components/audio/__examples__/web/image.tsx deleted file mode 100644 index 8ae03400..00000000 --- a/packages/discuz-design/components/audio/__examples__/web/image.tsx +++ /dev/null @@ -1,55 +0,0 @@ -import Card from '../../index'; -import React from 'react'; - -export default function Example1() { - const footer = ( - - ); - - return ( - <> - 设置fullBody来铺满内容区域} footer={footer}> - bg - - - - } - footer={footer} - > - 设置fullHeader来铺满头部区域 - - - 标题} - footer={ - bg - } - > - 设置fullFooter来铺满底部区域 - - - ); -} diff --git a/packages/discuz-design/components/audio/__examples__/web/index.jsx b/packages/discuz-design/components/audio/__examples__/web/index.jsx new file mode 100644 index 00000000..ac4435ca --- /dev/null +++ b/packages/discuz-design/components/audio/__examples__/web/index.jsx @@ -0,0 +1,30 @@ +import React, { useState } from "react"; +import Audio from '../../index'; + +export default function FlexExample() { + const [src, setSrc] = useState('https://demo.dj63.com//2016/CLUB商业/club中文/20140101/夏日香气_主题曲_左右为难_电视剧歌曲_韩语.mp3') + const [audio, setAudio] = useState(null) + + const onClick = () => { + console.log(audio); + + setSrc('https://demo.dj63.com//2016/串烧舞曲/20150101/佛山DJ宅神[磁性_男声_女声]歌曲连版串烧[专辑1].mp3') + } + + const onPlay = () => { + console.log('正在播放'); + } + + const getCurrentTime = () => { + console.log(audio.state.currentTime); + } + + return ( +
+
点击切换音频
+
+ ); +} + diff --git a/packages/discuz-design/components/audio/index.tsx b/packages/discuz-design/components/audio/index.tsx index e8a85db6..7964f56c 100644 --- a/packages/discuz-design/components/audio/index.tsx +++ b/packages/discuz-design/components/audio/index.tsx @@ -2,15 +2,13 @@ import React from 'react'; import { baseComponentFactory } from '../../extends/baseComponent'; import { ViewAdapter } from './layouts/index'; import { LogicalAdapter } from './adapters/index'; -import { CardProps } from './interface'; +import { StateInterface, AudioProps } from './interface'; -interface CardState {} +interface AudioLayoutProps {} -interface CardLayoutProps {} +interface AudioAdapter {} -interface CardAdapter {} - -export default class Card extends baseComponentFactory({ +export default class Audio extends baseComponentFactory({ viewAdapter: ViewAdapter, logicalAdapter: LogicalAdapter, }) { diff --git a/packages/discuz-design/components/audio/interface.ts b/packages/discuz-design/components/audio/interface.ts index c5d7ffe6..e84c0c50 100644 --- a/packages/discuz-design/components/audio/interface.ts +++ b/packages/discuz-design/components/audio/interface.ts @@ -1,19 +1,40 @@ import { StyledProps } from 'utils/_type/StyledProps'; export interface StateInterface { - audioCtx: Taro.InnerAudioContext + audioCtx: any audioImg: string currentTime: number duration: number } -export interface PropsInterface { - audioSrc: string -} - -export interface CustomAudio extends StyledProps { +export interface AudioProps extends StyledProps { + /** + * 音频地址 + */ + src: string, + /** + * 是否循环播放 + * @default false + */ + loop?: string, + /** + * 音频播放错误回调 + */ + onError?: () => void, + /** + * 音频播放回调 + */ + onPlay?: () => void, + /** + * 音频播放暂停回调 + */ + onPause?: () => void, + /** + * 音频播放完成回调 + */ + onEnded?: () => void, /** - * 卡片主体内容 + * 获取音频实例 */ - audioSrc: string + onRef?: (any) => any, } diff --git a/packages/discuz-design/components/audio/layouts/index.tsx b/packages/discuz-design/components/audio/layouts/index.tsx index 9e3f32b7..173935cd 100644 --- a/packages/discuz-design/components/audio/layouts/index.tsx +++ b/packages/discuz-design/components/audio/layouts/index.tsx @@ -3,11 +3,11 @@ import { baseLayoutFactory } from '../../../extends/baseLayout'; export const ViewAdapter = baseLayoutFactory({ layoutImplement() { if (process.env.DISCUZ_ENV === 'web') { - return require('./web').WebLayout; + return require('./web').AudioWebLayout; } if (process.env.DISCUZ_ENV === 'mini') { - return require('./mini').MiniLayout; + return require('./mini').AudioMiniLayout; } }, }); diff --git a/packages/discuz-design/components/audio/layouts/mini/index.tsx b/packages/discuz-design/components/audio/layouts/mini/index.tsx index 8e6a40b1..e75f08f7 100644 --- a/packages/discuz-design/components/audio/layouts/mini/index.tsx +++ b/packages/discuz-design/components/audio/layouts/mini/index.tsx @@ -1,13 +1,15 @@ import Taro from '@tarojs/taro' +import classNames from 'classnames'; import React, { Component } from 'react'; import { View, Image, Text } from "@tarojs/components"; -import { beforeAudioPlay, afterAudioPlay } from './utils'; -import iconPaused from '../images/paused.png' -import iconPlaying from '../images/play.png' +import iconPlaying from '../images/paused.png' +import iconPaused from '../images/play.png' import iconLoading from '../images/loading.gif' -import { StateInterface, PropsInterface } from '../../interface'; +import { StateInterface, AudioProps } from '../../interface'; +import { ConfigContext } from '../../../../extends/configContext'; -class CustomAudio extends Component { +export class AudioMiniLayout extends Component { + static contextType = ConfigContext; constructor(props) { super(props) @@ -22,19 +24,23 @@ class CustomAudio extends Component { this.playOrStopAudio = this.playOrStopAudio.bind(this) } - componentWillMount() { + componentDidMount() { + const { onRef = () => {} } = this.props + onRef(this) + const { audioCtx, audioImg } = this.state - audioCtx.src = this.props.audioSrc + audioCtx.src = this.props.src + audioCtx.loop = !!this.props.loop // 当播放的时候通过TimeUpdate的回调去更改当前播放时长和总时长(总时长更新放到onCanplay回调中会出错) audioCtx.onTimeUpdate(() => { if (audioCtx.currentTime > 0 && audioCtx.currentTime <= 1) { this.setState({ - currentTime: 1 + currentTime: 0 }) } else if (audioCtx.currentTime !== Math.floor(audioCtx.currentTime)) { this.setState({ @@ -74,24 +80,30 @@ class CustomAudio extends Component { // 开始播放后更改图标状态为播放中 audioCtx.onPlay(() => { - console.log('onPlay') this.setAudioImg(iconPlaying) + + const { onPlay = () => {} } = this.props + onPlay() }) // 暂停后更改图标状态为暂停 audioCtx.onPause(() => { - console.log('onPause') this.setAudioImg(iconPaused) - afterAudioPlay() + // // afterAudioPlay() + + const { onPause = () => {} } = this.props + onPause() }) // 播放结束后更改图标状态 audioCtx.onEnded(() => { - console.log('onEnded') if (audioImg !== iconPaused) { this.setAudioImg(iconPaused) } - afterAudioPlay() + // afterAudioPlay() + + const { onEnded = () => {} } = this.props + onEnded() }) // 音频加载失败时 抛出异常 @@ -100,20 +112,24 @@ class CustomAudio extends Component { title: '音频加载失败', icon: 'none' }) + + const { onError = () => {} } = this.props + onError() + throw new Error(e.errMsg) }) } componentWillReceiveProps(nextProps) { - const newSrc = nextProps.audioSrc || '' + const newSrc = nextProps.src || '' console.log('componentWillReceiveProps', nextProps) - if (this.props.audioSrc !== newSrc && newSrc !== '') { + if (this.props.src !== newSrc && newSrc !== '') { const audioCtx = this.state.audioCtx if (!audioCtx.paused) { // 如果还在播放中,先进行停止播放操作 audioCtx.stop() } - audioCtx.src = nextProps.audioSrc + audioCtx.src = nextProps.src // 重置当前播放时间和总时长 this.setState({ @@ -129,7 +145,7 @@ class CustomAudio extends Component { this.state.audioCtx.stop() this.state.audioCtx.destroy() - afterAudioPlay() + // afterAudioPlay() } setAudioImg(newImg: string) { @@ -141,27 +157,28 @@ class CustomAudio extends Component { playOrStopAudio() { const audioCtx = this.state.audioCtx if (audioCtx.paused) { - if (beforeAudioPlay()) { + // if (beforeAudioPlay()) { audioCtx.play() - } + // } } else { audioCtx.pause() } } render () { + const { clsPrefix } = this.context; + const { audioImg, + currentTime, duration } = this.state return( - - - 约{Math.floor(duration)}秒 + + + {Math.floor(currentTime)}/{Math.floor(duration)} ) } -} - -export default CustomAudio \ No newline at end of file +} \ No newline at end of file diff --git a/packages/discuz-design/components/audio/layouts/web/index.tsx b/packages/discuz-design/components/audio/layouts/web/index.tsx index e69de29b..a87dd9d5 100644 --- a/packages/discuz-design/components/audio/layouts/web/index.tsx +++ b/packages/discuz-design/components/audio/layouts/web/index.tsx @@ -0,0 +1,184 @@ +import React, { Component } from 'react'; +import classNames from 'classnames'; +import { createInnerAudioContext } from './web' +import { ConfigContext } from '../../../../extends/configContext'; +import iconPlaying from '../images/paused.png' +import iconPaused from '../images/play.png' +import iconLoading from '../images/loading.gif' +import { StateInterface, AudioProps } from '../../interface'; + +export class AudioWebLayout extends Component { + static contextType = ConfigContext; + + constructor(props) { + super(props) + + this.state = { + audioCtx: null, + audioImg: iconLoading, + currentTime: 0, + duration: 0 + } + + this.playOrStopAudio = this.playOrStopAudio.bind(this) + this.audioMount = this.audioMount.bind(this) + } + + componentDidMount() { + const { onRef = () => {} } = this.props + onRef(this) + + const audioCtx = createInnerAudioContext() + this.audioMount(audioCtx) + this.setState({ audioCtx }) + } + + componentWillReceiveProps(nextProps) { + const newSrc = nextProps.src || '' + console.log('componentWillReceiveProps', nextProps) + if (this.props.src !== newSrc && newSrc !== '') { + const audioCtx = this.state.audioCtx + if (!audioCtx.paused) { // 如果还在播放中,先进行停止播放操作 + audioCtx.stop() + } + + audioCtx.src = nextProps.src + + // 重置当前播放时间和总时长 + this.setState({ + currentTime: 0, + duration: 0, + }) + } + + } + + componentWillUnmount() { + console.log('componentWillUnmount') + + this.state.audioCtx.stop() + this.state.audioCtx.destroy() + // afterAudioPlay() + } + + setAudioImg(newImg: string) { + this.setState({ + audioImg: newImg + }) + } + + playOrStopAudio() { + const audioCtx = this.state.audioCtx + if (audioCtx.paused) { + // if (beforeAudioPlay()) { + audioCtx.play() + // } + } else { + audioCtx.pause() + } + } + + audioMount(audioCtx) { + const { + audioImg + } = this.state + + audioCtx.src = this.props.src + audioCtx.loop = !!this.props.loop + + // 当播放的时候通过TimeUpdate的回调去更改当前播放时长和总时长(总时长更新放到onCanplay回调中会出错) + audioCtx.onTimeUpdate(() => { + if (audioCtx.currentTime > 0 && audioCtx.currentTime <= 1) { + this.setState({ + currentTime: 0 + }) + } else if (audioCtx.currentTime !== Math.floor(audioCtx.currentTime)) { + this.setState({ + currentTime: Math.floor(audioCtx.currentTime) + }) + } + + const tempDuration = Math.ceil(audioCtx.duration) + if (this.state.duration !== tempDuration) { + this.setState({ + duration: tempDuration + }) + } + }) + + // 当音频可以播放就将状态从loading变为可播放 + audioCtx.onCanplay(() => { + if (audioImg === iconLoading) { + this.setAudioImg(iconPaused) + + // 获取音频时长 + audioCtx.duration; + setTimeout(() => { + this.setState({ + duration: audioCtx.duration + }) + }, 10) + } + }) + + // 当音频在缓冲时改变状态为加载中 + audioCtx.onWaiting(() => { + if (audioImg !== iconLoading) { + this.setAudioImg(iconLoading) + } + }) + + // 开始播放后更改图标状态为播放中 + audioCtx.onPlay(() => { + this.setAudioImg(iconPlaying) + + const { onPlay = () => {} } = this.props + onPlay() + }) + + // 暂停后更改图标状态为暂停 + audioCtx.onPause(() => { + this.setAudioImg(iconPaused) + + const { onPause = () => {} } = this.props + onPause() + // afterAudioPlay() + }) + + // 播放结束后更改图标状态 + audioCtx.onEnded(() => { + if (audioImg !== iconPaused) { + this.setAudioImg(iconPaused) + } + + const { onEnded = () => {} } = this.props + onEnded() + // afterAudioPlay() + }) + + // 音频加载失败时 抛出异常 + audioCtx.onError((e) => { + const { onError = () => {} } = this.props + onError() + + throw new Error(e.errMsg) + }) + } + + render () { + const { clsPrefix } = this.context; + + const { + audioImg, + currentTime, + duration + } = this.state + + return( +
+ + {Math.floor(currentTime)}/{Math.floor(duration)} +
+ ) + } +} \ No newline at end of file diff --git a/packages/discuz-design/components/audio/layouts/web/web.js b/packages/discuz-design/components/audio/layouts/web/web.js index 3d6680bd..e8a68271 100644 --- a/packages/discuz-design/components/audio/layouts/web/web.js +++ b/packages/discuz-design/components/audio/layouts/web/web.js @@ -69,7 +69,7 @@ export const createInnerAudioContext = () => { */ iac.destroy = () => { iac.stop() - document.body.removeChild(audioEl) + // document.body.removeChild(audioEl) audioEl = null } diff --git a/packages/discuz-design/components/audio/styles/index.scss b/packages/discuz-design/components/audio/styles/index.scss index 732a8926..caf7278d 100644 --- a/packages/discuz-design/components/audio/styles/index.scss +++ b/packages/discuz-design/components/audio/styles/index.scss @@ -1,39 +1,23 @@ -.custom-audio { +@import '../../styles/mixin.scss'; +@include b(audio) { border-radius: 8vw; - border: #CCC 1px solid; - background: #F3F6FC; - color: #333; - display: flex; - flex-flow: row nowrap; - align-items: center; - justify-content: space-between; - padding: 2vw; - font-size: 4vw; - .audio-btn { - + &-btn { width: 10vw; - height: 10vw; - white-space: nowrap; - display: flex; - align-items: center; - justify-content: center; - } - } diff --git a/packages/discuz-design/components/audio/styles/var.scss b/packages/discuz-design/components/audio/styles/var.scss index a350745e..e69de29b 100644 --- a/packages/discuz-design/components/audio/styles/var.scss +++ b/packages/discuz-design/components/audio/styles/var.scss @@ -1,22 +0,0 @@ -// 组件变量 -// 名称可按如下规则定义: -// -[type]-[attrtype]--[status] - -// component:组件名,如button, -// type: 组件类型,如 button 的次要按钮(line) -// attrtype: 属性的具体应用场景。如颜色,用于背景(bg)、文本(text)、边框(boder)等 -// attr: 属性名称,如color、height、radius等 -// status: 表示组件状态或尺寸,如 hover、disabled、s、l 等 - -// 如:$button-line-bg-color-hover -// 如:$button-line-height-s - -$color-white: #fff; - -$card-text-color: var(--color-text-primary); -$card-border-border: var(--border-border); -$card-border-color: var(--border-color); -$card-border-radius: var(--border-radius-small); -$card-box-shadow: var(--box-shadow); - -$card-padding: 20px; \ No newline at end of file diff --git a/packages/discuz-design/components/index.ts b/packages/discuz-design/components/index.ts index ee4401f5..e30457b3 100644 --- a/packages/discuz-design/components/index.ts +++ b/packages/discuz-design/components/index.ts @@ -5,4 +5,5 @@ export * as Dialog from './dialog'; export * as Card from './card'; export * as ScrollView from './scrollView'; export * as Toast from './Toast'; -export * as Flex from './flex'; \ No newline at end of file +export * as Flex from './flex'; +export * as Audio from './audio'; \ No newline at end of file diff --git a/packages/discuz-design/site/mini/src/pages/audio/index.jsx b/packages/discuz-design/site/mini/src/pages/audio/index.jsx index ed6eaea9..1c8cf341 100644 --- a/packages/discuz-design/site/mini/src/pages/audio/index.jsx +++ b/packages/discuz-design/site/mini/src/pages/audio/index.jsx @@ -4,8 +4,6 @@ import { View, Button } from "@tarojs/components"; import Audio from "../../../../../components/audio/__examples__/mini/index"; export default class Index extends Component { - componentWillMount() {} - componentDidMount() {} componentWillUnmount() {} diff --git a/packages/discuz-design/site/web/pages/audio.js b/packages/discuz-design/site/web/pages/audio.js new file mode 100644 index 00000000..e37c0474 --- /dev/null +++ b/packages/discuz-design/site/web/pages/audio.js @@ -0,0 +1,20 @@ +import React, { Component } from "react"; +import Audio from "../../../components/audio/__examples__/web/index"; + +export default class Index extends Component { + componentWillMount() {} + + componentDidMount() {} + + componentWillUnmount() {} + + componentDidShow() {} + + componentDidHide() {} + + render() { + return ( + + ); + } +} -- Gitee From 03b4b3da45eec668e2f5d153e6ad0aac325f8622 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=88=98=E5=AE=87=E7=90=B3?= Date: Thu, 4 Mar 2021 21:43:57 +0800 Subject: [PATCH 3/7] =?UTF-8?q?fix:=20=E6=B7=BB=E5=8A=A0readme=EF=BC=8C?= =?UTF-8?q?=E5=88=A0=E9=99=A4=E5=A4=9A=E4=BD=99log?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../discuz-design/components/audio/README.md | 23 ++++++++----------- .../components/audio/layouts/mini/index.tsx | 3 --- .../components/audio/layouts/web/index.tsx | 3 --- 3 files changed, 10 insertions(+), 19 deletions(-) diff --git a/packages/discuz-design/components/audio/README.md b/packages/discuz-design/components/audio/README.md index 39381396..33d93693 100644 --- a/packages/discuz-design/components/audio/README.md +++ b/packages/discuz-design/components/audio/README.md @@ -1,22 +1,19 @@ -# Card +# Audio ## 组件说明 -基础的容器组件,可以容纳任意内容。 + +基础的音频组件。 ## 示例 -### WEB示例 -[基础用法](./__examples__/web/base.tsx) -[自定义头尾](./__examples__/web/custom.tsx) -[带边框](./__examples__/web/border.tsx) -[图片展示](./__examples__/web/image.tsx) +### WEB 示例 + +[基础用法](./__examples__/web/index.tsx) ### 小程序示例 -[基础用法](./__examples__/mini/base.tsx) -[自定义头尾](./__examples__/mini/custom.tsx) -[带边框](./__examples__/mini/border.tsx) -[图片展示](./__examples__/mini/image.tsx) -## API参数 -[API参数](./interface.ts) +[基础用法](./__examples__/mini/index.tsx) + +## API 参数 +[API 参数](./interface.ts) diff --git a/packages/discuz-design/components/audio/layouts/mini/index.tsx b/packages/discuz-design/components/audio/layouts/mini/index.tsx index e75f08f7..864d60a0 100644 --- a/packages/discuz-design/components/audio/layouts/mini/index.tsx +++ b/packages/discuz-design/components/audio/layouts/mini/index.tsx @@ -122,7 +122,6 @@ export class AudioMiniLayout extends Component { componentWillReceiveProps(nextProps) { const newSrc = nextProps.src || '' - console.log('componentWillReceiveProps', nextProps) if (this.props.src !== newSrc && newSrc !== '') { const audioCtx = this.state.audioCtx if (!audioCtx.paused) { // 如果还在播放中,先进行停止播放操作 @@ -141,8 +140,6 @@ export class AudioMiniLayout extends Component { } componentWillUnmount() { - console.log('componentWillUnmount') - this.state.audioCtx.stop() this.state.audioCtx.destroy() // afterAudioPlay() diff --git a/packages/discuz-design/components/audio/layouts/web/index.tsx b/packages/discuz-design/components/audio/layouts/web/index.tsx index a87dd9d5..8b2d36c2 100644 --- a/packages/discuz-design/components/audio/layouts/web/index.tsx +++ b/packages/discuz-design/components/audio/layouts/web/index.tsx @@ -35,7 +35,6 @@ export class AudioWebLayout extends Component { componentWillReceiveProps(nextProps) { const newSrc = nextProps.src || '' - console.log('componentWillReceiveProps', nextProps) if (this.props.src !== newSrc && newSrc !== '') { const audioCtx = this.state.audioCtx if (!audioCtx.paused) { // 如果还在播放中,先进行停止播放操作 @@ -54,8 +53,6 @@ export class AudioWebLayout extends Component { } componentWillUnmount() { - console.log('componentWillUnmount') - this.state.audioCtx.stop() this.state.audioCtx.destroy() // afterAudioPlay() -- Gitee From 68b5f82798155cd16865f3e6c8d42fe7d1a52380 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=88=98=E5=AE=87=E7=90=B3?= Date: Thu, 4 Mar 2021 22:01:45 +0800 Subject: [PATCH 4/7] =?UTF-8?q?fix:=20=E6=B7=BB=E5=8A=A0=E5=BE=85=E5=8A=9E?= =?UTF-8?q?=E9=A1=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/discuz-design/components/audio/interface.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/discuz-design/components/audio/interface.ts b/packages/discuz-design/components/audio/interface.ts index e84c0c50..cb71a7f1 100644 --- a/packages/discuz-design/components/audio/interface.ts +++ b/packages/discuz-design/components/audio/interface.ts @@ -35,6 +35,7 @@ export interface AudioProps extends StyledProps { onEnded?: () => void, /** * 获取音频实例 + * @todo 此处定义后期需要调整,不建议使用onRef这种自定义的方式获取组件实例 */ onRef?: (any) => any, } -- Gitee From 249c7b2935878d6cbbe82c763669219581efeb89 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=88=98=E5=AE=87=E7=90=B3?= Date: Fri, 5 Mar 2021 10:45:09 +0800 Subject: [PATCH 5/7] =?UTF-8?q?fix:=20=E6=B7=BB=E5=8A=A0defaultProps?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/discuz-design/components/audio/index.tsx | 9 +++++++++ packages/discuz-design/components/audio/interface.ts | 6 +++++- .../components/audio/layouts/mini/index.tsx | 7 ++----- .../components/audio/layouts/web/index.tsx | 10 +++------- .../discuz-design/components/audio/layouts/web/web.js | 2 +- 5 files changed, 20 insertions(+), 14 deletions(-) diff --git a/packages/discuz-design/components/audio/index.tsx b/packages/discuz-design/components/audio/index.tsx index 7964f56c..3c75a4c3 100644 --- a/packages/discuz-design/components/audio/index.tsx +++ b/packages/discuz-design/components/audio/index.tsx @@ -12,6 +12,15 @@ export default class Audio extends baseComponentFactory {}, + onPlay: () => {}, + onPause: () => {}, + onEnded: () => {}, + onRef: () => {}, + loop: false + }; + render() { const { RenderComponent } = this; return {this.props.children}; diff --git a/packages/discuz-design/components/audio/interface.ts b/packages/discuz-design/components/audio/interface.ts index cb71a7f1..dbb36599 100644 --- a/packages/discuz-design/components/audio/interface.ts +++ b/packages/discuz-design/components/audio/interface.ts @@ -16,21 +16,25 @@ export interface AudioProps extends StyledProps { * 是否循环播放 * @default false */ - loop?: string, + loop?: boolean, /** * 音频播放错误回调 + * @default () => {} */ onError?: () => void, /** * 音频播放回调 + * @default () => {} */ onPlay?: () => void, /** * 音频播放暂停回调 + * @default () => {} */ onPause?: () => void, /** * 音频播放完成回调 + * @default () => {} */ onEnded?: () => void, /** diff --git a/packages/discuz-design/components/audio/layouts/mini/index.tsx b/packages/discuz-design/components/audio/layouts/mini/index.tsx index 864d60a0..b362a438 100644 --- a/packages/discuz-design/components/audio/layouts/mini/index.tsx +++ b/packages/discuz-design/components/audio/layouts/mini/index.tsx @@ -20,8 +20,6 @@ export class AudioMiniLayout extends Component { currentTime: 0, duration: 0 } - - this.playOrStopAudio = this.playOrStopAudio.bind(this) } componentDidMount() { @@ -82,8 +80,7 @@ export class AudioMiniLayout extends Component { audioCtx.onPlay(() => { this.setAudioImg(iconPlaying) - const { onPlay = () => {} } = this.props - onPlay() + this.props.onPlay() }) // 暂停后更改图标状态为暂停 @@ -151,7 +148,7 @@ export class AudioMiniLayout extends Component { }) } - playOrStopAudio() { + playOrStopAudio = () => { const audioCtx = this.state.audioCtx if (audioCtx.paused) { // if (beforeAudioPlay()) { diff --git a/packages/discuz-design/components/audio/layouts/web/index.tsx b/packages/discuz-design/components/audio/layouts/web/index.tsx index 8b2d36c2..52cba4a0 100644 --- a/packages/discuz-design/components/audio/layouts/web/index.tsx +++ b/packages/discuz-design/components/audio/layouts/web/index.tsx @@ -19,9 +19,6 @@ export class AudioWebLayout extends Component { currentTime: 0, duration: 0 } - - this.playOrStopAudio = this.playOrStopAudio.bind(this) - this.audioMount = this.audioMount.bind(this) } componentDidMount() { @@ -64,7 +61,7 @@ export class AudioWebLayout extends Component { }) } - playOrStopAudio() { + playOrStopAudio = () => { const audioCtx = this.state.audioCtx if (audioCtx.paused) { // if (beforeAudioPlay()) { @@ -75,7 +72,7 @@ export class AudioWebLayout extends Component { } } - audioMount(audioCtx) { + audioMount = (audioCtx) => { const { audioImg } = this.state @@ -129,8 +126,7 @@ export class AudioWebLayout extends Component { audioCtx.onPlay(() => { this.setAudioImg(iconPlaying) - const { onPlay = () => {} } = this.props - onPlay() + this.props.onPlay() }) // 暂停后更改图标状态为暂停 diff --git a/packages/discuz-design/components/audio/layouts/web/web.js b/packages/discuz-design/components/audio/layouts/web/web.js index e8a68271..bf31f915 100644 --- a/packages/discuz-design/components/audio/layouts/web/web.js +++ b/packages/discuz-design/components/audio/layouts/web/web.js @@ -76,7 +76,7 @@ export const createInnerAudioContext = () => { const simpleProperties = ['src', 'autoplay', 'loop', 'volume', 'duration', 'currentTime', 'buffered', 'paused'] simpleProperties.forEach(propertyName => { Object.defineProperty(iac, propertyName, { - get: () => audioEl[propertyName], + get: () => audioEl ? audioEl[propertyName] : '', set (value) { audioEl[propertyName] = value } }) }) -- Gitee From bed81b39617b51f00528a29f7ed49cc303ba7a0e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=88=98=E5=AE=87=E7=90=B3?= Date: Fri, 5 Mar 2021 16:10:12 +0800 Subject: [PATCH 6/7] =?UTF-8?q?fix:=20=E6=B7=BB=E5=8A=A0=E5=8F=AF=E8=A2=AB?= =?UTF-8?q?vscode=E8=AF=86=E5=88=AB=E7=9A=84TODO=E6=A0=87=E8=AF=86?= =?UTF-8?q?=EF=BC=8C=E4=BE=BF=E4=BA=8E=E5=90=8E=E6=9C=9F=E8=BF=BD=E8=B8=AA?= =?UTF-8?q?=E5=BE=85=E5=8A=9E=E4=BA=8B=E9=A1=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/discuz-design/components/audio/interface.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/discuz-design/components/audio/interface.ts b/packages/discuz-design/components/audio/interface.ts index dbb36599..d8fcfa07 100644 --- a/packages/discuz-design/components/audio/interface.ts +++ b/packages/discuz-design/components/audio/interface.ts @@ -41,5 +41,6 @@ export interface AudioProps extends StyledProps { * 获取音频实例 * @todo 此处定义后期需要调整,不建议使用onRef这种自定义的方式获取组件实例 */ + // TODO: 此处定义后期需要调整,不建议使用onRef这种自定义的方式获取组件实例 onRef?: (any) => any, } -- Gitee From 817205ab55b20eba2b16012dab3c245f797d4c44 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=88=98=E5=AE=87=E7=90=B3?= Date: Fri, 5 Mar 2021 18:30:14 +0800 Subject: [PATCH 7/7] =?UTF-8?q?fix:=20=E4=BF=AE=E6=94=B9=E7=BB=84=E4=BB=B6?= =?UTF-8?q?api=EF=BC=8C=E5=AE=9E=E7=8E=B0=E8=8E=B7=E5=8F=96ref=E9=80=BB?= =?UTF-8?q?=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../components/audio/__examples__/mini/index.jsx | 11 ++++++----- .../components/audio/__examples__/web/index.jsx | 11 ++++++----- .../discuz-design/components/audio/index.tsx | 16 +++++++++++++--- .../discuz-design/components/audio/interface.ts | 5 ++--- 4 files changed, 27 insertions(+), 16 deletions(-) diff --git a/packages/discuz-design/components/audio/__examples__/mini/index.jsx b/packages/discuz-design/components/audio/__examples__/mini/index.jsx index 5a80c61a..82f18571 100644 --- a/packages/discuz-design/components/audio/__examples__/mini/index.jsx +++ b/packages/discuz-design/components/audio/__examples__/mini/index.jsx @@ -4,11 +4,9 @@ import Audio from '../../index'; export default function FlexExample() { const [src, setSrc] = useState('https://demo.dj63.com//2016/CLUB商业/club中文/20140101/夏日香气_主题曲_左右为难_电视剧歌曲_韩语.mp3') - const [audio, setAudio] = useState(null) + const audioRef = React.useRef(); const onClick = () => { - console.log(audio); - setSrc('https://demo.dj63.com//2016/串烧舞曲/20150101/佛山DJ宅神[磁性_男声_女声]歌曲连版串烧[专辑1].mp3') } @@ -16,14 +14,17 @@ export default function FlexExample() { console.log('正在播放'); } + // 获取当前播放时间 const getCurrentTime = () => { - console.log(audio.state.currentTime); + // @ts-ignore + const audioState = audioRef.current.getState() + console.log(audioState.currentTime); } return ( 点击切换音频 - ); diff --git a/packages/discuz-design/components/audio/__examples__/web/index.jsx b/packages/discuz-design/components/audio/__examples__/web/index.jsx index ac4435ca..593148b9 100644 --- a/packages/discuz-design/components/audio/__examples__/web/index.jsx +++ b/packages/discuz-design/components/audio/__examples__/web/index.jsx @@ -3,11 +3,9 @@ import Audio from '../../index'; export default function FlexExample() { const [src, setSrc] = useState('https://demo.dj63.com//2016/CLUB商业/club中文/20140101/夏日香气_主题曲_左右为难_电视剧歌曲_韩语.mp3') - const [audio, setAudio] = useState(null) + const audioRef = React.useRef(); const onClick = () => { - console.log(audio); - setSrc('https://demo.dj63.com//2016/串烧舞曲/20150101/佛山DJ宅神[磁性_男声_女声]歌曲连版串烧[专辑1].mp3') } @@ -15,14 +13,17 @@ export default function FlexExample() { console.log('正在播放'); } + // 获取当前播放时间 const getCurrentTime = () => { - console.log(audio.state.currentTime); + // @ts-ignore + const audioState = audioRef.current.getState() + console.log(audioState.currentTime); } return (
点击切换音频
-
); diff --git a/packages/discuz-design/components/audio/index.tsx b/packages/discuz-design/components/audio/index.tsx index 3c75a4c3..3384aaf7 100644 --- a/packages/discuz-design/components/audio/index.tsx +++ b/packages/discuz-design/components/audio/index.tsx @@ -1,4 +1,4 @@ -import React from 'react'; +import React, { useRef } from 'react'; import { baseComponentFactory } from '../../extends/baseComponent'; import { ViewAdapter } from './layouts/index'; import { LogicalAdapter } from './adapters/index'; @@ -19,10 +19,20 @@ export default class Audio extends baseComponentFactory {}, onRef: () => {}, loop: false - }; + }; + + // 获取子组件实例 + setChildrenRef = (ref) => { + this.setState({ childrenRef: ref }) + } + + // 获取子组件实例的state值 + getState = () => { + return this.state.childrenRef.state + } render() { const { RenderComponent } = this; - return {this.props.children}; + return {this.props.children}; } } diff --git a/packages/discuz-design/components/audio/interface.ts b/packages/discuz-design/components/audio/interface.ts index d8fcfa07..9649eec3 100644 --- a/packages/discuz-design/components/audio/interface.ts +++ b/packages/discuz-design/components/audio/interface.ts @@ -5,6 +5,7 @@ export interface StateInterface { audioImg: string currentTime: number duration: number + childrenRef: any } export interface AudioProps extends StyledProps { @@ -39,8 +40,6 @@ export interface AudioProps extends StyledProps { onEnded?: () => void, /** * 获取音频实例 - * @todo 此处定义后期需要调整,不建议使用onRef这种自定义的方式获取组件实例 */ - // TODO: 此处定义后期需要调整,不建议使用onRef这种自定义的方式获取组件实例 - onRef?: (any) => any, + ref?: any } -- Gitee