(๋ฏธ๋์ด ์ฟผ๋ฆฌ์ ํคํ๋ ์์ผ๋ก ๋ง๋ ๊ฐ๋จํ ํ์ด์ง)
๊ธฐ๋ณธ ํ
@keyframes ์ ๋๋ฉ์ด์
์ด๋ฆ {
0% { /* from ์ด๋ผ๊ณ ์์ฑํด๋ ๋ฉ๋๋ค.*/
CSS์์ฑ : ์์ฑ๊ฐ;
}
50% { /* ์ ๋๋ฉ์ด์
์งํ๋์ ๋ฐ๋ฅธ ์คํ์ผ์ ์ค์ ํฉ๋๋ค. */
/* ํ์ํ๋ค๋ฉด 1๋ถํฐ 99๊น์ง๋, ์์์ ๊น์ง๋ ๋ชจ๋ ์์ฑํด๋ ๋ฉ๋๋ค.*/
CSS์์ฑ : ์์ฑ๊ฐ;
}
100% { /* to ๋ผ๊ณ ์์ฑํด๋ ๋ฉ๋๋ค.*/
CSS์์ฑ : ์์ฑ๊ฐ;
}
}
ํ์ ํ๋ ํคํ๋ ์ ์์
@keyframes lotate {
0% {
transform : rotate(0deg)
}
50% {
transform : rotate(180deg)
}
100% {
transform : rotate(360deg)
}
}
/* ์์ ์์ ์์ 0๋, 50% ์์ ์์ 180๋, ์๋ฃ ์์ ์์ 360๋ ํ์ ์ํค๋ ์ ๋๋ฉ์ด์
์
๋๋ค. */
-----
/* ๋ง๋ ํคํ๋ ์ ์ ๋๋งค์ด์
์ ์ฉ */
.logo {
animation: lotate 3s;
}
์๋์์ ์๋ก ์ฌ๋ผ์ค๋ ํคํ๋ ์ ์์
@keyframes fadeIn {
from {
opacity: 1;
transform: translateY(60px); /* ์ ์ฉํ ๊ณณ์ ๋ง๊ฒ translateY์ ์กฐ์ ํด์ฃผ๋ฉด ๋จ */
}
to {
opacity: 3;
transform: none;
}
}
-----
์ ๋๋งค์ด์
์ ์ฉํ ๊ณณ {
animation: fadeIn 0.35s ease-out;
}
bounce ํคํ๋ ์
@keyframes bounce {
from {
transform: translateY(0);
}
to {
transform: translateY(-5px);
}
}
animation: bounce 500ms infinite alternate ease-in
animation-play-state
@keyframes rotate {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
.cd-box {
width: 562px;
border-radius: 50%;
animation: rotate 7.2s linear infinite;
animation-play-state: ${({ isPlaying }) => (isPlaying ? 'running' : 'paused')};
}
animation
: ๋์ด์ฐ๊ธฐ๋ก ์ญ ๋์ดํ๋ฉด ์๋์ ์์ฑ๋ค์ ํ ๋ฒ์ ์ง์ ํ ์ ์๋ค.
animation-name
: ์ ๋๋ฉ์ด์
์ ์ค๊ฐ ์ํ๋ฅผ ์ง์ ํ๋ ์ด๋ฆ. @keyframes ๋ธ๋ก์ ์์ฑ
animation-duration
: ํ ์ธ์ดํด์ ์ ๋๋ฉ์ด์
์ด ์ฌ์๋ ์๊ฐ ์ง์
animation-delay
: ์ ๋๋ฉ์ด์
์ ์์์ ์ง์ฐ์ํฌ ์๊ฐ ์ง์
animation-direction
: ์ ๋๋ฉ์ด์
์ฌ์ ๋ฐฉํฅ์ ์ง์
animation-iteration-count
: ์ ๋๋ฉ์ด์
์ด ๋ช ๋ฒ ๋ฐ๋ณต๋ ์ง ์ง์
animation-play-state
: ์ ๋๋ฉ์ด์
์ ์ฌ์ ์ํ. ๋ฉ์ถ๊ฑฐ๋ ๋ค์ ์ฌ์ ์ํฌ ์ ์์
animation-timing-function
: ์ค๊ฐ ์ํ๋ค์ ์ ํ์ ์ด๋ค ์๊ฐ๊ฐ๊ฒฉ์ผ๋ก ์งํํ ์ง ์ง์
animation-fill-mode
: ์ ๋๋ฉ์ด์
์ด ์ฌ์ ์ ํ์ ์ํ ์ง์
โท duration / delay
.logo {
animation : lotate 3s 3s ;
}
/* ์ ์ฝ๋๋ ์๋์ ๊ฐ๋ค. */
.logo {
animation-name : lotate;
animation-duration : 3s;
animation-delay : 3s;
}
โท direction
.logo {
animation : lotate 3s reverse ;
}
/* ์ ์ฝ๋๋ ์๋์ ๊ฐ๋ค. */
.logo {
animation-name : lotate;
animation-duration : 3s;
animation-direction : alternate;
}
/*
* normal : ๊ธฐ๋ณธ ๊ฐ. ์ฌ์์ด ๋๋๋ฉด ์ฒ์๋ถํฐ ๋ค์ ์ฌ์ํฉ๋๋ค.
* reverse : ์ญ๋ฐฉํฅ์ผ๋ก ์ฌ์ํฉ๋๋ค.
* alternate : ์๋ฐฉํฅ๋ถํฐ ์ญ๋ฐฉํฅ์ ๋ฒ๊ฐ์๊ฐ๋ฉฐ ์ฌ์ํฉ๋๋ค.
* alternate-reverse : ์ญ๋ฐฉํฅ๋ถํฐ ์๋ฐฉํฅ์ ๋ฒ๊ฐ์๊ฐ๋ฉฐ ์ฌ์ํฉ๋๋ค.
*/
โท iteration-count
.logo {
animation : lotate 3s infinite ;
/* ์ ๋๋ฉ์ด์
์ด ๋ฌดํ ๋ฐ๋ณต ๋ฉ๋๋ค. */
}
.logo {
animation-name : lotate;
animation-duration : 3s;
animation-iteration-count : 3 ;
/* ์ ๋๋ฉ์ด์
์ด 3๋ฒ ๋ฐ๋ณต ๋ฉ๋๋ค. */
}
โท play-state
.logo {
animation : lotate 3s pause ;
}
/* ์ ์ฝ๋๋ ์๋์ ๊ฐ๋ค. */
.logo {
animation-name : lotate;
animation-duration : 3s;
animation-play-state : pause ;
}
/*
* paused : ์ ์ง
* running : ์์ง์
* inherit : ์์
*/
โท fill-mode
/*
* none : ๊ธฐ๋ณธ ๊ฐ
* forwards : ์ฌ์์ค์ด ์๋ ๊ฒฝ์ฐ ๋ง์ง๋ง ํคํ๋ ์ ์คํ์ผ์ ์ ์ง
* backwards : ์ฌ์์ค์ด ์๋ ๊ฒฝ์ฐ ์ฒซ ๋ฒ์งธ ํคํ๋ ์ ์คํ์ผ์ ์ ์ง
* both: ์ฌ์ ์ ์๋ ์ฒซ ๋ฒ์งธ ํคํ๋ ์ ์คํ์ผ์, ์ฌ์ ํ์๋ ๋ง์ง๋ง ํคํ๋ ์ ์คํ์ผ์ ์ ์ง
*/
import styled, { keyframes } from 'styled-components';
const fadein = keyframes`
from {
opacity: 0;
}
to {
opacity: 1;
}
`
const fadeout = keyframes`
from {
opacity: 1;
}
to {
opacity: 0;
}
`
-----
/* ์ฌ์ฉํ ์ปดํฌ๋ํธ์ ์ ์ฉ. props๋ก ํ์ฉ ๊ฐ๋ฅ */
animation: 0.35s;
animation-name: ${(props) => props.fadeIn ? fadein : fadeout}
์บ๋ฒ์ค๋ canvas ์๋ฆฌ๋จผํธ๋ฅผ DOM์ผ๋ก ์กฐ์ํ๋ ๋ฐฉ์์ผ๋ก ์์ฑ๋๋ค.
<!-- id๋ก ์์ฑํด์ฃผ๋ ๊ฒ์ด ์ข๋ค. -->
<!-- ๋๋น์ ๋์ด๋ฅผ ์ค์ ํด ์ค๋ค. -->
<!-- ํฌ๊ธฐ๋ฅผ ์ค์ ํด์ฃผ์ง ์์ผ๋ฉด ๊ธฐ๋ณธ์ ์ผ๋ก 300px 150px๋ก ์์ฑ๋จ -->
<canvas id="canvas" width="500" height="500">
์บ๋ฒ์ค๋ฅผ ์ง์ํ์ง ์๋ ๋ธ๋ผ์ฐ์ ์์๋ ์บ๋ฒ์ค ๋์ ํ๊ทธ ์ฌ์ด ๋ด์ฉ์ด ํ์๋ฉ๋๋ค.
</canvas>
-----
<!-- vw, vh๋ฅผ ์ ๋ฌํ์ง๋ง 50ํฝ์
40ํฝ์
๋ก ์ค์ ๋จ -->
<!-- ํฝ์
๋จ์๋ก๋ง ๋ช
์ํด์ผ ์ธ์ํ๋๋ก ๋์ด ์๊ธฐ ๋๋ฌธ -->
<canvas id="canvas" vw="500" vh="500"></canvas>
์๋ฐ์คํฌ๋ฆฝํธ๋ก ์๋ฆฌ๋จผํธ๋ฅผ ์ ํํด์ค๋ค.
const canvas = document.querySelector("#canvas");
DOM์ผ๋ก ์ค์ ํ๋ ๋ฐฉ๋ฒ์ด ์๋ค.
์ด ๊ฒฝ์ฐ์ ์ ๋์ ์ธ ๊ฐ๋ ์ค์ ์ด ๊ฐ๋ฅํ์ฌ
์บ๋ฒ์ค์ ํฌ๊ธฐ๊ฐ ๊ณ ์ ๋์ด ์์ง ์์ ๊ฒฝ์ฐ์ ์ฌ์ฉํ๊ธฐ ์ข๋ค.
// ํ๋ฉด ํฌ๊ธฐ์ ๋ง์ถฐ์ ์ค์ ํด์ค ์๋ ์์ต๋๋ค.
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
// ํ๋ฉด ํฌ๊ธฐ๋ฅผ ๊ฐ์ ธ์ ๊ทธ์ ๋น๋กํ์ฌ ์ค์ ํด์ค ์๋ ์์ต๋๋ค.
canvas.width = window.innerWidth * 0.5;
canvas.height = window.innerHeight * 0.4;
// DOM์ผ๋ก ์ค์ ํ ์, ํฝ์
๋จ์๊ฐ ์๋ vw, vh๋ก ๋จ์๊ฐ์ ์ง์ ํด๋ ์ค์ ์ด ๋ฉ๋๋ค.
// ์ฃผ์ํด์ผ ํ ์ ์ style ์์ฑ์ ์ด์ฉํ์ฌ ํฌ๊ธฐ์ ๋ณํ๋ฅผ ์ฃผ๋ ๊ฒฝ์ฐ๋ ํฝ์
์ ํฌ๊ธฐ๊น์ง ํด๋น ๋จ์์ ๋น๋กํด ํ๋ํ๋ ๊ฐ๋
์ด๋ฏ๋ก,
// ํน์ ํ ๊ฒฝ์ฐ๊ฐ ์๋๋ฉด ์ฌ์ฉ์ ์์ ํฉ๋๋ค.
canvas.style.width = "50vw";
canvas.style.height = "40vh";
fillStyle
: ์ฌ๊ฐํ ๋ด๋ถ ์์
fillRect
: ์ฌ๊ฐํ์ ๊ทธ๋ ค์ค
lineWidth
: ์ ์ ๊ตต๊ธฐ
strokeStyle
: ์ ์ ์์
strokeRect
: ์ ์ผ๋ก ๋ ์ฌ๊ฐํ์ ๊ทธ๋ ค์ค
clearRect
: ์ง์ธ ๋ฒ์
โท ์์น ๋ ์ฌ๊ฐํ ๊ทธ๋ฆฌ๊ธฐ
// ์ฌ๊ฐํ ๋ด๋ถ๋ฅผ ์์น ํ ์์์ ์ค์
ctx.fillStyle = 'blue'
// ์ ๋ฌ ์ธ์๋ ์์๋๋ก x์ขํ, y์ขํ, ๊ฐ๋ก๊ธธ์ด, ์ธ๋ก๊ธธ์ด ์ด๋ค.
ctx.fillRect = (10, 10, 100, 50)
โท ์ ์ผ๋ก๋ง ๊ทธ๋ฆฌ๊ธฐ
// ์ ์ ๊ตต๊ธฐ๋ฅผ ์ค์
ctx.lineWidth = 5;
// ์ ์ ์์์ ์ค์
ctx.strokeStyle = "black";
// ์ ๋ฌ ์ธ์๋ ์์๋๋ก x์ขํ, y์ขํ, ๊ฐ๋ก๊ธธ์ด, ์ธ๋ก๊ธธ์ด ์ด๋ค.
ctx.strokeRect(10, 10, 100, 50)
โท ์ฌ๊ฐํ์ผ๋ก ์ง์ฐ๊ธฐ
// ์ ๋ฌ ์ธ์๋ ์ญ์ ๋์ผํฉ๋๋ค.
// ๊ทธ๋ ค๋์ ์ฌ๊ฐํ ๊ฐ์ด๋ฐ ๋ถ๋ถ์ ์ง์๋ณด์ธ์.
ctx.clearRect( 20, 20, 80, 30)
ํด๋ฆญํ ๋ ์บ๋ฒ์ค ์์์์ ๋ง์ฐ์ค ์์น๋ฅผ ๊ตฌํ๋ ค๋ฉด,
ํ๋ฉด์์์ ๋ง์ฐ์ค ์์น์์ ํ๋ฉด์์์ ์บ๋ฒ์ค ์์น๋ฅผ ๋นผ๋ฉด ๋๋ค.
ํ๋ฉด์ ๋ง์ฐ์ค ์์น๋ฅผ ๊ตฌํ๋ ์ด๋ฒคํธ ๊ฐ์ฒด์ ์์ฑ
X์ขํ : event.clientX
Y์ขํ : event.clientY
-------
ํ๋ฉด์ ์บ๋ฒ์ค์ ์์น๋ฅผ ๊ตฌํ๋ ์์ฑ
X์ขํ : ctx.canvas.offsetLeft
Y์ขํ : ctx.canvas.offsetTop
ํน์ event.offsetX, event.offsetY๋ก ๋ฐ๋ก ๊ตฌํ ์๋ ์๋ค.
์ต์ข ๊ตฌํ ์ฝ๋
html
<canvas id="canvas" width="200" height="150"></canvas>
javascript
const canvas = document.querySelector("#canvas");
const ctx = canvas.getContext("2d");
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
canvas.onclick = function (event) {
const x = event.clientX - ctx.canvas.offsetLeft
const y = event.clientY - ctx.canvas.offsetTop
// ๊ตฌํ ์ขํ๋ฅผ ์ด์ฉํด์ ์ฌ๊ฐํ์ ๊ทธ๋ฆฌ๋ ์ฝ๋๋ฅผ ์์ฑํด๋ณด๊ฒ ์ต๋๋ค.
ctx.fillRect(x - 15, y - 15, 30, 30);
// ํด๋ฆญํ ๋๋ง๋ค 30ํฝ์
*30ํฝ์
ํฌ๊ธฐ์ ์ฌ๊ฐํ์ ๊ทธ๋ฆฌ๋๋ก ํ๋ ค๊ณ ํฉ๋๋ค.
// ์ด ๋, x, y๋ฅผ ๊ทธ๋๋ก ์ ๋ฌํ๋ฉด ํด๋น ์ขํ๋ถํฐ ์ฌ๊ฐํ์ด ์์๋์ด ์ด์ํ ๋๋์ ์ค๋๋ค.
// ํด๋ฆญํ ์์น๋ฅผ ์ฌ๊ฐํ์ ์ ์ค์์ด ๋๊ฒ ํ๋ ค๋ฉด ์ฌ๊ฐํํฌ๊ธฐ/2 ํ ๋งํผ ์ขํ์์ ๋นผ์ฃผ๋ฉด ๋ฉ๋๋ค.
// ๋ฐ๋ผ์ x - 15, y - 15 ๋ฅผ ์ ๋ฌํฉ๋๋ค.
}
Canvas๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ํ ์ ์ฉํ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ด๋ค.
์ฌ๋ฌ ์ข
๋ฅ์ ์ฐจํธ๋ฅผ ๋ง๋๋ ๋ฐ ์ฌ์ฉํ ์ ์๋ค.
์ฌ๋ฌ ์ฐจํธ ์ ํ์ ํผํฉํ๊ณ ๋ฐ์ดํฐ๋ฅผ ๋ ์ง ์๊ฐ,
๋ก๊ทธ ๋๋ ์ฌ์ฉ์ ์ ์ ์ฒ๋์ ์ฝ๊ฒ ํ์ํ ์ ์๋ค.
๋ํ ๋ฐ์ดํฐ๋ฅผ ๋ณ๊ฒฝํ๊ฑฐ๋ ์์์ ์
๋ฐ์ดํธํ ๋
์ฆ์ ์ ์ฉํ์ฌ ์ฌ์ฉํ ์ ์๋ ์ ๋๋ฉ์ด์
์ ์ ๊ณตํ๋ค.
โท ์์ ์๋ฐ์คํฌ๋ฆฝํธ
<!-- header ์์ script ํ๊ทธ๋ฅผ ์ด๊ณ CDN ์ฃผ์๋ฅผ ๋ฃ์ด์ค๋ค. -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.4/Chart.js" ></script>
โท ๋ฆฌ์กํธ
// ๋ฆฌ์กํธ์์ ์ง์ ์ค์นํด์ผ ํจ
npm install react-chartjs-2 chart.js
// ๊ฐ์ ธ์ค๊ธฐ
import Chart from "chart.js";
โท ์์ ์๋ฐ์คํฌ๋ฆฝํธ
html
<canvas id="myChart" width="600" height="400"></canvas>
javascript
let myCanvas = document.getElementById("myChart").getContext("2d");
...
const labels = [
'January',
'February',
'March',
'April',
'May',
'June',
];
const data = {
labels: labels,
datasets: [{
label: 'My First dataset',
// โ ๋ง๋ ๋ณ๋ก ์์์ ๋ค๋ฅด๊ฒ ํ๊ธฐ ์ํด ์ฌ์ฉ(๊ธฐ๋ณธ๊ฐ: rgba(0,0,0,0.1))
backgroundColor: 'rgb(255, 99, 132)',
borderColor: 'rgb(255, 99, 132)',
data: [0, 10, 5, 2, 20, 30, 45],
}]
};
const config = {
type: 'line',
data: data // ์ค์ ๋ฐ์ดํฐ๋ค์ ๋ด๊ณ ์์
};
//์ด ๋ถ๋ถ์ด chart constructor ์ด๋ค.
const myChart = new Chart(
myCanvas,
config
);
/*
* ํ์
์ข
๋ฅ
* - line
* - bar
* - radar
* - polarArea
* - pie
* - doughnut
* - bubble
*/
โท ๋ฆฌ์กํธ
//canvas๋ฅผ ์ฌ์ฉํด useRef๋ฅผ ์ ์ฉํ๊ธฐ ์ํ์ฌ chart.js@2 ๋ฒ์ ์ ์ฌ์ฉํ๊ณ ์์ต๋๋ค.
const ExmapleChart = ({ data }) => {
//useRef ์ฌ์ฉ.
const chartRef = useRef(null);
//chart๋ฅผ ์ ์ฅํด๋ state๋ฅผ ๋ง๋ จ.
const [myChart, setMyChart] = useState(null);
//์ปดํฌ๋ํธ๊ฐ ๋ก๋ฉ๋๋ฉด์ ๋์์ ๋ ์ผ ํ๋ฏ๋ก useEffect๋ฅผ ์ฌ์ฉ.
useEffect(() => {
//chartRef๊ฐ ์กด์ฌํ์ง ์์ผ๋ฉด ๋์ํ์ง X
if (!chartRef) return;
//์ฐจํธ๋ฅผ ๊ทธ๋ฆฌ๊ธฐ ์ํ ๊ฐ์ฒด ์์ฑ
const ctx = chartRef.current.getContext("2d");
//์ค์ ์ฐจํธ๋ฅผ ๊ทธ๋ฆฌ๋ ๊ณณ
const myChart = new Chart(ctx, {
type: "bar",
data: {
labels: ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"],
datasets: [
{
label: "# of Votes",
data: data,
backgroundColor: [
"rgba(255, 99, 132, 0.2)",
"rgba(54, 162, 235, 0.2)",
"rgba(255, 206, 86, 0.2)",
"rgba(75, 192, 192, 0.2)",
"rgba(153, 102, 255, 0.2)",
"rgba(255, 159, 64, 0.2)",
],
borderColor: [
"rgba(255, 99, 132, 1)",
"rgba(54, 162, 235, 1)",
"rgba(255, 206, 86, 1)",
"rgba(75, 192, 192, 1)",
"rgba(153, 102, 255, 1)",
"rgba(255, 159, 64, 1)",
],
borderWidth: 1,
},
],
},
});
//์ฐจํธ ์ํ๋ฅผ ์ ์ฅ
setMyChart(myChart);
}, []);
//data์ ์ฐจํธ๊ฐ ๋ฐ๋ ๋๋ง๋ค ๋ ๋๋ง
useEffect(() => {
if (!myChart) return;
myChart.data.datasets[0].data = data;
myChart.update();
}, [data, myChart]);
return <canvas ref={chartRef} id="myChart" width="400" height="400" />;
};
๐ผ๋ฏธ๋์ด ์ฟผ๋ฆฌ / ๐๋ฆฌํ๋ก์ฐ, ๋ฆฌํ์ธํธ ์ต์ ํ ๋ณด๋ฌ๊ฐ๊ธฐ
๐ text-animation codepen
๐ css animation ์ฌ์ดํธ ๋ชจ์
๐ 3schools์ Canvas Reference