HTML
CSS
JavaScript
SVG
d3.js

D3JSで棒グラフを描画してみる

More than 1 year has passed since last update.

基本

最低限必要なもの

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<!-- <script src="https://d3js.org/d3.v3.min.js"></script> -->
<script src="https://d3js.org/d3.v4.min.js"></script>
</head>
<body>
<div id="shape1"></div>
<style>
svg {
border: solid 1px #CCC;
}
</style>
<script>
var data = [10, 20, 30, 10, 40, 50, 20, 60];
var svg = d3.select("#shape1").append("svg")
.attr("width", 120)
.attr("height", 70);
// rectの追加
// var svg = svg.selectAll("rect"); rect→svgに変更→違いがよくわからない
var svg = svg.selectAll("svg");
svg.data(data)
.enter()
.append("rect")
// 棒のxy座標 iはdataのindex
.attr("x", function (d, i) { return i * 15; })
.attr("y", function (d) { return 70 - d; })
// 1個の棒の幅 x座標との差分がMarginとなる
.attr("width", 10)
// 1個の棒の高さ
.attr("height", function (d) { return d; })
.style("fill", "#F00");
</script>
</body>
</html>

★出力イメージ
image.png

棒のサイズからグラフ領域を設定

(1)データ個数8個

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<!-- <script src="https://d3js.org/d3.v3.min.js"></script> -->
<script src="https://d3js.org/d3.v4.min.js"></script>
</head>
<body>
<div id="shape1">
</div>
<style>
svg {
border: solid 1px #CCC;
}
</style>
<script>
// データ設定 8個
var data = [10, 20, 30, 10, 40, 50, 20, 60];
// 棒グラフの幅
var barWidth = 15;
// 棒の間隔
var barMargin = 5;
// SVGの追加
// 配列のデータ個数を取得し、個数分のwidthを設定する。
var svgWidth = data.length * barWidth;
// 配列の中で最大値を取得し、高さに+10する。
var svgHeight = Math.max.apply(null, data) + 10;
// SVG描画
var svg = d3.select("#shape1").append("svg")
.attr("width", svgWidth)
.attr("height", svgHeight);
// rectの追加
// var svg = svg.selectAll("rect"); rect→svgに変更→違いがよくわからない
var svg = svg.selectAll("svg");
svg.data(data)
.enter()
.append("rect")
// iはdataのindex
.attr("x", function (d, i) { return i * barWidth; })
.attr("y", function (d) { return svgHeight - d; })
.attr("width", barWidth - barMargin)
.attr("height", function (d) { return d; })
.style("fill", "#F00");
</script>
</body>
</html>

★出力イメージ
image.png

(2)データ個数10個

データ個数が変わった場合も特にすることなし

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<!-- <script src="https://d3js.org/d3.v3.min.js"></script> -->
<script src="https://d3js.org/d3.v4.min.js"></script>
</head>
<body>
<div id="shape1">
</div>
<style>
svg {
border: solid 1px #CCC;
}
</style>
<script>
// データ設定 8個 最大値:60
// var data = [10, 20, 30, 10, 40, 50, 20, 60];
// データ設定 10個 最大値:120
var data = [10, 20, 30, 10, 40, 50, 20, 120, 60, 10];
// 棒グラフの幅
var barWidth = 15;
// 棒の間隔
var barMargin = 5;
// SVGの追加
// 配列のデータ個数を取得し、個数分のwidthを設定する。
var svgWidth = data.length * barWidth;
// 配列の中で最大値を取得し、高さに+10する。
var svgHeight = Math.max.apply(null, data) + 10;
// SVG描画
var svg = d3.select("#shape1").append("svg")
.attr("width", svgWidth)
.attr("height", svgHeight);
// rectの追加
// var svg = svg.selectAll("rect"); rect→svgに変更→違いがよくわからない
var svg = svg.selectAll("svg");
svg.data(data)
.enter()
.append("rect")
// iはdataのindex
.attr("x", function (d, i) { return i * barWidth; })
.attr("y", function (d) { return svgHeight - d; })
.attr("width", barWidth - barMargin)
.attr("height", function (d) { return d; })
.style("fill", "#F00");
</script>
</body>
</html>

★出力イメージ
image.png

(3)配列を連想配列にしてみる

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<!-- <script src="https://d3js.org/d3.v3.min.js"></script> -->
<script src="https://d3js.org/d3.v4.min.js"></script>
</head>
<body>
<div id="shape1">
</div>
<style>
svg {
border: solid 1px #CCC;
}
</style>
<script>
// データ設定 8個 最大値:60
// var data = [10, 20, 30, 10, 40, 50, 20, 60];
// データ設定 10個 最大値:120
// var data = [10, 20, 30, 10, 40, 50, 20, 120, 60, 10];
// データ設定 連想配列にしてみる
var data = [{x:10},{x: 20}, {x:30}, {x:10}, {x:40}, {x:50}, {x:20}, {x:120}, {x:60}, {x:10}];
// 棒グラフの幅
var barWidth = 15;
// 棒の間隔
var barMargin = 5;
// SVGの追加
// 配列のデータ個数を取得し、個数分のwidthを設定する。
var svgWidth = data.length * barWidth;
// 配列の中で最大値を取得し、高さに+10する。
// var svgHeight = Math.max.apply(null, data) + 10;
var svgHeight = Math.max.apply(null,data.map(function(o){return o.x;})) + 10;
// SVG描画
var svg = d3.select("#shape1").append("svg")
.attr("width", svgWidth)
.attr("height", svgHeight);
// rectの追加
// var svg = svg.selectAll("rect"); rect→svgに変更→違いがよくわからない
var svg = svg.selectAll("svg");
svg.data(data)
.enter()
.append("rect")
// iはdataのindex
.attr("x", function (d, i) { return i * barWidth; })
// .attr("y", function (d) { return svgHeight - d; })
.attr("y", function (d) { return svgHeight - d.x; })
.attr("width", barWidth - barMargin)
// .attr("height", function (d) { return d; })
.attr("height", function (d) { return d.x; })
.style("fill", "#00F");
</script>
</body>
</html>

★出力イメージ
image.png

グラフ領域幅固定

(1)幅に対して高さの割合を固定にする。

データの高さから棒の高さの割合を算出する。

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<!-- <script src="https://d3js.org/d3.v3.min.js"></script> -->
<script src="https://d3js.org/d3.v4.min.js"></script>
</head>
<body>
<div id="shape1">
</div>
<style>
svg {
border: solid 1px #CCC;
}
</style>
<script>
// データ設定
var data = [10, 20, 30, 10, 40, 50, 20, 60];
// SVGの追加
// SVG領域を固定
var svgWidth = 120;
// 縦横比を固定にするため、幅に対して高さの割合を設定
var svgHeightPercentage = 0.8; // 120*0.8=96
// 高さの設定
var svgHeight = svgWidth * svgHeightPercentage;
// 最大値の高さを取得
var barMaxHeight = Math.max.apply(null, data);
// barMaxHeightの高さを100%として、その10%をMarginとする。
var barTopMargin = barMaxHeight / svgHeight * 0.1;
// 棒領域の高さを設定
var barHeight = barMaxHeight / svgHeight + barTopMargin;
// SVG描画
var svg = d3.select("#shape1").append("svg")
.attr("width", svgWidth)
.attr("height", svgHeight);
// rectの追加
// 棒グラフの幅
var barWidth = svgWidth / data.length;
// 棒の間隔
var barMargin = (svgWidth / data.length) * 0.2;
// 棒グラフの描画
var svg = svg.selectAll("svg");
svg.data(data)
.enter()
.append("rect")
.attr("x", function (d, i) { return i * barWidth; })
.attr("y", function (d) { return svgHeight - d / barHeight; })
.attr("width", barWidth - barMargin)
.attr("height", function (d) { return d / barHeight; })
.style("fill", "#F00");
</script>
</body>
</html>

★出力イメージ
image.png

(2)幅に対して高さの割合を固定にする。配列を連想配列に変更し、データ件数と最大値を変更。

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<!-- <script src="https://d3js.org/d3.v3.min.js"></script> -->
<script src="https://d3js.org/d3.v4.min.js"></script>
</head>
<body>
<div id="shape1">
</div>
<style>
svg {
border: solid 1px #CCC;
}
</style>
<script>
// データ設定
// var data = [10, 20, 30, 10, 40, 50, 20, 60];
var data = [{x:10},{x: 20}, {x:30}, {x:10}, {x:40}, {x:50}, {x:20}, {x:120}, {x:60}, {x:30}];
// SVGの追加
// SVG領域を固定
var svgWidth = 120;
// 縦横比を固定にするため、幅に対して高さの割合を設定
var svgHeightPercentage = 0.8; // 120*0.8=96
// 高さの設定
var svgHeight = svgWidth * svgHeightPercentage;
// 最大値の高さを取得
// var barMaxHeight = Math.max.apply(null, data);
var barMaxHeight = Math.max.apply(null,data.map(function(o){return o.x;}));
// barMaxHeightの高さを100%として、その10%をMarginとする。
var barTopMargin = barMaxHeight / svgHeight * 0.1;
// 棒領域の高さを設定
var barHeight = barMaxHeight / svgHeight + barTopMargin;
// SVG描画
var svg = d3.select("#shape1").append("svg")
.attr("width", svgWidth)
.attr("height", svgHeight);
// rectの追加
// 棒グラフの幅
var barWidth = svgWidth / data.length;
// 棒の間隔
var barMargin = (svgWidth / data.length) * 0.2;
// 棒グラフの描画
var svg = svg.selectAll("svg");
svg.data(data)
.enter()
.append("rect")
.attr("x", function (d, i) { return i * barWidth; })
// .attr("y", function (d) { return svgHeight - d / barHeight; })
.attr("y", function (d) { return svgHeight - d.x / barHeight; })
.attr("width", barWidth - barMargin)
// .attr("height", function (d) { return d / barHeight; })
.attr("height", function (d) { return d.x / barHeight; })
.style("fill", "#F00");
</script>
</body>
</html>

★出力イメージ
image.png
グラフ領域は変わらず、データ数が増えたため、棒の幅が狭くなった。

(3)ウィンドウサイズをリサイズしたときにグラフ表示を拡大縮小する。メディアクエリなし

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<!-- <script src="https://d3js.org/d3.v3.min.js"></script> -->
<script src="https://d3js.org/d3.v4.min.js"></script>
</head>
<body>
<div id="shape1">
</div>
<style>
svg {
border: solid 1px #CCC;
}
</style>
<script>
// ページ初期表示
window.onload = function () {
dispSVG();
}
// ウィンドウリサイズ時に再描画
var timer = 0;
window.onresize = function () {
if (timer > 0) {
window.clearTimeout(timer);
}
timer = setTimeout(function () {
removeSVG();
dispSVG();
}, 200);
};
// SVG消去
function removeSVG() {
d3.select("#shape1").selectAll("svg").remove();
}
// SVG描画
function dispSVG() {
// データ設定
var data = [
{ x: 10 }, { x: 20 }, { x: 30 }, { x: 10 },
{ x: 40 }, { x: 50 }, { x: 20 }, { x: 60 }
];
// SVGの追加
// SVG領域を固定 window.innerWidth
var svgWidth = (window.innerWidth * 0.3);
// 縦横比を固定にするため、幅に対して高さの割合を設定
var svgHeightPercentage = 0.3;
// 高さの設定
var svgHeight = svgWidth * svgHeightPercentage;
// 最大値の高さを取得
var barMaxHeight = Math.max.apply(null, data.map(function (o) { return o.x; }));
// barMaxHeightの高さを100%として、その10%をMarginとする。
var barTopMargin = barMaxHeight / svgHeight * 0.1;
// 棒領域の高さを設定
var barHeight = barMaxHeight / svgHeight + barTopMargin;
// SVG描画
var svg = d3.select("#shape1").append("svg")
.attr("width", svgWidth)
.attr("height", svgHeight);
// rectの追加
// 棒グラフの幅
var barWidth = svgWidth / data.length;
// 棒の間隔
var barMargin = (svgWidth / data.length) * 0.2;
// 棒グラフの描画
var svg = svg.selectAll("svg");
svg.data(data)
.enter()
.append("rect")
.attr("x", function (d, i) { return i * barWidth; })
.attr("y", function (d) { return svgHeight - d.x / barHeight; })
.attr("width", barWidth - barMargin)
.attr("height", function (d) { return d.x / barHeight; })
.style("fill", "#F00");
}
</script>
</body>
</html>

★出力イメージ
image.png

ウィンドウ幅を広げる
image.png

ウィンドウ幅を狭める
image.png

(4)ウィンドウサイズをリサイズしたときにグラフ表示を拡大縮小する。メディアクエリ使用

メディアクエリを使用してもonresizeでグラフ領域の幅を取得して、高さや棒グラフのサイズを書き換えている。

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<!-- <script src="https://d3js.org/d3.v3.min.js"></script> -->
<script src="https://d3js.org/d3.v4.min.js"></script>
</head>
<body>
<div id="shape1">
</div>
<style>
svg {
border: solid 1px #CCC;
}
@media screen and ( max-width:767px) {
#shape1 {
width:400px;
}
}
@media screen and (min-width:768px) and ( max-width:1024px) {
#shape1 {
width:600px;
}
}
@media screen and (min-width:1024px) {
#shape1 {
width:800px;
}
}
</style>
<script>
// ページ初期表示
window.onload = function () {
dispSVG();
}
// ウィンドウリサイズ時に再描画
var timer = 0;
window.onresize = function () {
if (timer > 0) {
window.clearTimeout(timer);
}
timer = setTimeout(function () {
removeSVG();
dispSVG();
}, 200);
};
// SVG消去
function removeSVG() {
d3.select("#shape1").selectAll("svg").remove();
}
// SVG描画
function dispSVG() {
// データ設定
var data = [
{ x: 10 }, { x: 20 }, { x: 30 }, { x: 10 },
{ x: 40 }, { x: 50 }, { x: 20 }, { x: 60 }
];
// SVGの追加
// SVG領域を固定 window.innerWidth
// var svgWidth = window.innerWidth * 0.3;
var svgWidth = document.getElementById("shape1").clientWidth;
// 縦横比を固定にするため、幅に対して高さの割合を設定
var svgHeightPercentage = 0.3;
// 高さの設定
var svgHeight = svgWidth * svgHeightPercentage;
// 最大値の高さを取得
var barMaxHeight = Math.max.apply(null, data.map(function (o) { return o.x; }));
// barMaxHeightの高さを100%として、その10%をMarginとする。
var barTopMargin = barMaxHeight / svgHeight * 0.1;
// 棒領域の高さを設定
var barHeight = barMaxHeight / svgHeight + barTopMargin;
// SVG描画
var svg = d3.select("#shape1").append("svg")
.attr("width", svgWidth)
.attr("height", svgHeight);
// rectの追加
// 棒グラフの幅
var barWidth = svgWidth / data.length;
// 棒の間隔
var barMargin = (svgWidth / data.length) * 0.2;
// 棒グラフの描画
var svg = svg.selectAll("svg");
svg.data(data)
.enter()
.append("rect")
.attr("x", function (d, i) { return i * barWidth; })
.attr("y", function (d) { return svgHeight - d.x / barHeight; })
.attr("width", barWidth - barMargin)
.attr("height", function (d) { return d.x / barHeight; })
.style("fill", "#F00");
}
</script>
</body>
</html>

★出力イメージ
ウィンドウサイズ767px未満
image.png

ウィンドウサイズ768px~1024px
image.png

ウィンドウサイズ1024px以上
image.png