D3.js Grid(그리드) 그리기
Grid 그리기
grid.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<script src="https://d3js.org/d3.v7.js"></script>
<script src="./js/grid.js"></script>
</head>
<body>
<div id="grid"></div>
<span id="data" style="display:none;">
[
[
{"x":1,"y":1,"width":100,"height":100,"selected":false},
{"x":101,"y":1,"width":250,"height":50,"selected":false}
],
[
{"x":101,"y":51,"width":100,"height":50,"selected":false},
{"x":201,"y":51,"width":150,"height":50,"selected":false}
],
[
{"x":1,"y":101,"width":50,"height":300,"selected":false},
{"x":51,"y":101,"width":50,"height":150,"selected":false},
{"x":101,"y":101,"width":100,"height":150,"selected":false},
{"x":201,"y":101,"width":150,"height":150,"selected":false}
],
[
{"x":51,"y":251,"width":50,"height":150,"selected":false},
{"x":101,"y":251,"width":100,"height":150,"selected":false},
{"x":201,"y":251,"width":150,"height":150,"selected":false}
]
]
</span>
</body>
</html>
./js/grid.js
document.addEventListener("DOMContentLoaded", function () {
// html의 Json 문자열을 deserialize 한다.
const gridData = JSON.parse(document.querySelector("#data").textContent);
const grid = d3.select("#grid")
.append("svg")
.attr("width", "510px")
.attr("height", "510px");
const row = grid.selectAll()
.data(gridData)
.enter()
.append("g")
.attr("class", "row");
const noSelectedColor = "#ffffff";
const selectedColor = "#2C93E8";
const column = row.selectAll()
.data(d => {
return d;
})
.enter()
.append("rect")
.attr("class", "square")
.attr("x", function (d) {
return d.x;
})
.attr("y", function (d) {
return d.y;
})
.attr("width", function (d) {
return d.width;
})
.attr("height", function (d) {
return d.height;
})
.style("fill", noSelectedColor)
.style("stroke", "#222")
.on('click', function (d) {
d.selected = !d.selected;
let cell = d3.select(this);
if (d.selected) {
cell.style("fill", selectedColor);
} else {
cell.style("fill", noSelectedColor);
}
});
});
코드 설명
위에서 순서대로 설명한다.
svg
태그
const grid = d3.select("#grid")
.append("svg")
.attr("width", "510px")
.attr("height", "510px");
실행 후에는 아래와 같이 변경된다.
<div id="grid">
<svg width="510px" height="510px"></svg>
</div>
select
메소드의 셀렉터는 js, css 등과 동일한다.
- 가져온 d3.selection 객체에
append
메소드로svg
태그가 삽입한다. append
메소드로 인해 태그가 실제로 생성된다.append
메소드의 반환 값은 d3.selection 객체이다.
attr
메소드로 속성을 추가한다.
data 메소드에 객체 할당
const row = grid.selectAll()
.data(gridData)
.enter()
.append("g")
.attr("class", "row");
실행 후에는 아래와 같이 변경된다.
<div id="grid">
<svg width="510px" height="510px">
<g class="row"></g>
<g class="row"></g>
<g class="row"></g>
<g class="row"></g>
</svg>
</div>
data
메소드로 그리드의 객체를 할당한다.- 예제에서는 Json 문자열에서 객체를 생성한다.
enter
메소드로data
메소드에 할당할 수 있었던 객체가 d3.selection 객체에 설정된다.append("g")
메소드로 객체의 각 배열 요소에g
요소를 바인딩하여 태그를 생성한다.
rect 생성
const noSelectedColor = "#ffffff";
const selectedColor = "#2C93E8";
const gridStrokeColor = "#222222";
const column = row.selectAll()
.data(d => d)
.enter()
.append("rect")
.attr("class", "square")
.attr("x", d => d.x)
.attr("y", d => d.y)
.attr("width", d => d.width)
.attr("height", d => d.height)
.style("fill", noSelectedColor)
.style("stroke", gridStrokeColor)
.on('click', function (d) {
d.selected = !d.selected;
let cell = d3.select(this);
if (d.selected) {
cell.style("fill", selectedColor);
} else {
cell.style("fill", noSelectedColor);
}
});
실행 후에는 아래와 같이 변경된다.
<div id="grid">
<svg width="510px" height="510px">
<g class="row">
<rect class="square" x="1" y="1" width="100" height="100" style="fill: rgb(255, 255, 255); stroke: rgb(34, 34, 34);">
</rect>
<rect class="square" x="101" y="1" width="250" height="50" style="fill: rgb(255, 255, 255); stroke: rgb(34, 34, 34);">
</rect>
</g>
<g class="row">
<rect class="square" x="101" y="51" width="100" height="50" style="fill: rgb(255, 255, 255); stroke: rgb(34, 34, 34);">
</rect>
<rect class="square" x="201" y="51" width="150" height="50" style="fill: rgb(255, 255, 255); stroke: rgb(34, 34, 34);">
</rect>
</g>
<g class="row">
<rect class="square" x="1" y="101" width="50" height="300" style="fill: rgb(255, 255, 255); stroke: rgb(34, 34, 34);">
</rect>
<rect class="square" x="51" y="101" width="50" height="150" style="fill: rgb(255, 255, 255); stroke: rgb(34, 34, 34);">
</rect>
<rect class="square" x="101" y="101" width="100" height="150" style="fill: rgb(255, 255, 255); stroke: rgb(34, 34, 34);">
</rect>
<rect class="square" x="201" y="101" width="150" height="150" style="fill: rgb(255, 255, 255); stroke: rgb(34, 34, 34);">
</rect>
</g>
<g class="row">
<rect class="square" x="51" y="251" width="50" height="150" style="fill: rgb(255, 255, 255); stroke: rgb(34, 34, 34);">
</rect>
<rect class="square" x="101" y="251" width="100" height="150" style="fill: rgb(255, 255, 255); stroke: rgb(34, 34, 34);">
</rect>
<rect class="square" x="201" y="251" width="150" height="150" style="fill: rgb(255, 255, 255); stroke: rgb(34, 34, 34);">
</rect>
</g>
</svg>
</div>
- 여기서는 이전에 g 요소에 바인딩한 배열의 행 객체의 요소에서 rect 를 생성한다.
x
,y
,width
,height
,fill
,stroke
는 SVG의 속성이다.
- jQuery와 같이 on 메소드로 이벤트를 부여할 수 있다.
- 여기에서는 클릭하면 배경색을 전환하는 이벤트를 부여하고 있다.
최종 수정 : 2024-01-18