1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

D3.jsでグリッドを作る

Last updated at Posted at 2019-08-29
grid.html
<!DOCTYPE html>
<html lang="jp">
  <head>
    <meta charset="utf-8" />
    <script src="https://d3js.org/d3.v5.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>
grid.js
document.addEventListener("DOMContentLoaded", function () {
    // html内のJson文字列をデシリアイズします。
    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);
            }
        });
});

Let's Make a Grid with D3.js

解説

上から順番に解説します。

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 メソッドで属性を追加します。

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 要素 をバインドし、タグを生成します。
(よくあるサンプルだと始めの selectAll で selectAll("row") などして、空の selection オブジェクトを取得するのを見かけます。ですが、引数は空でいいと思うのですが、わざわざ"row"などして空振りする効果がよくわかりません。)

d3.jsのセレクタとタグ操作
D3.jsで<g>要素を活用する

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 メソッドでイベントを付与できます。ここでは、クリックすると背景色を切り替えるイベントを付与しています。
(ただ、ここでもう一度 data(d => d).enter() しないといけないのがよくわからない。)

完成形

image.png

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?