custom audio player
change the defaut html audio player to a custom player
This commit is contained in:
parent
f8462dbb84
commit
d7eef09946
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
|
@ -0,0 +1,13 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg width="100%" height="100%" viewBox="0 0 256 256" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;">
|
||||
<g>
|
||||
<g>
|
||||
<g>
|
||||
<path d="M114.7,10.6C80.5,14.5 49.1,34 29.4,63.5C25.2,69.9 18.4,83.8 15.9,91.1C8,115.2 8,140.8 16.1,165.1C33.5,217 85.2,250.8 139.3,245.4C183.9,241 223.1,210.6 238.9,168.2C246.2,148.4 248,125.3 243.7,104.4C233.7,55.6 192.3,17.2 142.7,10.9C135.6,9.9 121.7,9.8 114.7,10.6ZM140.5,19C196.1,25 237.5,71.6 237.5,128.1C237.5,165.1 219.6,198.8 189,219.3C167.9,233.4 141.1,239.8 115,236.8C77.7,232.5 46,210.1 29.6,176.5C14.7,146.2 14.8,109.6 29.7,79.3C35.3,67.7 41,59.8 50.4,50.3C67.4,33 90.5,21.8 114.9,19C120.9,18.3 134.3,18.3 140.5,19Z" style="fill:rgb(64,124,222);fill-rule:nonzero;stroke:rgb(64,124,222);stroke-width:1px;"/>
|
||||
<path d="M104.3,86.7C104.1,87.1 104.1,104.9 104.1,126.3L104.3,165.2L118.9,165.2L118.9,86.3L111.7,86.1C106.3,86 104.5,86.2 104.3,86.7Z" style="fill:rgb(64,124,222);fill-rule:nonzero;stroke:rgb(64,124,222);stroke-width:1px;"/>
|
||||
<path d="M136.6,87.3C136.4,88.4 136.4,149.5 136.7,162L136.8,165.5L144.3,165.3L151.7,165.1L151.7,86.3L144.3,86.1C136.9,86 136.8,86 136.6,87.3Z" style="fill:rgb(64,124,222);fill-rule:nonzero;stroke:rgb(64,124,222);stroke-width:1px;"/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.6 KiB |
|
|
@ -0,0 +1,12 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg width="100%" height="100%" viewBox="0 0 256 256" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;">
|
||||
<g>
|
||||
<g>
|
||||
<g>
|
||||
<path d="M115,10.4C93.4,12.8 72.1,21.7 54.5,35.4C49.4,39.5 40,48.8 35.7,54.2C22.7,70.3 14.1,90.4 10.9,111.5C9.7,120.1 9.7,136 10.9,144.5C15.3,174 29.7,199.7 52.8,219C78.4,240.4 113.5,250.1 146.3,244.8C197.7,236.4 237.4,196.2 245.1,144.7C246.3,136.3 246.3,119.9 245.1,111.4C241.4,86.2 230.7,64.4 213,46.1C202.5,35.2 192.4,27.9 179.3,21.6C159.4,12 136.4,8 115,10.4ZM146,20.7C193.8,29.3 229.1,65.9 235.9,114.2C236.8,120.8 236.7,136.8 235.6,143.7C230.8,174.4 214.5,200.4 189.1,217.8C168.3,232 142.2,238.7 117.3,236.2C78.4,232.3 44.2,207.5 28.6,172C21.3,155.4 18.5,139.2 19.6,120.5C21.5,86.8 40.8,54.3 69.6,36.2C82.5,28.1 98,22.3 111.8,20.4C114.4,20 117.3,19.6 118.3,19.5C122.1,19.1 140.9,19.8 146,20.7Z" style="fill:rgb(64,124,222);fill-rule:nonzero;stroke:rgb(64,124,222);stroke-width:1px;"/>
|
||||
<path d="M110,81.1C106.9,82.4 107,80.4 107,128.1L107,172.5L108.3,173.9C109.1,174.7 110.4,175.2 111.6,175.2C113.4,175.2 116.8,172.5 139.5,153.8C153.7,142 165.9,131.8 166.5,131.2C167,130.6 167.5,129.1 167.5,128.1C167.5,127 167,125.6 166.5,125C165.9,124.4 155.1,115.3 142.4,104.8C129.8,94.4 118.2,84.8 116.7,83.6C113.8,81 111.8,80.3 110,81.1ZM136.7,112.3C146.9,120.7 155.3,127.8 155.3,127.9C155.4,128.1 148,134.4 138.9,141.9C129.8,149.5 121.1,156.6 119.6,157.9L116.8,160.3L116.8,128C116.8,102.2 117,95.9 117.6,96.3C117.9,96.7 126.6,103.9 136.7,112.3Z" style="fill:rgb(64,124,222);fill-rule:nonzero;stroke:rgb(64,124,222);stroke-width:1px;"/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.9 KiB |
|
|
@ -11,3 +11,4 @@
|
|||
@import './custom/chips';
|
||||
@import './custom/common';
|
||||
@import './custom/partner_agreement_v1';
|
||||
@import './custom/audio_player';
|
||||
|
|
|
|||
|
|
@ -0,0 +1,135 @@
|
|||
|
||||
.audio-player {
|
||||
height: 30px;
|
||||
background: #ffffff;
|
||||
//box-shadow: 0 0 20px 0 #000a;
|
||||
font-family: arial;
|
||||
color: #1b1a1a;
|
||||
font-size: 0.75em;
|
||||
overflow: hidden;
|
||||
// display: grid;
|
||||
// grid-template-rows: 6px auto;
|
||||
}
|
||||
|
||||
.audio-player .controls {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: stretch;
|
||||
padding: 0;
|
||||
gap: 2px;
|
||||
}
|
||||
.audio-player .controls > * {
|
||||
display: flex;
|
||||
// justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.audio-player .controls .timeline {
|
||||
margin-top: auto;
|
||||
margin-bottom: auto;
|
||||
margin-left: 5px;
|
||||
margin-right: 5px;
|
||||
background: rgb(14, 157, 223);
|
||||
width: 100%;
|
||||
height: 4px;
|
||||
cursor: pointer;
|
||||
//box-shadow: 0 2px 10px 0 #0008;
|
||||
}
|
||||
.audio-player .controls .timeline .progress {
|
||||
background: coral;
|
||||
width: 0%;
|
||||
height: 100%;
|
||||
transition: 0.25s;
|
||||
}
|
||||
|
||||
|
||||
|
||||
.audio-player .controls .play-pause-button{
|
||||
background: "none";
|
||||
border: "none";
|
||||
cursor: "pointer";
|
||||
outline: "none";
|
||||
left: 0;
|
||||
|
||||
}
|
||||
.audio-player .controls .time {
|
||||
display: flex;
|
||||
}
|
||||
.audio-player .controls .time > * {
|
||||
padding: 2px;
|
||||
}
|
||||
.audio-player .controls .volume-container {
|
||||
margin-right: 5px;
|
||||
cursor: pointer;
|
||||
position: relative;
|
||||
z-index: 2;
|
||||
width: 30px;
|
||||
}
|
||||
.audio-player .controls .volume-container .volume-button {
|
||||
height: 26px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
.audio-player .controls .volume-container .volume-button .volume {
|
||||
transform: scale(1.4);
|
||||
}
|
||||
.audio-player .controls .volume-container .volume-slider {
|
||||
position: absolute;
|
||||
left: -4px;
|
||||
top: 12px;
|
||||
z-index: -1;
|
||||
width: 0;
|
||||
height: 10px;
|
||||
background: white;
|
||||
box-shadow: 0 0 10px #000a;
|
||||
transition: 0.25s;
|
||||
}
|
||||
.audio-player .controls .volume-container .volume-slider .volume-percentage {
|
||||
background: coral;
|
||||
height: 100%;
|
||||
width: 75%;
|
||||
}
|
||||
.audio-player .controls .volume-container:hover .volume-slider {
|
||||
left: -123px;
|
||||
width: 120px;
|
||||
}
|
||||
|
||||
// .audio-player .controls .toggle-play.play {
|
||||
// cursor: pointer;
|
||||
// position: relative;
|
||||
// left: 0;
|
||||
// height: 0;
|
||||
// width: 0;
|
||||
// border: 7px solid #0000;
|
||||
// border-left: 13px solid white;
|
||||
// }
|
||||
// .audio-player .controls .toggle-play.play:hover {
|
||||
// transform: scale(1.1);
|
||||
// }
|
||||
// .audio-player .controls .toggle-play.pause {
|
||||
// height: 15px;
|
||||
// width: 20px;
|
||||
// cursor: pointer;
|
||||
// position: relative;
|
||||
// }
|
||||
// .audio-player .controls .toggle-play.pause:before {
|
||||
// position: absolute;
|
||||
// top: 0;
|
||||
// left: 0px;
|
||||
// background: white;
|
||||
// content: "";
|
||||
// height: 15px;
|
||||
// width: 3px;
|
||||
// }
|
||||
// .audio-player .controls .toggle-play.pause:after {
|
||||
// position: absolute;
|
||||
// top: 0;
|
||||
// right: 8px;
|
||||
// background: white;
|
||||
// content: "";
|
||||
// height: 15px;
|
||||
// width: 3px;
|
||||
// }
|
||||
// .audio-player .controls .toggle-play.pause:hover {
|
||||
// transform: scale(1.1);
|
||||
// }
|
||||
|
|
@ -0,0 +1,169 @@
|
|||
import React, { useRef, useEffect, useState } from 'react';
|
||||
import playIcon from '../../assets/img/icons/play-icon.svg';
|
||||
import pauseIcon from '../../assets/img/icons/pause-icon.svg';
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||
|
||||
const JKAudioPlayer = ({ audioUrl }) => {
|
||||
|
||||
const audioPlayer = useRef(null);
|
||||
|
||||
const [audio, setAudio] = useState(null);
|
||||
const [isPlaying, setIsPlaying] = useState(false);
|
||||
const [isMuted, setIsMuted] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
if (!audioUrl) return;
|
||||
console.log('audioUrl: ' + audioUrl)
|
||||
if (audio) { stopAudio(); }
|
||||
|
||||
const audio = new Audio(audioUrl);
|
||||
setAudio(audio);
|
||||
|
||||
}, [audioUrl]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!audio || !audioPlayer) return;
|
||||
stopAudio();
|
||||
const audioLoadedDataEventListener = audio.addEventListener("loadeddata", () => {
|
||||
audioPlayer.current.querySelector(".time .length").textContent = getTimeCodeFromNum(
|
||||
audio.duration
|
||||
);
|
||||
audio.volume = .75;
|
||||
});
|
||||
|
||||
const audioPercentageCheckInterval = setInterval(() => {
|
||||
const progressBar = audioPlayer.current.querySelector(".progress");
|
||||
progressBar.style.width = audio.currentTime / audio.duration * 100 + "%";
|
||||
audioPlayer.current.querySelector(".time .current").textContent = getTimeCodeFromNum(
|
||||
audio.currentTime
|
||||
);
|
||||
}, 500);
|
||||
|
||||
//audio.play();
|
||||
|
||||
return () => {
|
||||
stopAudio();
|
||||
audio.removeEventListener("loadeddata", audioLoadedDataEventListener);
|
||||
clearInterval(audioPercentageCheckInterval);
|
||||
}
|
||||
}, [audio, audioPlayer]);
|
||||
|
||||
const stopAudio = () => {
|
||||
if (!audio) return;
|
||||
audio.pause();
|
||||
audio.currentTime = 0;
|
||||
setIsPlaying(false);
|
||||
}
|
||||
|
||||
const togglePlayPause = (e) => {
|
||||
if (!audio) return;
|
||||
if (audio.paused) {
|
||||
audio.play();
|
||||
setIsPlaying(true);
|
||||
} else {
|
||||
audio.pause();
|
||||
setIsPlaying(false);
|
||||
}
|
||||
}
|
||||
|
||||
const onVolumeButtonClick = () => {
|
||||
if (!audio) return;
|
||||
audio.muted = !audio.muted;
|
||||
setIsMuted(audio.muted);
|
||||
}
|
||||
|
||||
const onClickTimeline = (e) => {
|
||||
if (!audio) return;
|
||||
let timeToSeek = 0;
|
||||
try {
|
||||
let timelineWidth = window.getComputedStyle(audioPlayer.current.querySelector(".timeline")).width;
|
||||
//remove px from the string if it exists
|
||||
if (timelineWidth.includes('px')) {
|
||||
timelineWidth = timelineWidth.replace('px', '');
|
||||
}
|
||||
timeToSeek = Math.floor(e.nativeEvent.offsetX / parseInt(timelineWidth) * audio.duration);
|
||||
} catch (e) {
|
||||
console.error('Error seeking audio: ' + e)
|
||||
timeToSeek = 0;
|
||||
}
|
||||
audio.currentTime = timeToSeek;
|
||||
}
|
||||
|
||||
const onVolumeSliderClick = (e) => {
|
||||
if (!audio) return;
|
||||
let volume = .75;
|
||||
try {
|
||||
let sliderWidth = window.getComputedStyle(audioPlayer.current.querySelector(".controls .volume-slider")).width;
|
||||
if (sliderWidth.includes('px')) {
|
||||
sliderWidth = sliderWidth.replace('px', '');
|
||||
}
|
||||
volume = parseFloat((e.nativeEvent.offsetX / parseInt(sliderWidth)).toFixed(2));
|
||||
} catch {
|
||||
console.error('Error changing volume')
|
||||
volume = .75;
|
||||
}
|
||||
audio.volume = volume;
|
||||
audioPlayer.current.querySelector(".controls .volume-percentage").style.width = volume * 100 + '%';
|
||||
}
|
||||
|
||||
|
||||
function getTimeCodeFromNum(num) {
|
||||
let seconds = parseInt(num);
|
||||
let minutes = parseInt(seconds / 60);
|
||||
seconds -= minutes * 60;
|
||||
const hours = parseInt(minutes / 60);
|
||||
minutes -= hours * 60;
|
||||
|
||||
if (hours === 0) return `${minutes}:${String(seconds % 60).padStart(2, 0)}`;
|
||||
return `${String(hours).padStart(2, 0)}:${minutes}:${String(
|
||||
seconds % 60
|
||||
).padStart(2, 0)}`;
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="audio-player" ref={audioPlayer}>
|
||||
|
||||
<div className="controls">
|
||||
<div className="play-container">
|
||||
<button
|
||||
onClick={togglePlayPause}
|
||||
className="play-pause-button"
|
||||
|
||||
>
|
||||
{isPlaying ? (
|
||||
<img src={pauseIcon} alt="Pause" width="30" />
|
||||
) : (
|
||||
<img src={playIcon} alt="Play" width="30" />
|
||||
)}
|
||||
</button>
|
||||
</div>
|
||||
<div className="time">
|
||||
<div className="current">0:00</div>
|
||||
<div className="divider">/</div>
|
||||
<div className="length"></div>
|
||||
</div>
|
||||
{/* <div className="name">Music Song</div> */}
|
||||
<div className="timeline" onClick={onClickTimeline}>
|
||||
<div className="progress"></div>
|
||||
</div>
|
||||
<div className="volume-container">
|
||||
<div className="volume-button" onClick={onVolumeButtonClick}>
|
||||
<div className="volume">
|
||||
{isMuted ? (
|
||||
<FontAwesomeIcon icon="volume-off" width={30} height={30} />
|
||||
) : (
|
||||
<FontAwesomeIcon icon="volume-up" width={30} height={30} />
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="volume-slider" onClick={onVolumeSliderClick}>
|
||||
<div className="volume-percentage"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default JKAudioPlayer
|
||||
|
|
@ -8,6 +8,7 @@ import { useJamTrack } from '../../hooks/useJamTrack';
|
|||
import JKSigningRetryConfirmModal from './JKSigningRetryConfirmModal';
|
||||
import JKSigningEstimateTimeModal from './JKSigningEstimateTimeModal';
|
||||
import { markMixdownActive } from '../../helpers/rest';
|
||||
import JKAudioPlayer from './JKAudioPlayer';
|
||||
|
||||
const JKJamTrackPlayer = () => {
|
||||
const [options, setOptions] = useState([]);
|
||||
|
|
@ -127,11 +128,7 @@ const JKJamTrackPlayer = () => {
|
|||
<Row className="mt-2">
|
||||
<Col>
|
||||
{audioUrl && (
|
||||
<figure>
|
||||
<audio controls style={{ width: '100%' }} ref={audioRef}>
|
||||
<source src={audioUrl} type={audioFileExtension(audioUrl)} />
|
||||
</audio>
|
||||
</figure>
|
||||
<JKAudioPlayer audioUrl={audioUrl} />
|
||||
)}
|
||||
</Col>
|
||||
</Row>
|
||||
|
|
|
|||
|
|
@ -24,9 +24,10 @@ const JKJamTrackResourceLinks = ({jamTrack}) => {
|
|||
</div>
|
||||
<div className="mb-3">
|
||||
<div>
|
||||
<a target="_blank" href="https://jamkazam.com/jamtracks">
|
||||
{/* <a target="_blank" href="/jamtracks">
|
||||
{t('jamtrack.help_resources.jamtracks_home.title')}
|
||||
</a>
|
||||
</a> */}
|
||||
<Link to="/jamtracks">{t('jamtrack.help_resources.jamtracks_home.title')}</Link>
|
||||
</div>
|
||||
{t('jamtrack.help_resources.jamtracks_home.description')}
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -24,7 +24,6 @@ const JKJamTrackShow = () => {
|
|||
const userId = currentUser.id;
|
||||
const resp = await getUserDetail({ id: userId });
|
||||
const data = await resp.json();
|
||||
console.log('user detail', data);
|
||||
await postUserEvent({ name: 'jamtrack_web_player_open' });
|
||||
if (!data.first_opened_jamtrack_web_player) {
|
||||
setTimeout(async () => {
|
||||
|
|
|
|||
|
|
@ -92,7 +92,6 @@ const JKJamTracksFilter = () => {
|
|||
try {
|
||||
const resp = await getJamTracks(options);
|
||||
const data = await resp.json();
|
||||
//console.log('jamtracks', data);
|
||||
setJamTracks(prev => [...prev, ...data.jamtracks]);
|
||||
setNextOffset(data.next);
|
||||
setTotalJamTracks(data.count);
|
||||
|
|
|
|||
|
|
@ -151,8 +151,6 @@ function JKPeopleFilter() {
|
|||
};
|
||||
|
||||
const onSubmit = (data) => {
|
||||
console.log("_DEBUG_ data", data)
|
||||
console.log("_DEBUG_ page.current", page.current)
|
||||
let genres = [];
|
||||
let joined_within_days = '';
|
||||
let active_within_days = '';
|
||||
|
|
@ -197,7 +195,6 @@ function JKPeopleFilter() {
|
|||
page.current = 0
|
||||
submitPageQuery()
|
||||
}else{
|
||||
console.log("_DEBUG_ after loadingStatus changed. page.current", page.current, hasNextPage(), offset)
|
||||
if (page.current === 1 && hasNextPage()) {
|
||||
dispatch(preFetchPeople({ data: params.current, offset, limit: perPageLimit }));
|
||||
page.current += 1;
|
||||
|
|
|
|||
|
|
@ -163,14 +163,14 @@ import {
|
|||
faMusic,
|
||||
faRecordVinyl,
|
||||
faAddressCard,
|
||||
faVolumeUp,
|
||||
faSpinner,
|
||||
faPlayCircle,
|
||||
faPauseCircle,
|
||||
faStopCircle,
|
||||
faInfoCircle,
|
||||
faDownload,
|
||||
|
||||
faVolumeOff,
|
||||
faVolumeUp,
|
||||
} from '@fortawesome/free-solid-svg-icons';
|
||||
|
||||
//import { faAcousticGuitar } from "../icons";
|
||||
|
|
@ -303,6 +303,7 @@ library.add(
|
|||
faPlayCircle,
|
||||
faPauseCircle,
|
||||
faStopCircle,
|
||||
faVolumeOff,
|
||||
|
||||
// Brand
|
||||
faFacebook,
|
||||
|
|
@ -349,5 +350,5 @@ library.add(
|
|||
farComment,
|
||||
farBell,
|
||||
|
||||
//faAcousticGuitar,
|
||||
|
||||
);
|
||||
|
|
|
|||
Loading…
Reference in New Issue