chore: slider to change width and height in image

This commit is contained in:
jialin
2024-12-02 08:20:30 +08:00
parent 412c6dadca
commit ec2cd29096
24 changed files with 500 additions and 283 deletions
+99 -21
View File
@@ -1,10 +1,11 @@
import React, {
forwardRef,
useCallback,
useEffect,
useImperativeHandle,
useRef
} from 'react';
import useWavesurfer from './hooks/use-wavesurfer';
import WaveSurfer, { WaveSurferOptions } from 'wavesurfer.js';
interface AudioPlayerProps {
autoplay: boolean;
@@ -15,27 +16,104 @@ interface AudioPlayerProps {
width?: number;
onReady?: () => void;
onClick?: (value: number) => void;
onFinish?: () => void;
onAnalyse?: (analyseData: any, frequencyBinCount: any) => void;
}
const AudioPlayer: React.FC<AudioPlayerProps> = forwardRef((props, ref) => {
const AudioPlayer: React.FC<
AudioPlayerProps & Omit<WaveSurferOptions, 'container'>
> = forwardRef((props, ref) => {
const { autoplay, audioUrl, speed = 1, ...rest } = props;
const container = useRef<HTMLDivElement>(null);
const {
createWavesurfer,
play,
pause,
duration,
destroyWavesurfer,
wavesurfer
} = useWavesurfer({
container,
autoplay: autoplay,
url: audioUrl,
audioRate: speed,
onReady: props.onReady,
onClick: props.onClick,
...rest
});
const wavesurfer = useRef<WaveSurfer | null>(null);
const container = useRef<any>(null);
const audioContext = useRef<any>(null);
const analyser = useRef<any>(null);
const dataArray = useRef<any>(null);
const audioStream = useRef<any>(null);
const mediaElement = useRef<any>(null);
const initAudioContext = useCallback(() => {
audioContext.current = new (window.AudioContext ||
window.webkitAudioContext)();
analyser.current = audioContext.current.createAnalyser();
analyser.current.fftSize = 512;
dataArray.current = new Uint8Array(analyser.current.frequencyBinCount);
}, []);
const generateVisualData = useCallback(() => {
const source = audioContext.current.createMediaElementSource(
mediaElement.current
);
source.connect(analyser.current);
analyser.current.connect(audioContext.current.destination);
}, []);
const listenEvents = () => {
wavesurfer.current?.on('ready', () => {
props.onReady?.();
});
wavesurfer.current?.on('click', (value) => {
props.onClick?.(value);
});
wavesurfer.current?.on('finish', () => {
props.onFinish?.();
});
wavesurfer.current?.on('play', () => {
// analyser.current?.getByteFrequencyData(dataArray.current);
// props.onAnalyse?.(dataArray.current, analyser);
});
};
const createWavesurfer = () => {
wavesurfer.current = WaveSurfer.create({
container: container.current,
url: audioUrl,
autoplay: autoplay,
audioRate: speed,
waveColor: '#4096ff',
progressColor: 'rgb(100, 0, 100)',
height: 60,
barWidth: 2,
barGap: 1,
barRadius: 2,
interact: true,
cursorWidth: 0,
...rest
});
mediaElement.current = wavesurfer.current?.getMediaElement();
initAudioContext();
generateVisualData();
listenEvents();
};
const destroyWavesurfer = () => {
if (wavesurfer.current) {
wavesurfer.current.destroy();
}
};
const play = () => {
if (wavesurfer.current) {
wavesurfer.current.play();
}
};
const duration = () => {
if (wavesurfer.current) {
return wavesurfer.current.getDuration();
}
return 0;
};
const pause = () => {
if (wavesurfer.current) {
wavesurfer.current.pause();
}
};
useImperativeHandle(ref, () => {
return {
@@ -46,13 +124,13 @@ const AudioPlayer: React.FC<AudioPlayerProps> = forwardRef((props, ref) => {
});
useEffect(() => {
if (container.current) {
if (container.current && audioUrl) {
createWavesurfer();
}
return () => {
destroyWavesurfer();
};
}, [container.current]);
}, [audioUrl, container.current]);
return <div ref={container} className="audio-container"></div>;
});
@@ -1,86 +0,0 @@
import { useRef } from 'react';
import WaveSurfer from 'wavesurfer.js';
interface Options {
container: React.RefObject<HTMLDivElement>;
waveColor?: string;
progressColor?: string;
url: string;
barWidth?: number;
barGap?: number;
barRadius?: number;
autoplay?: boolean;
audioRate?: number;
onReady?: () => void;
onClick: (value: number) => void;
}
const useWavesurfer = (options: Options) => {
const wavesurfer = useRef<WaveSurfer | null>(null);
const { container, url, ...rest } = options;
const createWavesurfer = () => {
if (!container.current) {
return;
}
if (wavesurfer.current) {
wavesurfer.current.destroy();
}
wavesurfer.current = WaveSurfer.create({
container: container.current,
waveColor: '#4096ff',
progressColor: 'rgb(100, 0, 100)',
url: url,
height: 60,
barWidth: 2,
barGap: 1,
barRadius: 2,
interact: true,
cursorWidth: 0,
...rest
});
wavesurfer.current?.on('ready', () => {
options.onReady?.();
});
wavesurfer.current?.on('click', (value) => {
options.onClick?.(value);
});
};
const destroyWavesurfer = () => {
if (wavesurfer.current) {
wavesurfer.current.destroy();
}
};
const play = () => {
if (wavesurfer.current) {
wavesurfer.current.play();
}
};
const duration = () => {
if (wavesurfer.current) {
return wavesurfer.current.getDuration();
}
return 0;
};
const pause = () => {
if (wavesurfer.current) {
wavesurfer.current.pause();
}
};
return {
createWavesurfer,
play,
pause,
wavesurfer,
duration,
destroyWavesurfer
};
};
export default useWavesurfer;
+21 -3
View File
@@ -37,9 +37,13 @@ interface SpeechContentProps {
const SpeechItem: React.FC<SpeechContentProps> = (props) => {
const intl = useIntl();
const [collapsed, setCollapsed] = useState(false);
const [isPlay, setIsPlay] = useState(false);
const [isPlay, setIsPlay] = useState(props.autoplay);
const [duration, setDuration] = useState(0);
const [currentTime, setCurrentTime] = useState(0);
const [audioChunks, setAudioChunks] = useState<any>({
data: [],
analyser: null
});
const ref = useRef<any>(null);
const handlePlay = () => {
@@ -52,8 +56,13 @@ const SpeechItem: React.FC<SpeechContentProps> = (props) => {
setIsPlay(true);
};
const handleCollapse = () => {
setCollapsed(!collapsed);
const handleOnAnalyse = (data: any, analyser: any) => {
setAudioChunks((pre: any) => {
return {
data: data,
analyser: analyser
};
});
};
const handleReay = () => {
@@ -80,6 +89,13 @@ const SpeechItem: React.FC<SpeechContentProps> = (props) => {
return (
<div>
<div className="speech-item">
{/* {isPlay && (
<AudioAnimation
height={82}
width={500}
analyserData={audioChunks}
></AudioAnimation>
)} */}
<div className="voice">
<IconFont type="icon-user_voice" className="font-size-16" />
</div>
@@ -89,6 +105,8 @@ const SpeechItem: React.FC<SpeechContentProps> = (props) => {
audioUrl={props.audioUrl}
onReady={handleReay}
onClick={handleOnClick}
onFinish={() => setIsPlay(false)}
onAnalyse={handleOnAnalyse}
ref={ref}
></AudioPlayer>
</div>