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={{
videoSrc:
'https://gs-files.oss-accelerate.aliyuncs.com/okr/prod/file/2021/08/10/1628605591454mda-met51bhiqb2sgjzd.mp4',
width: 750,
height: 420,
width: 500,
height: 320,
theme: 'red',
poster: 'https://cdn.gudsen.com/2021/06/28/f81356b08b4842d7a3719499f557c8e4.JPG',
pausePlacement: 'center',
}}
/>
<button onClick={() => videoMethod('play')}></button>

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

@ -14,6 +14,7 @@ const Index: FC<switchType> = function Index({ sole, label, onChange, theme }) {
const refs = useRef<HTMLInputElement>(null!);
const switchChange: React.ChangeEventHandler<HTMLInputElement> = (e) => {
e.stopPropagation();
const status = e.target.value === 'yes' ? 'no' : 'yes';
setOn(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 Progress from '../progress';
import Controls from '../controls';
@ -76,6 +76,23 @@ const Index = memo(function Index(props) {
const handlePlay = () => {
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 (
<div
className="JoL-controller-container"
@ -96,6 +113,7 @@ const Index = memo(function Index(props) {
fill="#fff"
fontSize={'47px'}
className="iconfont play-icon"
style={pausePosition}
/>
)}
<div className="JoL-progress-and-controls-wrap">

@ -40,6 +40,7 @@
text-align: center;
line-height: 42px;
&-multiple {
cursor: pointer;
padding: 0 10px;
position: relative;
&-container {
@ -78,6 +79,7 @@
&-volume {
padding: 0 10px;
position: relative;
cursor: pointer;
&:hover {
z-index: 1000000000;
&-layer {
@ -147,6 +149,7 @@
&-set {
padding: 0 10px;
position: relative;
cursor: pointer;
&-container {
@include wh(100%, 70px);
@include position(absolute, -12px, auto, 0, 50%);
@ -155,7 +158,10 @@
}
&:hover {
z-index: 1000000000;
.multifunction-set-layer {
.hover-icon-rotateAnimate {
animation: rotateAnimate 0.5s ease;
}
.JoL-multifunction-set-layer {
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 Broadcast from '@/components/svgIcon';
import Tooltip from '@/components/tooltip';
import { FlowContext, contextType } from '@/core/context';
import { FlowContext } from '@/core/context';
import { useVideo } from '@/core/useVideo';
import { secondsToMinutesAndSecondes, createALabel } from '@/utils';
import { useControls } from './variable';
import useWindowClient from '@/utils/useWindowClient';
import screenfull, { Screenfull } from 'screenfull';
import { multipleList } from '@/core/config';
import { multipleList, defaultVolume } from '@/core/config';
import SetComponent from './set';
import MultipleComponent from './multiple';
import VolumeComponent from './volume';
@ -87,6 +87,7 @@ const Index = memo(function Index(props) {
* @description
*/
const changeCurrentVolume: React.MouseEventHandler<HTMLDivElement> = (e) => {
e.stopPropagation();
const volumeSliderMirrorElement = (
volumeSliderMirror.current as HTMLDivElement & { element: HTMLDivElement }
).element;
@ -99,7 +100,8 @@ const Index = memo(function Index(props) {
updateCurrentVolume(volumePercent);
};
const slideCurrentVolume = () => {
const slideCurrentVolume: React.MouseEventHandler<HTMLDivElement> = (e) => {
e.stopPropagation();
const volumeSliderMirrorElement = (
volumeSliderMirror.current as HTMLDivElement & { element: HTMLDivElement }
).element;
@ -123,7 +125,8 @@ const Index = memo(function Index(props) {
volumeInterval.current && clearInterval(volumeInterval.current);
dispatch({ type: 'isSlideVolume', data: false });
};
const clearVolumeInterval = () => {
const clearVolumeInterval: React.MouseEventHandler<HTMLDivElement> = (e) => {
e.stopPropagation();
whenMouseUpDo();
};
/**
@ -201,6 +204,15 @@ const Index = memo(function Index(props) {
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 (
<div
className="JoL-controls-container"
@ -224,12 +236,21 @@ const Index = memo(function Index(props) {
changeCurrentVolume={changeCurrentVolume}
slideCurrentVolume={slideCurrentVolume}
clearVolumeInterval={clearVolumeInterval}
isMuted={controlsState.isMuted}
toggleVolume={toggleVolume}
/>
<SetComponent switchChange={switchChange} />
<Tooltip
styleCss={{ padding: '0 5px' }}
title="截图"
icon={<Broadcast iconClass="screenshot" fill="#fff" onClick={screenshot} />}
icon={
<Broadcast
iconClass="screenshot"
className="hover-icon-animate"
fill="#fff"
onClick={screenshot}
/>
}
/>
<Tooltip
styleCss={{ padding: '0 5px' }}
@ -238,6 +259,7 @@ const Index = memo(function Index(props) {
<Broadcast
iconClass="fullScreen"
fill="#fff"
className="hover-icon-animate"
fontSize={'20px'}
onClick={pictureInPicture}
/>
@ -250,6 +272,7 @@ const Index = memo(function Index(props) {
<Broadcast
iconClass="fullScreen"
fill="#fff"
className="hover-icon-animate"
fontSize={'20px'}
onClick={clientFullScreen}
/>
@ -264,6 +287,7 @@ const Index = memo(function Index(props) {
fill="#fff"
fontSize={'20px'}
onClick={requestFullScreen}
className="hover-icon-animate"
/>
}
/>

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

@ -1,7 +1,6 @@
import React, { memo, FC, useState, useContext } from 'react';
import Broadcast from '@/components/svgIcon';
import Switch from '@/components/switch';
import { FlowContext } from '@/core/context';
import './index.scss';
@ -19,9 +18,9 @@ const Set: FC<SetType> = memo(function Set({ switchChange }) {
<div
className="JoL-multifunction-set"
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
className="JoL-multifunction-set-container"
style={{ display: isShow ? 'block' : 'none' }}

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

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

Loading…
Cancel
Save