SVG는 시각화, 상호작용하는 웹을 만들 때 자주 사용되는 스펙이다. D3.js는 SVG를 조금 다루기 쉽게 만들어준다.
SVG와 D3.js를 이용하여 나만의 로딩 아이콘을 만들어보자.
아래와 같은 결과물을 만들어보자!
먼저, HTML에 svg 태그를 생성하고, 그 안에 text태그를 넣어서 글씨를 쓴다.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>Document</title>
<style>
.heavy {
font: bold 30px sans-serif;
}
</style>
</head>
<body>
<svg height="200" width="400">
<text id="loading_text" x="0" y="50" fill="black" class="heavy">
Loading ...
</text>
SVG를 지원하지 않는 브라우저입니다.
</svg>
</body>
</html>
기본 색상은 블랙으로 했고, 글씨를 조금 강조시키기 위해 Heavy라는 스타일을 입혔다.
여기까지 하면 결과는 다음과 같다.
이제 여기서 빨간색과 검은색을 왔다갔다하도록 d3 라이브러리를 임포트하고 코드를 넣어보자.
<script src="https://d3js.org/d3.v4.js"></script>
<script>
repeat();
function repeat() {
d3.select('#loading_text') // 셀렉터로 태그 잡기
.transition() // 변환을 주는 함수
.duration(1000) // 변환까지 걸리는 시간 설정 (ms) 및 빨간색으로 변환
.attr('fill', 'red') // 빨간색 채우기
.transition() // 변환을 다시 주기
.attr('fill', 'black') // 검정색으로 변환
.on('end', repeat); // 변환이 끝나면 repeat 함수를 다시 호출하여 반복하기
}
</script>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>Document</title>
<style>
.heavy {
font: bold 30px sans-serif;
}
</style>
</head>
<body>
<svg height="200" width="400">
<text id="loading_text" x="0" y="50" fill="black" class="heavy">
Loading ...
</text>
SVG를 지원하지 않는 브라우저입니다.
</svg>
<script src="https://d3js.org/d3.v4.js"></script>
<script>
// d3.select('#loading_text').transition().duration(1000).attr('fill', 'red');
repeat();
function repeat() {
d3.select('#loading_text') // 셀렉터로 태그 잡기
.transition() // 변환을 주는 함수
.duration(1000) // 변환까지 걸리는 시간 설정 (ms) 및 빨간색으로 변환
.attr('fill', 'red') // 빨간색 채우기
.transition() // 변환을 다시 주기
.attr('fill', 'black') // 검정색으로 변환
.on('end', repeat); // 변환이 끝나면 repeat 함수를 다시 호출하여 반복하기
}
</script>
</body>
</html>
위에 글씨 로딩과 같은 맥락으로 진행하면 된다.
단, 움직이는 좌표를 생각하고 동그라미 순서대로 애니메이션이 진행될 수 있게 해주면 된다.
코드는 다음과 같다.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>Document</title>
</head>
<body>
<svg height="200" width="400">
<circle cx="50" , cy="50" r="10"></circle>
<circle cx="80" , cy="50" r="10"></circle>
<circle cx="110" , cy="50" r="10"></circle>
<circle cx="140" , cy="50" r="10"></circle>
<circle cx="170" , cy="50" r="10"></circle>
SVG를 지원하지 않는 브라우저입니다.
</svg>
<script src="https://d3js.org/d3.v4.js"></script>
<script>
repeat();
function turnToRed(selector) {
d3.selectAll(`${selector}`).each(function (d, i, x) {
var event = d3
.select(this)
.transition()
.delay(i * 100)
.duration(100)
.attr('fill', 'red')
.attr('cy', function (a, b, c) {
return 50 - 17;
})
.transition()
.attr('cy', function (a, b, c) {
return 50 + 17;
})
.transition()
.attr('cy', function (a, b, c) {
return 50;
})
.transition()
.attr('fill', 'black');
if (i === x.length - 1) {
event.on('end', () => {
turnToRed('circle');
});
}
});
}
function repeat() {
turnToRed('circle');
}
</script>
</body>
</html>
위에 소스를 이해했다면 이해에 큰 어려움은 없을 것 같다.
https://css-tricks.com/svg-properties-and-css/
https://www.d3-graph-gallery.com/graph/interactivity_transition.html#button