From a25bbf56ad885096881af501d69a27a2d4dd1635 Mon Sep 17 00:00:00 2001 From: catchonme Date: Wed, 8 May 2019 17:12:39 +0800 Subject: [PATCH 1/3] =?UTF-8?q?audio=20=E7=BB=84=E4=BB=B6=E5=A2=9E?= =?UTF-8?q?=E5=8A=A0=E6=94=AF=E6=8C=81=E8=87=AA=E5=AE=9A=E4=B9=89=E9=85=8D?= =?UTF-8?q?=E7=BD=AE=E6=8E=A7=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/renderers.md | 3 +- scss/_variables.scss | 32 ++---- scss/components/_audio.scss | 112 +++++++++---------- src/renderers/Audio.tsx | 214 +++++++++++++++++++++++------------- 4 files changed, 200 insertions(+), 161 deletions(-) diff --git a/docs/renderers.md b/docs/renderers.md index 92ff25d5..17b7a4d8 100644 --- a/docs/renderers.md +++ b/docs/renderers.md @@ -3477,7 +3477,8 @@ CRUD 支持三种模式:`table`、`cards`、`list`,默认为 `table`。 | src | `string` | | 音频地址 | | loop | `boolean` | false | 是否循环播放 | | autoPlay | `boolean` | false | 是否自动播放 | -| rates | `array` | `[1.0, 2.0, 4.0]` | 加速播放 | +| rates | `array` | `[]` | 加速播放 | +| controls | `array` | `['rates', 'play', 'time', 'process', 'volume']` | 内部模块定制化 | ```schema:height="200" scope="body" { diff --git a/scss/_variables.scss b/scss/_variables.scss index df6f5bbb..cc80ab3a 100644 --- a/scss/_variables.scss +++ b/scss/_variables.scss @@ -1192,41 +1192,26 @@ $IconPicker-sugItem-lineHeight: px2rem(28px) !default; $IconPicker-selectedIcon-marginRight: px2rem(5px) !default; // Audio -$Audio-width: px2rem(300px) !default; $Audio-height: px2rem(50px) !default; $Audio-lineHeight: px2rem(50px) !default; $Audio-border: px2rem(1px) solid #dee2e6 !default; -$Audio-rate-padding: 0 px2rem(5px) !default; $Audio-rate-width: px2rem(40px) !default; $Audio-rate-height: px2rem(50px) !default; $Audio-rate-lineHeight: px2rem(50px) !default; $Audio-rate-bg: #dee2e6 !default; -$Audio-rateControlItem-padding: px2rem(16px) px2rem(7px) !default; $Audio-rateControlItem-bg: #dee2e6 !default; $Audio-rateControlItem-borderRight: px2rem(1px) solid #d3dae0 !default; -$Audio-play-width: px2rem(25px) !default; +$Audio-play-width: px2rem(20px) !default; $Audio-play-top: px2rem(5px) !default; -$Audio-play-marginLeft: px2rem(10px) !default; -$Audio-times-width: px2rem(80px) !default; -$Audio-times-margin: 0 px2rem(10px) !default; +$Audio-times-width: px2rem(75px) !default; +$Audio-times-margin: 0 px2rem(5px) !default; $Audio-process-width: px2rem(80px) !default; -$Audio-volume-width: px2rem(22px) !default; +$Audio-volume-width: px2rem(20px) !default; $Audio-volume-height: px2rem(22px) !default; -$Audio-volume-lineHeight: px2rem(30px) !default; -$Audio-volume-borderRadius: px2rem(15px) !default; -$Audio-volume-top: px2rem(5px) !default; -$Audio-volume-left: px2rem(10px) !default; -$Audio-volumeControl-width: px2rem(130px) !default; -$Audio-volumeControl-height: px2rem(30px) !default; -$Audio-volumeControl-lineHeight: px2rem(30px) !default; -$Audio-volumeControl-right: px2rem(-6px) !default; -$Audio-volumeControl-top: px2rem(-4px) !default; -$Audio-volumeControl-paddingLeft: px2rem(10px) !default; -$Audio-volumeControl-bg: #E6E7E9 !default; -$Audio-volumeControl-border: px2rem(2px) solid transparent !default; -$Audio-volumeControl-borderRadius: px2rem(10px) !default; +$Audio-volumeControl-width: px2rem(110px) !default; +$Audio-volumeControl-height: px2rem(50px) !default; +$Audio-volumeControl-lineHeight: px2rem(50px) !default; $Audio-input-width: px2rem(80px) !default; -$Audio-volumeControl-input-margin: px2rem(-3px) px2rem(10px) 0 0 !default; $Audio-track-height: px2rem(6px) !default; $Audio-track-bg: #d7dbdd !default; $Audio-track-borderRadius: px2rem(3px) !default; @@ -1237,4 +1222,5 @@ $Audio-thumb-bg: #606670 !default; $Audio-thumb-marginTop: px2rem(-5px) !default; $Audio-svg-width: px2rem(20px) !default; $Audio-svg-height: px2rem(20px) !default; -$Audio-svg-top: px2rem(4px) !default; \ No newline at end of file +$Audio-svg-top: px2rem(6px) !default; +$Audio-item-margin: px2rem(10px) !default; \ No newline at end of file diff --git a/scss/components/_audio.scss b/scss/components/_audio.scss index dd53e7d9..a95e7e3b 100644 --- a/scss/components/_audio.scss +++ b/scss/components/_audio.scss @@ -29,6 +29,8 @@ @mixin svg { width: $Audio-svg-width; height: $Audio-svg-height; + position: relative; + top: $Audio-svg-top; } .#{$ns}Audio-original { @@ -42,52 +44,47 @@ } .#{$ns}Audio { - width: $Audio-width; + box-sizing: border-box; height: $Audio-height; line-height: $Audio-lineHeight; border: $Audio-border; display: inline-block; - &-rates-holder { - display: inline-block; - width: $Audio-rate-width / 2; - } + padding-left: $Audio-item-margin; &-rates { display: inline-block; - position: relative; - - .#{$ns}Audio-rate { - display: block; - padding: $Audio-rate-padding; - width: $Audio-rate-width; - height: $Audio-rate-height; - line-height: $Audio-rate-lineHeight; - text-align: center; - background: $Audio-rate-bg; - cursor: pointer; + width: $Audio-rate-width; + height: $Audio-rate-height; + text-align: center; + background: $Audio-rate-bg; + cursor: pointer; + margin-right: $Audio-item-margin; + } + &-rateControl { + display: inline-block; + margin-right: $Audio-item-margin; + &::after { + display: inline-block; + clear: both; + content: ""; } - .#{$ns}Audio-rateControl { - position: absolute; - top: 0; - left: 0; - z-index: 1; - - .#{$ns}Audio-rateControlItem { - padding: $Audio-rateControlItem-padding; - background: $Audio-rateControlItem-bg; - cursor: pointer; - user-select: none; - border-right: $Audio-rateControlItem-borderRight; - } + .#{$ns}Audio-rateControlItem { + display: inline-block; + width: $Audio-rate-width; + height: $Audio-rate-height; + background: $Audio-rate-bg; + cursor: pointer; + text-align: center; + float: left; + box-sizing: border-box; + border-right: $Audio-rateControlItem-borderRight; } } &-play { display: inline-block; width: $Audio-play-width; - position: relative; - top: $Audio-play-top; cursor: pointer; - margin-left: $Audio-play-marginLeft; + margin-right: $Audio-item-margin; svg { @include svg(); @@ -96,13 +93,14 @@ &-times { display: inline-block; width: $Audio-times-width; - margin: $Audio-times-margin; + margin-right: $Audio-item-margin; cursor: default; } &-process { display: inline-block; width: $Audio-process-width; cursor: pointer; + margin-right: $Audio-item-margin; input[type=range] { @include input-range(); @@ -112,43 +110,31 @@ display: inline-block; width: $Audio-volume-width; height: $Audio-volume-height; - line-height: $Audio-volume-lineHeight; - border-radius: $Audio-volume-borderRadius; - position: relative; - top: $Audio-volume-top; - left: $Audio-volume-left; cursor: pointer; + margin-right: $Audio-item-margin; svg { @include svg(); } + } + &-volumeControl { + display: inline-block; + width: $Audio-volumeControl-width; + height: $Audio-volumeControl-height; + line-height: $Audio-volumeControl-lineHeight; + margin-right: $Audio-item-margin; + input[type=range] { + @include input-range(); + } - .#{$ns}Audio-volumeControl { - position: absolute; - right: $Audio-volumeControl-right; - top: $Audio-volumeControl-top; - padding-left: $Audio-volumeControl-paddingLeft; - height: $Audio-volumeControl-height; - line-height: $Audio-volumeControl-lineHeight; - border-radius: $Audio-volumeControl-borderRadius; - background: $Audio-volumeControl-bg; - border: $Audio-volumeControl-border; - width: $Audio-volumeControl-width; - input[type=range] { - margin: $Audio-volumeControl-input-margin; - @include input-range(); - } + .#{$ns}Audio-volumeControlIcon { + margin-right: $Audio-item-margin; + display: inline-block; + cursor: pointer; + } - .#{$ns}Audio-volumeControlIcon { - display: inline-block; - cursor: pointer; - } - - svg { - position: relative; - top: $Audio-svg-top; - @include svg(); - } + svg { + @include svg(); } } } \ No newline at end of file diff --git a/src/renderers/Audio.tsx b/src/renderers/Audio.tsx index 1c38b911..92fd7326 100644 --- a/src/renderers/Audio.tsx +++ b/src/renderers/Audio.tsx @@ -1,7 +1,8 @@ import * as React from 'react'; +import upperFirst = require('lodash/upperFirst'); import {Renderer, RendererProps} from '../factory'; -import {autobind} from '../utils/helper'; -import {volumeIcon, muteIcon, playIcon, pauseIcon} from '../components/icons'; +import { autobind } from '../utils/helper'; +import { volumeIcon, muteIcon, playIcon, pauseIcon} from '../components/icons'; export interface AudioProps extends RendererProps { className?: string; @@ -10,6 +11,7 @@ export interface AudioProps extends RendererProps { autoPlay?: boolean; loop?: boolean; rates?: number[]; + controls?: string[]; } export interface AudioState { @@ -33,14 +35,15 @@ export class Audio extends React.Component { static defaultProps: Pick< AudioProps, - 'inline' | 'autoPlay' | 'playbackRate' | 'loop' | 'rates' | 'progressInterval' - > = { + 'inline' | 'autoPlay' | 'playbackRate' | 'loop' | 'rates' | 'progressInterval' | 'controls' + > = { inline: true, autoPlay: false, playbackRate: 1, loop: false, - rates: [1.0, 2.0, 4.0], + rates: [], progressInterval: 1000, + controls: ['rates', 'play', 'time', 'process', 'volume'] }; state: AudioState = { @@ -59,6 +62,7 @@ export class Audio extends React.Component { componentWillUnmount() { clearTimeout(this.progressTimeout); + clearTimeout(this.durationTimeout); } componentDidMount() { @@ -256,9 +260,128 @@ export class Audio extends React.Component { }); } + @autobind + renderRates() { + const { + rates, + classnames: cx + } = this.props; + const { + showHandlePlaybackRate, + playbackRate + } = this.state; + + return ( + rates && rates.length ? + showHandlePlaybackRate ? ( +
+ {rates.map((rate, index) => +
this.handlePlaybackRate(rate)}> + x{rate.toFixed(1)} +
+ )} +
+ ) : ( +
+ x{playbackRate.toFixed(1)} +
+ ) + : null + ) + } + + @autobind + renderPlay() { + const {classnames: cx} = this.props; + const {playing} = this.state; + + return ( +
+ {playing ? pauseIcon : playIcon} +
+ ) + } + + @autobind + renderTime() { + const {classnames: cx} = this.props; + + return ( +
+ {this.getCurrentTime()} / {this.getDuration()} +
+ ) + } + + @autobind + renderProcess() { + const {classnames: cx} = this.props; + const {played} = this.state; + + return ( +
+ +
+ ) + } + + @autobind + renderVolume() { + const {classnames: cx} = this.props; + const { + volume, + showHandleVolume + } = this.state; + + return ( + showHandleVolume ? ( +
this.toggleHandleVolume(false)}> +
+ {volume > 0 ? volumeIcon : muteIcon} +
+ +
+ ) : ( +
this.toggleHandleVolume(true)}> + {volume > 0 ? volumeIcon : muteIcon} +
+ ) + ) + } + render() { - const {className, inline, src, autoPlay, loop, rates, classnames: cx} = this.props; - const {playing, played, volume, muted, playbackRate, showHandlePlaybackRate, showHandleVolume} = this.state; + const { + className, + inline, + src, + autoPlay, + loop, + controls, + classnames: cx + } = this.props; + const {muted} = this.state; return (
@@ -269,76 +392,19 @@ export class Audio extends React.Component { autoPlay={autoPlay} controls muted={muted} - loop={loop} - > + loop={loop}>
- {rates && rates.length ? ( -
-
- x{playbackRate.toFixed(1)} -
- {showHandlePlaybackRate ? ( -
- {rates.map((rate, index) => ( - this.handlePlaybackRate(rate)} - > - x{rate.toFixed(1)} - - ))}{' '} -
- ) : null} -
- ) : ( -
- )} -
- {playing ? pauseIcon : playIcon} -
-
- {this.getCurrentTime()} / {this.getDuration()} -
-
- -
-
this.toggleHandleVolume(true)} - onMouseLeave={() => this.toggleHandleVolume(false)} - > - {showHandleVolume ? ( -
- -
- {volume > 0 ? volumeIcon : muteIcon} -
-
- ) : volume > 0 ? ( - volumeIcon - ) : ( - muteIcon - )} -
+ {controls && controls.map((control:string, index:number) => { + control = 'render' + upperFirst(control); + const method:'renderRates'|'renderPlay'|'renderTime'|'renderProcess'|'renderVolume'|'render' = control as any; + return ( + + {this[method]()} + + ) + })}
); From e584492c176aa12be468d22476554262f12a5fef Mon Sep 17 00:00:00 2001 From: catchonme Date: Wed, 8 May 2019 17:23:18 +0800 Subject: [PATCH 2/3] =?UTF-8?q?combo=20=E4=B8=ADis-disabled=20=E5=B1=9E?= =?UTF-8?q?=E6=80=A7=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- scss/components/form/_combo.scss | 5 +++++ src/renderers/Audio.tsx | 6 +++--- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/scss/components/form/_combo.scss b/scss/components/form/_combo.scss index 10c216fa..19d57532 100644 --- a/scss/components/form/_combo.scss +++ b/scss/components/form/_combo.scss @@ -69,6 +69,11 @@ white-space: nowrap; align-items: flex-start; padding-top: $Form-label-paddingTop; + + > .is-disabled { + pointer-events: none; + opacity: $Button-onDisabled-opacity; + } } } diff --git a/src/renderers/Audio.tsx b/src/renderers/Audio.tsx index 92fd7326..ada8caee 100644 --- a/src/renderers/Audio.tsx +++ b/src/renderers/Audio.tsx @@ -1,8 +1,8 @@ import * as React from 'react'; import upperFirst = require('lodash/upperFirst'); import {Renderer, RendererProps} from '../factory'; -import { autobind } from '../utils/helper'; -import { volumeIcon, muteIcon, playIcon, pauseIcon} from '../components/icons'; +import {autobind} from '../utils/helper'; +import {volumeIcon, muteIcon, playIcon, pauseIcon} from '../components/icons'; export interface AudioProps extends RendererProps { className?: string; @@ -36,7 +36,7 @@ export class Audio extends React.Component { static defaultProps: Pick< AudioProps, 'inline' | 'autoPlay' | 'playbackRate' | 'loop' | 'rates' | 'progressInterval' | 'controls' - > = { + > = { inline: true, autoPlay: false, playbackRate: 1, From 8ee328fcbb2b00c17edf00e2a0b88110054f5e9f Mon Sep 17 00:00:00 2001 From: catchonme Date: Wed, 8 May 2019 17:34:50 +0800 Subject: [PATCH 3/3] =?UTF-8?q?=E5=8E=BB=E9=99=A4=E6=97=A0=E7=94=A8?= =?UTF-8?q?=E7=9A=84@autobind?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/renderers/Audio.tsx | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/renderers/Audio.tsx b/src/renderers/Audio.tsx index ada8caee..ad4963bb 100644 --- a/src/renderers/Audio.tsx +++ b/src/renderers/Audio.tsx @@ -260,7 +260,6 @@ export class Audio extends React.Component { }); } - @autobind renderRates() { const { rates, @@ -295,7 +294,6 @@ export class Audio extends React.Component { ) } - @autobind renderPlay() { const {classnames: cx} = this.props; const {playing} = this.state; @@ -309,7 +307,6 @@ export class Audio extends React.Component { ) } - @autobind renderTime() { const {classnames: cx} = this.props; @@ -320,7 +317,6 @@ export class Audio extends React.Component { ) } - @autobind renderProcess() { const {classnames: cx} = this.props; const {played} = this.state; @@ -338,7 +334,6 @@ export class Audio extends React.Component { ) } - @autobind renderVolume() { const {classnames: cx} = this.props; const {