optimize the details

master
lgf 3 years ago
parent 08c2bf0b45
commit 872af4b6d7
  1. 5
      src/appComponent.tsx
  2. 16
      src/assets/css/mixin.scss
  3. 4
      src/components/svgIcon/index.tsx
  4. 1
      src/components/switch/index.tsx
  5. 20
      src/core/controller/index.tsx
  6. 13
      src/core/controls/index.scss
  7. 34
      src/core/controls/index.tsx
  8. 6
      src/core/controls/multiple.tsx
  9. 5
      src/core/controls/set.tsx
  10. 14
      src/core/controls/variable.ts
  11. 18
      src/core/controls/volume.tsx

@ -94,10 +94,11 @@ const AppComponent = memo(function AppComponent(props) {
option={{ option={{
videoSrc: videoSrc:
'https://gs-files.oss-accelerate.aliyuncs.com/okr/prod/file/2021/08/10/1628605591454mda-met51bhiqb2sgjzd.mp4', 'https://gs-files.oss-accelerate.aliyuncs.com/okr/prod/file/2021/08/10/1628605591454mda-met51bhiqb2sgjzd.mp4',
width: 750, width: 500,
height: 420, height: 320,
theme: 'red', theme: 'red',
poster: 'https://cdn.gudsen.com/2021/06/28/f81356b08b4842d7a3719499f557c8e4.JPG', poster: 'https://cdn.gudsen.com/2021/06/28/f81356b08b4842d7a3719499f557c8e4.JPG',
pausePlacement: 'center',
}} }}
/> />
<button onClick={() => videoMethod('play')}></button> <button onClick={() => videoMethod('play')}></button>

@ -37,3 +37,19 @@
opacity: 1; opacity: 1;
} }
} }
@keyframes scaleAnimate {
50% {
transform: scale(1.2);
}
100% {
transform: scale(1);
}
}
@keyframes rotateAnimate {
0% {
transform: rotate(270deg);
}
100% {
transform: rotate(360deg);
}
}

@ -4,6 +4,7 @@ export type svgProps = {
fill?: string; fill?: string;
fontSize?: string; fontSize?: string;
className?: string; className?: string;
style?: React.CSSProperties;
onClick?: React.MouseEventHandler<SVGSVGElement>; onClick?: React.MouseEventHandler<SVGSVGElement>;
}; };
@ -13,12 +14,13 @@ const SvgIcon: React.FC<svgProps> = memo(function SvgIcon({
fontSize = '18px', fontSize = '18px',
className, className,
onClick, onClick,
style,
}) { }) {
const iconName = useMemo(() => '#icon-' + iconClass, [iconClass]); const iconName = useMemo(() => '#icon-' + iconClass, [iconClass]);
return ( return (
<svg <svg
fontSize={fontSize!} fontSize={fontSize!}
style={{ ...svgStyle, fontSize }} style={{ ...svgStyle, fontSize, ...style }}
aria-hidden="true" aria-hidden="true"
className={className!} className={className!}
onClick={onClick} onClick={onClick}

@ -14,6 +14,7 @@ const Index: FC<switchType> = function Index({ sole, label, onChange, theme }) {
const refs = useRef<HTMLInputElement>(null!); const refs = useRef<HTMLInputElement>(null!);
const switchChange: React.ChangeEventHandler<HTMLInputElement> = (e) => { const switchChange: React.ChangeEventHandler<HTMLInputElement> = (e) => {
e.stopPropagation();
const status = e.target.value === 'yes' ? 'no' : 'yes'; const status = e.target.value === 'yes' ? 'no' : 'yes';
setOn(status); setOn(status);
onChange && onChange(status); onChange && onChange(status);

@ -1,4 +1,4 @@
import React, { memo, useContext, useRef, useState } from 'react'; import React, { memo, useContext, useRef, useState, useMemo } from 'react';
import Broadcast from '@/components/svgIcon'; import Broadcast from '@/components/svgIcon';
import Progress from '../progress'; import Progress from '../progress';
import Controls from '../controls'; import Controls from '../controls';
@ -76,6 +76,23 @@ const Index = memo(function Index(props) {
const handlePlay = () => { const handlePlay = () => {
handleChangePlayState && handleChangePlayState(); handleChangePlayState && handleChangePlayState();
}; };
/**
* @description
*/
const pausePosition = useMemo(() => {
if (propsAttributes!.pausePlacement === 'center') {
return {
left: '50%',
top: '50%',
transform: 'translate(-50%, -50%)',
};
} else {
return {
right: '30px',
bottom: '60px',
};
}
}, [propsAttributes!.pausePlacement]);
return ( return (
<div <div
className="JoL-controller-container" className="JoL-controller-container"
@ -96,6 +113,7 @@ const Index = memo(function Index(props) {
fill="#fff" fill="#fff"
fontSize={'47px'} fontSize={'47px'}
className="iconfont play-icon" className="iconfont play-icon"
style={pausePosition}
/> />
)} )}
<div className="JoL-progress-and-controls-wrap"> <div className="JoL-progress-and-controls-wrap">

@ -40,6 +40,7 @@
text-align: center; text-align: center;
line-height: 42px; line-height: 42px;
&-multiple { &-multiple {
cursor: pointer;
padding: 0 10px; padding: 0 10px;
position: relative; position: relative;
&-container { &-container {
@ -78,6 +79,7 @@
&-volume { &-volume {
padding: 0 10px; padding: 0 10px;
position: relative; position: relative;
cursor: pointer;
&:hover { &:hover {
z-index: 1000000000; z-index: 1000000000;
&-layer { &-layer {
@ -147,6 +149,7 @@
&-set { &-set {
padding: 0 10px; padding: 0 10px;
position: relative; position: relative;
cursor: pointer;
&-container { &-container {
@include wh(100%, 70px); @include wh(100%, 70px);
@include position(absolute, -12px, auto, 0, 50%); @include position(absolute, -12px, auto, 0, 50%);
@ -155,7 +158,10 @@
} }
&:hover { &:hover {
z-index: 1000000000; z-index: 1000000000;
.multifunction-set-layer { .hover-icon-rotateAnimate {
animation: rotateAnimate 0.5s ease;
}
.JoL-multifunction-set-layer {
animation: show 0.3s ease; animation: show 0.3s ease;
} }
} }
@ -176,4 +182,9 @@
} }
} }
} }
.hover-icon-animate {
&:hover {
animation: scaleAnimate 0.5s ease;
}
}
} }

@ -1,13 +1,13 @@
import React, { memo, useContext, useRef, useEffect, useMemo, useCallback } from 'react'; import React, { memo, useContext, useRef, useEffect, useMemo, useCallback } from 'react';
import Broadcast from '@/components/svgIcon'; import Broadcast from '@/components/svgIcon';
import Tooltip from '@/components/tooltip'; import Tooltip from '@/components/tooltip';
import { FlowContext, contextType } from '@/core/context'; import { FlowContext } from '@/core/context';
import { useVideo } from '@/core/useVideo'; import { useVideo } from '@/core/useVideo';
import { secondsToMinutesAndSecondes, createALabel } from '@/utils'; import { secondsToMinutesAndSecondes, createALabel } from '@/utils';
import { useControls } from './variable'; import { useControls } from './variable';
import useWindowClient from '@/utils/useWindowClient'; import useWindowClient from '@/utils/useWindowClient';
import screenfull, { Screenfull } from 'screenfull'; import screenfull, { Screenfull } from 'screenfull';
import { multipleList } from '@/core/config'; import { multipleList, defaultVolume } from '@/core/config';
import SetComponent from './set'; import SetComponent from './set';
import MultipleComponent from './multiple'; import MultipleComponent from './multiple';
import VolumeComponent from './volume'; import VolumeComponent from './volume';
@ -87,6 +87,7 @@ const Index = memo(function Index(props) {
* @description * @description
*/ */
const changeCurrentVolume: React.MouseEventHandler<HTMLDivElement> = (e) => { const changeCurrentVolume: React.MouseEventHandler<HTMLDivElement> = (e) => {
e.stopPropagation();
const volumeSliderMirrorElement = ( const volumeSliderMirrorElement = (
volumeSliderMirror.current as HTMLDivElement & { element: HTMLDivElement } volumeSliderMirror.current as HTMLDivElement & { element: HTMLDivElement }
).element; ).element;
@ -99,7 +100,8 @@ const Index = memo(function Index(props) {
updateCurrentVolume(volumePercent); updateCurrentVolume(volumePercent);
}; };
const slideCurrentVolume = () => { const slideCurrentVolume: React.MouseEventHandler<HTMLDivElement> = (e) => {
e.stopPropagation();
const volumeSliderMirrorElement = ( const volumeSliderMirrorElement = (
volumeSliderMirror.current as HTMLDivElement & { element: HTMLDivElement } volumeSliderMirror.current as HTMLDivElement & { element: HTMLDivElement }
).element; ).element;
@ -123,7 +125,8 @@ const Index = memo(function Index(props) {
volumeInterval.current && clearInterval(volumeInterval.current); volumeInterval.current && clearInterval(volumeInterval.current);
dispatch({ type: 'isSlideVolume', data: false }); dispatch({ type: 'isSlideVolume', data: false });
}; };
const clearVolumeInterval = () => { const clearVolumeInterval: React.MouseEventHandler<HTMLDivElement> = (e) => {
e.stopPropagation();
whenMouseUpDo(); whenMouseUpDo();
}; };
/** /**
@ -201,6 +204,15 @@ const Index = memo(function Index(props) {
dispatch({ type: 'isWebPageFullScreen', data: true }); dispatch({ type: 'isWebPageFullScreen', data: true });
} }
}; };
/**
* @description
*/
const toggleVolume = () => {
reviceProps.videoRef!.volume = controlsState.isMuted ? defaultVolume / 100 : 0;
dispatch({ type: 'isMuted', data: controlsState.isMuted ? false : true });
reviceProps.videoRef!.muted = controlsState.isMuted ? false : true;
};
return ( return (
<div <div
className="JoL-controls-container" className="JoL-controls-container"
@ -224,12 +236,21 @@ const Index = memo(function Index(props) {
changeCurrentVolume={changeCurrentVolume} changeCurrentVolume={changeCurrentVolume}
slideCurrentVolume={slideCurrentVolume} slideCurrentVolume={slideCurrentVolume}
clearVolumeInterval={clearVolumeInterval} clearVolumeInterval={clearVolumeInterval}
isMuted={controlsState.isMuted}
toggleVolume={toggleVolume}
/> />
<SetComponent switchChange={switchChange} /> <SetComponent switchChange={switchChange} />
<Tooltip <Tooltip
styleCss={{ padding: '0 5px' }} styleCss={{ padding: '0 5px' }}
title="截图" title="截图"
icon={<Broadcast iconClass="screenshot" fill="#fff" onClick={screenshot} />} icon={
<Broadcast
iconClass="screenshot"
className="hover-icon-animate"
fill="#fff"
onClick={screenshot}
/>
}
/> />
<Tooltip <Tooltip
styleCss={{ padding: '0 5px' }} styleCss={{ padding: '0 5px' }}
@ -238,6 +259,7 @@ const Index = memo(function Index(props) {
<Broadcast <Broadcast
iconClass="fullScreen" iconClass="fullScreen"
fill="#fff" fill="#fff"
className="hover-icon-animate"
fontSize={'20px'} fontSize={'20px'}
onClick={pictureInPicture} onClick={pictureInPicture}
/> />
@ -250,6 +272,7 @@ const Index = memo(function Index(props) {
<Broadcast <Broadcast
iconClass="fullScreen" iconClass="fullScreen"
fill="#fff" fill="#fff"
className="hover-icon-animate"
fontSize={'20px'} fontSize={'20px'}
onClick={clientFullScreen} onClick={clientFullScreen}
/> />
@ -264,6 +287,7 @@ const Index = memo(function Index(props) {
fill="#fff" fill="#fff"
fontSize={'20px'} fontSize={'20px'}
onClick={requestFullScreen} onClick={requestFullScreen}
className="hover-icon-animate"
/> />
} }
/> />

@ -23,8 +23,8 @@ const Multiple: FC<MultipleType> = memo(function Multiple({
return ( return (
<div <div
className="JoL-multifunction-multiple" className="JoL-multifunction-multiple"
onMouseEnter={(e) => [setIsShow(true), e.stopPropagation()]} onClick={(e) => setIsShow((pre) => !pre)}
onMouseLeave={(e) => [setIsShow(false), e.stopPropagation()]} onMouseLeave={(e) => [setIsShow(false)]}
> >
<p>{multipleText}</p> <p>{multipleText}</p>
<div <div
@ -34,7 +34,7 @@ const Multiple: FC<MultipleType> = memo(function Multiple({
<ul className="JoL-multifunction-multiple-layer"> <ul className="JoL-multifunction-multiple-layer">
{multipleList.map((item, index) => ( {multipleList.map((item, index) => (
<li <li
onClick={() => [selectPlayRate(item.id), setIsShow(false)]} onClick={(e) => [selectPlayRate(item.id), setIsShow(false), e.stopPropagation()]}
key={index} key={index}
style={{ color: multiple === item.id ? (theme ? theme : defaultTheme) : '#fff' }} style={{ color: multiple === item.id ? (theme ? theme : defaultTheme) : '#fff' }}
> >

@ -1,7 +1,6 @@
import React, { memo, FC, useState, useContext } from 'react'; import React, { memo, FC, useState, useContext } from 'react';
import Broadcast from '@/components/svgIcon'; import Broadcast from '@/components/svgIcon';
import Switch from '@/components/switch'; import Switch from '@/components/switch';
import { FlowContext } from '@/core/context'; import { FlowContext } from '@/core/context';
import './index.scss'; import './index.scss';
@ -19,9 +18,9 @@ const Set: FC<SetType> = memo(function Set({ switchChange }) {
<div <div
className="JoL-multifunction-set" className="JoL-multifunction-set"
onMouseEnter={(e) => [setIsShow(true), e.stopPropagation()]} onMouseEnter={(e) => [setIsShow(true), e.stopPropagation()]}
onMouseLeave={(e) => [setIsShow(false), e.stopPropagation()]} onMouseLeave={(e) => [setIsShow(false)]}
> >
<Broadcast iconClass="set" fill="#fff" /> <Broadcast iconClass="set" fill="#fff" className="hover-icon-rotateAnimate" />
<div <div
className="JoL-multifunction-set-container" className="JoL-multifunction-set-container"
style={{ display: isShow ? 'block' : 'none' }} style={{ display: isShow ? 'block' : 'none' }}

@ -25,6 +25,10 @@ export interface controlsVariableType<T = number, K = boolean> {
* @description * @description
*/ */
isWebPageFullScreen: K; isWebPageFullScreen: K;
/**
* @description
*/
isMute: K;
} }
export interface volumeActionType { export interface volumeActionType {
@ -51,13 +55,18 @@ export interface isWebPageFullScreenActionType {
type: 'isWebPageFullScreen'; type: 'isWebPageFullScreen';
data: controlsVariableType['isWebPageFullScreen']; data: controlsVariableType['isWebPageFullScreen'];
} }
export interface isMuteActionType {
type: 'isMute';
data: controlsVariableType['isMute'];
}
export type mergeAction = export type mergeAction =
| volumeActionType | volumeActionType
| isMutedActionType | isMutedActionType
| isSlideVolumeActionType | isSlideVolumeActionType
| isScreentFullActionType | isScreentFullActionType
| multipleActionType | multipleActionType
| isWebPageFullScreenActionType; | isWebPageFullScreenActionType
| isMuteActionType;
export const useControls = () => { export const useControls = () => {
const initialState = { const initialState = {
@ -67,6 +76,7 @@ export const useControls = () => {
isScreentFull: false, isScreentFull: false,
multiple: 1.0, multiple: 1.0,
isWebPageFullScreen: false, isWebPageFullScreen: false,
isMute: false,
}; };
const reducer = (state: controlsVariableType, action: mergeAction) => { const reducer = (state: controlsVariableType, action: mergeAction) => {
@ -83,6 +93,8 @@ export const useControls = () => {
return { ...state, multiple: action.data }; return { ...state, multiple: action.data };
case 'isWebPageFullScreen': case 'isWebPageFullScreen':
return { ...state, isWebPageFullScreen: action.data }; return { ...state, isWebPageFullScreen: action.data };
case 'isMute':
return { ...state, isMute: action.data };
default: default:
return state; return state;
} }

@ -6,13 +6,22 @@ import './index.scss';
export interface VolumeType { export interface VolumeType {
volume: number; volume: number;
isMuted: boolean;
changeCurrentVolume: React.MouseEventHandler<HTMLDivElement>; changeCurrentVolume: React.MouseEventHandler<HTMLDivElement>;
slideCurrentVolume: React.MouseEventHandler<HTMLDivElement>; slideCurrentVolume: React.MouseEventHandler<HTMLDivElement>;
clearVolumeInterval: React.MouseEventHandler<HTMLDivElement>; clearVolumeInterval: React.MouseEventHandler<HTMLDivElement>;
toggleVolume: Function;
} }
const Volume = function Volume( const Volume = function Volume(
{ volume, changeCurrentVolume, slideCurrentVolume, clearVolumeInterval }: VolumeType, {
volume,
changeCurrentVolume,
slideCurrentVolume,
clearVolumeInterval,
isMuted,
toggleVolume,
}: VolumeType,
ref: React.Ref<unknown> | undefined, ref: React.Ref<unknown> | undefined,
) { ) {
const volumeSliderMirror = useRef<HTMLDivElement>(null); const volumeSliderMirror = useRef<HTMLDivElement>(null);
@ -30,10 +39,11 @@ const Volume = function Volume(
return ( return (
<div <div
className="JoL-multifunction-volume" className="JoL-multifunction-volume"
onMouseEnter={(e) => [setIsShow(true), e.stopPropagation()]} onMouseEnter={(e) => [setIsShow(true)]}
onMouseLeave={(e) => [setIsShow(false), e.stopPropagation()]} onMouseLeave={(e) => [setIsShow(false)]}
onClick={(e) => [toggleVolume()]}
> >
<Broadcast iconClass="volume" fill="#fff" fontSize={'20px'} /> <Broadcast iconClass={isMuted ? 'set' : 'volume'} fill="#fff" fontSize={'20px'} />
<div <div
className="JoL-multifunction-volume-container" className="JoL-multifunction-volume-container"
style={{ display: isShow ? 'block' : 'none' }} style={{ display: isShow ? 'block' : 'none' }}

Loading…
Cancel
Save