Velog를 보다가 LOCKED님의 Flutter로 광원효과 만들기 글을 보았다.
나도 해보고 싶다!
어떻게 만들것인가!
1. 라이브러리 사용하지말자!
2. styled-component의 css적 요소만 사용하자!
일단은 styled-component로 div를 하나 만들었다
const Card = styled.div`
width:200px;
height:120px;
`;
우선 background-color를 radial-gradient로 채우자!
const Card = styled.div`
width:200px;
height:120px;
background: radial-gradient(
farthest-corner at 10% 10%,
#ffffff 0%,
#f34161 80%
);
`;
animation을 넣자! 그 전에.. 마우스가 들어갔을 때를 알기 위해서 eventHandler 처리!
...
const Controller : React.FC = () => {
const [hover, setHover] = useState<boolean>(false);
const onMouseEnter = () => {
setHover(true);
}
const onMouseLeave = () => {
setHover(false);
}
return (
...
<Presenter
hover={hover}
onMouseEnter={onMouseEnter}
onMouseLeave={onMouseLeave}
/>
)
}
interface PresenterProps {
hover:boolean;
onMouseEnter:()=>void;
onMouseLeave:()=>void;
}
const Presenter : React.FC<PresenterProps> = (props) => {
const {hover, onMouseEnter, onMouseLeave} = props;
return(
...
<Card onMouseEnter={onMouseEnter} onMouseLeave={onMouseLeave}/>
)
}
이벤트 핸들러 추가 ! 그리고 애니메이션 추가!
...
const Presenter : React.FC<PresenterProps> = (props) => {
const {hover, onMouseEnter, onMouseLeave} = props;
return(
...
<Card onMouseEnter={onMouseEnter} onMouseLeave={onMouseLeave} hover={hover} />
)
}
...
const Card = styled.div<{hover:boolean}>`
width:200px;
height:120px;
background: radial-gradient(
farthest-corner at 10% 10%,
#ffffff 0%,
#f34161 80%
);
animation: 0.4s forwrads ${props => props.hover ? 'rotateFrom' : 'rotateTo'};
@keyframes rotateTo {
0% {
background: radial-gradient(
farthest-corner at 90% 90%,
#ffffff 0%,
#f34161 80%);
}
100% {
background: radial-gradient(
farthest-corner at 10% 10%,
#ffffff 0%,
#f34161 80%);
}
}
@keyframes rotateFrom {
0% {
background: radial-gradient(
farthest-corner at 10% 10%,
#ffffff 0%,
#f34161 80%);
}
100% {
background: radial-gradient(
farthest-corner at 90% 90%,
#ffffff 0%,
#f34161 80%);
}
}
`;
그런데 ! 이거 애니메이션이 안된다 ... 그래서 찾아봤더니 !
const Card = styled.div<{hover:boolean}>`
@property --x {
syntax: '<percentage>';
inherits: false;
initial-value: 0%;
}
@property --y {
syntax: '<percentage>';
inherits: false;
initial-value: 0%;
}
width:200px;
height:120px;
background: radial-gradient(
farthest-corner at var{--x} var{--y},
#ffffff 0%,
#f34161 80%
);
animation: 0.4s forwrads ${props => props.hover ? 'rotateFrom' : 'rotateTo'};
@keyframes rotateTo {
0% {
--x: 110%;
--y: 80%;
}
100% {
--x: -20%;
--y: 20%;
}
}
@keyframes rotateFrom {
0% {
--x: -20%;
--y: 20%;
}
100% {
--x: 110%;
--y: 80%;
}
}
`;
이렇게 하면 radial-gradient가 애니메이션이 된다! 헤헤
조금 더 나아가서 transform : rotate3d()를 주자!
const Card = styled.div<{hover:boolean}>`
@property --x {
syntax: '<percentage>';
inherits: false;
initial-value: 0%;
}
@property --y {
syntax: '<percentage>';
inherits: false;
initial-value: 0%;
}
width:200px;
height:120px;
background: radial-gradient(
farthest-corner at var{--x} var{--y},
#ffffff 0%,
#f34161 80%
);
animation: 0.4s forwrads ${props => props.hover ? 'rotateFrom' : 'rotateTo'};
@keyframes rotateTo {
0% {
--x: 110%;
--y: 80%;
transform: rotate3d(0, 1, 0, -30deg) rotate3d(0, 0, 0.2, -5deg)
rotate3d(1, 0, 0, 5deg);
}
100% {
--x: -20%;
--y: 20%;
transform: rotate3d(0, 1, 0, 15deg) rotate3d(0, 0, -0.2, 5deg)
rotate3d(1, 0, 0, 0deg);
}
}
@keyframes rotateFrom {
0% {
--x: -20%;
--y: 20%;
transform: rotate3d(0, 1, 0, 15deg) rotate3d(0, 0, -0.2, 5deg)
rotate3d(1, 0, 0, 0deg);
}
100% {
--x: 110%;
--y: 80%;
transform: rotate3d(0, 1, 0, -30deg) rotate3d(0, 0, 0.2, -5deg)
rotate3d(1, 0, 0, 5deg);
}
}
`;
이렇게 하면 !!
참고
LOCKED 님의 velog : https://velog.io/@locked/Flutter-%EA%B7%B8%EB%9D%BC%EB%8D%B0%EC%9D%B4%EC%85%98%EC%9C%BC%EB%A1%9C-%EB%A7%8C%EB%93%A4%EC%96%B4%EB%B3%B4%EB%8A%94-%EA%B4%91%EC%9B%90-%ED%9A%A8%EA%B3%BC
MDN transform : https://developer.mozilla.org/en-US/docs/Web/CSS/transform-function/rotate3d()
MDN radial-gradietn: https://developer.mozilla.org/en-US/docs/Web/CSS/gradient/radial-gradient()