From f68c1ac3e2a013fdc86acd3935101ae0eb7e889b Mon Sep 17 00:00:00 2001 From: ambar Date: Tue, 8 Feb 2022 17:58:39 +0800 Subject: [PATCH] fix: use smooth progress transition --- packages/griffith/src/components/Slider.tsx | 51 ++++++++++++++----- packages/griffith/src/components/Video.tsx | 2 +- .../MinimalTimeline.spec.tsx.snap | 8 ++- .../__snapshots__/VolumeSlide.spec.tsx.snap | 9 ++-- .../__snapshots__/TimelineItem.spec.tsx.snap | 18 +++++-- .../__snapshots__/VolumeItem.spec.tsx.snap | 12 ++++- 6 files changed, 75 insertions(+), 25 deletions(-) diff --git a/packages/griffith/src/components/Slider.tsx b/packages/griffith/src/components/Slider.tsx index 32c84764..f3a2a635 100644 --- a/packages/griffith/src/components/Slider.tsx +++ b/packages/griffith/src/components/Slider.tsx @@ -3,7 +3,6 @@ import {css, StyleDeclarationMap} from 'aphrodite/no-important' import clamp from 'lodash/clamp' import {ProgressDot as ProgressDotType} from '../types' import ProgressDot, {ProgressDotsProps} from './ProgressDot' -import formatPercent from '../utils/formatPercent' import styles, { horizontal as horizontalStyles, @@ -40,6 +39,11 @@ type State = { slidingValue: null | number } +const getRatio = (value: number, total?: number) => + total ? clamp(value / total, 0, 1) : 0 + +const toPercentage = (value: number) => `${value * 100}%` + export type SliderProps = OwnProps //& typeof Slider.defaultProps class Slider extends Component { @@ -109,15 +113,38 @@ class Slider extends Component { return orientation === 'horizontal' ? 'width' : 'height' } - getPercentage() { + getPercentageValue() { const {value, total} = this.props const {isSlideActive, slidingValue} = this.state - return formatPercent(isSlideActive ? slidingValue! : value!, total) + return getRatio(isSlideActive ? slidingValue! : value!, total) + } + + getProgressStyle(value: number) { + const {orientation} = this.props + const scaleAxis = orientation === 'horizontal' ? 'scaleX' : 'scaleY' + return { + [this.getSizeKey()]: '100%', + transform: `${scaleAxis}(${value})`, + transformOrigin: this.getAlignKey(), + } + } + + getProgressThumbStyle(value: number) { + const {orientation} = this.props + const horizontal = orientation === 'horizontal' + const translateAxis = horizontal ? 'translateX' : 'translateY' + return { + [this.getSizeKey()]: '100%', + transform: `${translateAxis}(${toPercentage( + horizontal ? value : 1 - value + )})`, + transformOrigin: this.getAlignKey(), + } } - getBufferedPercentage() { + getBufferedPercentageValue() { const {buffered, total} = this.props - return formatPercent(buffered!, total) + return getRatio(buffered!, total) } getSlidingValue(event: globalThis.MouseEvent) { @@ -239,6 +266,7 @@ class Slider extends Component { onKeyDown: this.handleKeyDown, onMouseDown: this.handleDragStart, } + const ratio = this.getPercentageValue() return (
{ {Boolean(buffered) && (
)}
{Boolean(progressDots?.length) && ( { )}
{!noInteraction && ( + // the position indicator (visible when hovering)
{ } // NOTE: 原生 `timeupdate` 事件更新频率不固定(4Hz~66Hz,由系统决定),这里以 rAF 提高了 UI 更新频率 - // 但进度条更新仍然是不平滑的,需要考虑使用进度动画(TODO) + // TODO: 考虑使用回调直接操作 DOM,减少 React rendering notifyTimeUpdate = (isRaf: boolean) => { const {onCurrentTimeUpdate, paused} = this.props diff --git a/packages/griffith/src/components/__tests__/__snapshots__/MinimalTimeline.spec.tsx.snap b/packages/griffith/src/components/__tests__/__snapshots__/MinimalTimeline.spec.tsx.snap index 779e9e98..7c21f0b6 100644 --- a/packages/griffith/src/components/__tests__/__snapshots__/MinimalTimeline.spec.tsx.snap +++ b/packages/griffith/src/components/__tests__/__snapshots__/MinimalTimeline.spec.tsx.snap @@ -14,7 +14,7 @@ exports[`MinimalTimeline get MinimalTimeline component 1`] = ` >
@@ -37,7 +37,11 @@ exports[`MinimalTimeline get MinimalTimeline component 2`] = ` >
diff --git a/packages/griffith/src/components/__tests__/__snapshots__/VolumeSlide.spec.tsx.snap b/packages/griffith/src/components/__tests__/__snapshots__/VolumeSlide.spec.tsx.snap index 806cb727..08ff4356 100644 --- a/packages/griffith/src/components/__tests__/__snapshots__/VolumeSlide.spec.tsx.snap +++ b/packages/griffith/src/components/__tests__/__snapshots__/VolumeSlide.spec.tsx.snap @@ -21,8 +21,9 @@ exports[`VolumeSlider get VolumeSlider component 1`] = ` className="bar_1kpj1ed-o_O-bar_1ql2ook" style={ Object { - "bottom": 0, - "height": "50%", + "height": "100%", + "transform": "scaleY(0.5)", + "transformOrigin": "bottom", } } /> @@ -31,7 +32,9 @@ exports[`VolumeSlider get VolumeSlider component 1`] = ` className="thumbWrapper_ay4wjb-o_O-thumbWrapper_drkmbm" style={ Object { - "bottom": "50%", + "height": "100%", + "transform": "translateY(50%)", + "transformOrigin": "bottom", } } > diff --git a/packages/griffith/src/components/items/__tests__/__snapshots__/TimelineItem.spec.tsx.snap b/packages/griffith/src/components/items/__tests__/__snapshots__/TimelineItem.spec.tsx.snap index ac660c49..8867b86b 100644 --- a/packages/griffith/src/components/items/__tests__/__snapshots__/TimelineItem.spec.tsx.snap +++ b/packages/griffith/src/components/items/__tests__/__snapshots__/TimelineItem.spec.tsx.snap @@ -15,16 +15,28 @@ exports[`TimelineItem get TimelineItem component 1`] = ` class=" bar_1kpj1ed-o_O-bar_g2nzkb-o_O-bar_1kvrquw-o_O-buffered_gsgvhl " - style="left: 0px; width: 6.417112299465241%" + style=" + width: 100%; + transform: scaleX(0.06417112299465241); + transform-origin: left; + " >
diff --git a/packages/griffith/src/components/items/__tests__/__snapshots__/VolumeItem.spec.tsx.snap b/packages/griffith/src/components/items/__tests__/__snapshots__/VolumeItem.spec.tsx.snap index e28a9467..183749b6 100644 --- a/packages/griffith/src/components/items/__tests__/__snapshots__/VolumeItem.spec.tsx.snap +++ b/packages/griffith/src/components/items/__tests__/__snapshots__/VolumeItem.spec.tsx.snap @@ -22,12 +22,20 @@ exports[`VolumeItem get VolumeItem component 1`] = `