video custom 해보기Frontend/웹 개발 꿀팁2022. 7. 14. 21:47
Table of Contents
Why?
- 기존의 video 엘리먼트의 디자인이 진행중이던 프로젝트와 어울리지 않아서 디자이너의 요청으로 아래처럼 재생 버튼이 가운데 있고 hover할 때 서서히 등장하고 volume 버튼도 오른쪽 위에 있고 hover할 때 서서히 등장하게 만들었다.
- react의 useState와 useRef를 이용하면 쉽게 만들 수 있다!
- video 엘리먼트의 autoplay 속성과 mute 속성의 초기값을 각각 false와 true로 정했기 때문에 그에 따른 state인 isPlaying과 isMuted를 각각 false/true로 만들고 이 상태값을 기준으로 버튼을 다르게 보이도록 구성했다!
- ref를 이용해서 play()와 pause() 함수로 비디오를 재생/정지 시켰고 muted 값을 true/false로 만들어서 소리가 안나거나 나도록 만들었다.
import React, {useState, useRef} from "react";
import "./App.scss";
const App = () => {
const videoRef = useRef();
const [isPlaying, setIsPlaying] = useState(false);
const [isMuted, setIsMuted] = useState(true);
const handlePlay = () => {
console.log(videoRef.current)
videoRef.current.play();
setIsPlaying(true);
}
const handlePause = () => {
videoRef.current.pause();
setIsPlaying(false);
}
const handleMute = () => {
videoRef.current.muted = true;
setIsMuted(true);
}
const handleSoundOn = () => {
videoRef.current.muted = false;
setIsMuted(false);
}
return (
<React.Fragment>
<div className="video-wrapper">
<div className="video-body">
<video src="video/video1.mp4" ref={videoRef}/>
<div className="video-volume-icon">
{isMuted ?
(
<div onClick={handleSoundOn}>
<MuteIcon/>
</div>
) :
(
<div onClick={handleMute}>
<NotMuteIcon/>
</div>
)
}
</div>
<div className="video-play-icon">
{!isPlaying ?
(
<div onClick={handlePlay}>
<PlayButton/>
</div>
) :
(
<div onClick={handlePause}>
<PauseButton/>
</div>
)
}
</div>
</div>
</div>
</React.Fragment>
)
}
const MuteIcon = () => {
return (
<svg viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg">
<path
d="M0.7 0.325C0.266667 0.758333 0.266667 1.45833 0.7 1.89167L4.76667 5.95833L4.44444 6.29167H1.11111C0.5 6.29167 0 6.79167 0 7.40278V11.8472C0 12.4583 0.5 12.9583 1.11111 12.9583H4.44444L8.1 16.6139C8.8 17.3139 10 16.8139 10 15.825V11.1917L14.6444 15.8361C14.1 16.2472 13.5111 16.5917 12.8667 16.8472C12.4667 17.0139 12.2222 17.4361 12.2222 17.8694C12.2222 18.6694 13.0333 19.1806 13.7667 18.8806C14.6556 18.5139 15.4889 18.025 16.2333 17.425L17.7222 18.9139C18.1556 19.3472 18.8556 19.3472 19.2889 18.9139C19.7222 18.4806 19.7222 17.7806 19.2889 17.3472L2.27778 0.325C1.84444 -0.108333 1.14444 -0.108333 0.7 0.325ZM17.7778 9.625C17.7778 10.5361 17.6111 11.4139 17.3222 12.225L19.0222 13.925C19.6444 12.625 20 11.1694 20 9.625C20 5.36944 17.3333 1.725 13.5778 0.291666C12.9222 0.0361109 12.2222 0.547222 12.2222 1.24722V1.45833C12.2222 1.88056 12.5 2.24722 12.9 2.40278C15.7556 3.55833 17.7778 6.35833 17.7778 9.625ZM8.1 2.63611L7.91111 2.825L10 4.91389V3.41389C10 2.425 8.8 1.93611 8.1 2.63611ZM15 9.625C15 7.65833 13.8667 5.96944 12.2222 5.14722V7.13611L14.9778 9.89167C14.9889 9.80278 15 9.71389 15 9.625Z"/>
</svg>
)
}
const NotMuteIcon = () => {
return (
<svg viewBox="0 0 20 19" xmlns="http://www.w3.org/2000/svg">
<path
d="M0 7.17891V11.6234C0 12.2345 0.5 12.7345 1.11111 12.7345H4.44444L8.1 16.39C8.8 17.09 10 16.59 10 15.6011V3.19003C10 2.20114 8.8 1.70114 8.1 2.40114L4.44444 6.0678H1.11111C0.5 6.0678 0 6.5678 0 7.17891ZM15 9.40114C15 7.43447 13.8667 5.74558 12.2222 4.92336V13.8678C13.8667 13.0567 15 11.3678 15 9.40114ZM12.2222 1.01225V1.23447C12.2222 1.65669 12.5 2.02336 12.8889 2.17891C15.7556 3.32336 17.7778 6.13447 17.7778 9.40114C17.7778 12.6678 15.7556 15.4789 12.8889 16.6234C12.4889 16.7789 12.2222 17.1456 12.2222 17.5678V17.79C12.2222 18.49 12.9222 18.9789 13.5667 18.7345C17.3333 17.3011 20 13.6678 20 9.40114C20 5.13447 17.3333 1.50114 13.5667 0.0678028C12.9222 -0.187753 12.2222 0.312247 12.2222 1.01225Z"/>
</svg>
)
}
const PlayButton = () => {
return (
<svg viewBox="0 0 27 32" xmlns="http://www.w3.org/2000/svg">
<path
d="M0 2.59204V29.408C0 31.4528 2.25192 32.6952 3.98615 31.5822L25.0558 18.1743C26.6606 17.1648 26.6606 14.8352 25.0558 13.7999L3.98615 0.417781C2.25192 -0.695235 0 0.547202 0 2.59204Z"/>
</svg>
)
}
const PauseButton = () => {
return (
<svg viewBox="0 0 18 20" xmlns="http://www.w3.org/2000/svg">
<path
d="M2.85714 20C4.42857 20 5.71429 18.7143 5.71429 17.1429V2.85714C5.71429 1.28571 4.42857 0 2.85714 0C1.28571 0 0 1.28571 0 2.85714V17.1429C0 18.7143 1.28571 20 2.85714 20ZM11.4286 2.85714V17.1429C11.4286 18.7143 12.7143 20 14.2857 20C15.8571 20 17.1429 18.7143 17.1429 17.1429V2.85714C17.1429 1.28571 15.8571 0 14.2857 0C12.7143 0 11.4286 1.28571 11.4286 2.85714Z"
/>
</svg>
)
}
export default App;
.video-wrapper {
margin: 150px;
width: 360px;
height: 640px;
.video-body {
width: 100%;
height: 100%;
border-radius: 10px;
overflow: hidden;
position: relative;
&:hover{
.video-volume-icon{
z-index: 1;
opacity: 1;
}
.video-play-icon{
z-index: 1;
opacity: 0.7;
}
}
video {
width: 100%;
height: 100%;
object-fit: contain;
}
.video-volume-icon {
display: flex;
position: absolute;
top: 8px;
right: 8px;
z-index: -1;
opacity: 0;
transition: opacity 1s ease;
svg {
fill: #fff;
width: 32px;
height: 32px;
cursor: pointer;
}
}
.video-play-icon {
display: flex;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
z-index: -1;
opacity: 0;
transition: opacity 1s ease;
svg {
fill: #fff;
width: 72px;
height: 72px;
cursor: pointer;
}
}
}
}
'Frontend > 웹 개발 꿀팁' 카테고리의 다른 글
flex-wrap이 body를 넘어가는 경우!! (0) | 2022.05.11 |
---|---|
이미지 업로드전 미리보기 (0) | 2022.05.11 |
로그인 후 redirect하기 (리액트 아님) (0) | 2022.05.11 |
서버에서 받은 이미지 파일 file 객체로 변환하기 (0) | 2021.11.25 |
keyframes (0) | 2021.08.14 |
@덕구공 :: Duck9s'
주니어 개발자에욤
포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!