xxxxxxxxxx
<html lang="ja">
<head>
<meta charset="UTF-8">
<script src="https://d3js.org/d3.v3.min.js" charset="utf-8"></script>
<script src="https://d3js.org/topojson.v1.min.js"></script>
<title>人口マップ3</title>
<style>
circle.playing {
fill: #f00;
};
</style>
</head>
<body>
<div class="container"></div>
<script type="text/javascript">
var mapfilepath = '/sugi2000/raw/560f664f9b32a17b2c4e/japan.topojson';
//var mapfilepath = 'japan.topojson';
var csvpath = 'choka.csv';
var jinkouData;
var years;
var currentYear;
var isPlaying = false; // 再生中かどうかを判定するフラグ
var zoom = d3.behavior.zoom()
.scaleExtent([1, 8])
.on("zoom", zoomed);
var w = 960;
var h = 960;
var container = d3.select('.container');
var svg = container.append('svg')
.attr('width', w)
.attr('height', h)
.append("g");
var g = svg.append("g");
svg.call(zoom)
.call(zoom.event);
// データの数値から色に変換する関数
var color = d3.scale.linear()
.domain([-80000, -8000, 0, 8000, 80000])
.range(['red', 'orange', 'white', 'cyan', 'blue']);
var sizeScale = d3.scale.linear()
.domain([-80000, 0, 80000])
.range([0.005, 1.0, 5.0]);
// 再生・停止
var startStop = function() {
console.log("startStop");
// 再生フラグを反転
isPlaying = !isPlaying;
// 再生ボタンのクラスのオンオフ
svg.selectAll('circle.play-button')
.classed('playing', isPlaying);
// 再生開始
if (isPlaying) {
if (years.indexOf(currentYear.toString()) === years.length - 1) { //最終年なら最初年に
currentYear = years[0];
} else {
currentYear++;
}
updateYear();
}
};
// 現在選択の年を変更した時に呼び出される関数(全国の都道府県の色を更新)
var updateYear = function() {
console.log("updateYear: " + currentYear + ', ' + years.indexOf(currentYear));
// 年ラベルの色を更新する
svg.selectAll('text.year')
.transition()
.duration(300)
.style('fill', function() {
var self = d3.select(this);
if (currentYear === self.attr('year')) {
return 'red';
} else {
return 'black';
}
});
//年ラベル背景ボックスを移動する
svg.selectAll('rect.year-rect')
.transition()
.duration(300)
.attr('x', w / years.length * years.indexOf(currentYear.toString()));
// 都道府県の色を更新する
var transitions = 0;
g.selectAll('path')
.transition()
.duration(1000)
.style('fill', function() {
return color(d3.select(this).attr('year-' + currentYear));
})
.attr('transform', function(d) {
var self = d3.select(this);
return 'translate(' + self.attr('center-x') + ', ' + self.attr('center-y') +
')scale(' + sizeScale(d3.select(this).attr('year-' + currentYear)) + ')' +
'translate(-' + self.attr('center-x') + ', -' + self.attr('center-y') + ')';
})
.each('start', function() { // トランジションの開始時の設定
transitions++; // 要素の数をカウントアップ
})
.each('end', function() { // トランジション終了時の関数
if (--transitions === 0) { // 要素の数をカウントダウン、ゼロなら全ての終了時
//console.log('done');
if (isPlaying) { // 再生中なら年を更新
if (years.indexOf(currentYear.toString()) === years.length - 1) { //最終年なら停止
startStop();
} else {
currentYear++;
updateYear();
}
}
}
})
;
};
// 再生ボタンを追加
svg.append('circle')
.attr('class', 'play-button')
.attr('cx', 40)
.attr('cy', 60)
.attr('r', 20)
.attr('fill', '#fff')
.style('cursor', 'pointer')//;
//d3.selectAll('circle.play-button')
.on('click', function() {
startStop(); // 再生または停止
});
// 凡例を追加
svg.selectAll('rect.legend')
.data([80000, 8000, 0, -8000, -80000])
.enter()
.append('rect')
.attr('class', 'legend')
.attr('x', 65)
.attr('y', function(d, i) { return 100 + 20 * i; })
.attr('width', 20)
.attr('height', 20)
.attr('fill', function(d) { return color(d); });
svg.selectAll('text.legend')
.data([80000, 8000, 0, -8000, -80000])
.enter()
.append('text')
.attr('x', 60)
.attr('y', function(d, i) { return 100 + 20 * i + 12; })
.attr('font-size', 9)
.attr('text-anchor', 'end')
.text(function(d) { return d + '人'; });
// csvファイルの読み込み
d3.csv(csvpath, function(error, dataset) {
// 背景色
g.append('rect')
.attr('class', 'background')
.attr('x', - w * 2)
.attr('y', - h * 2)
.attr('width', w * 4)
.attr('height', h * 4)
.attr('fill', 'darkgray');
console.log(dataset);
jinkouData = dataset;
// 年ラベルの背景ボックス
years = Object.keys(dataset[0]);
svg.append('rect')
.attr('class', 'year-rect')
.attr('x', 0)
.attr('y', 10)
.attr('width', w / years.length)
.attr('height', 20)
.attr('fill', '#fff');
// 年ラベルの設定
years.some(function(v, i){
if (v === 'ken') { years.splice(i, 1); }
});
svg.selectAll('text.year')
.data(years)
.enter()
.append('text')
.attr('class', 'year')
.attr('x', function(d, i){return (i + 0.5) * w / years.length;})
.attr('y', 20)
.attr('text-anchor', 'middle')
.attr('font-size', 9)
.attr('font-family', 'Helvetica')
.attr('font-weight', 'bold')
.attr('year', function(d){return d;})
.style('cursor', 'pointer')
.text(function(d){return d + '年';});
// クリックイベントの設定
d3.selectAll('text.year').on('click', function(){
currentYear = this.getAttribute('year');
updateYear();
});
// csvファイルを読み込んだ後にmapファイルを読み込み
d3.json(mapfilepath, loadmapCallback);
});
// mapファイル読み込みのコールバック関数(読み込み終了後に呼び出される)
var loadmapCallback = function(error, collection) {
if (error) {
return console.warn(error);
}
var japan = topojson.feature(collection, collection.objects.japan).features;
// setup map
var projection = d3.geo.mercator()
.scale(1500)
.center([137, 34])
//.center(d3.geo.centroid(collection))
.translate([w / 2, h / 2 - 50]);
var path = d3.geo.path().projection(projection);
g.selectAll('path')
.data(japan)
.enter()
.append('path')
.attr('d', path)
.attr('ken', function(d) {
return d.properties.name_local;
})
.attr('center-x', function(d, i) {
return path.centroid(japan[i])[0];
})
.attr('center-y', function(d, i) {
if (d.properties.name_local === "東京都") { // 東京都だけ中心点を上にずらす
var top = path.bounds(japan[i])[0][1];
return top + (path.centroid(japan[i])[1] - top) * 0.1;
}
return path.centroid(japan[i])[1];
})
.style('fill', function(d, i) {
return 'lightgray';
})
.style('cursor', 'pointer')
.on('mouseover', function(){
var self = d3.select(this);
self.style('fill', 'red');
})
.on('mouseout', function(d, i){
var self = d3.select(this);
self.transition()
.duration(300)
.style('fill', function(d, i) {
return color(self.attr('year-' + currentYear));
});
})
;
// jinkouDataの各年のデータをpathの属性に追加する
svg.selectAll('path')
.each(function() {
var p = d3.select(this);
var ds = jinkouData.filter(function(d){
//console.log('ken', d['ken']);
return (d['ken'] === p.attr('ken'));
});
if (ds.length > 0) {
var d = ds[0];
for (var year of years) {
p.attr('year-' + year, d[year]);
}
}
})
// 最初の年で色を更新する
currentYear = years[0];
updateYear();
};
function zoomed() {
g.attr("transform", "translate(" + d3.event.translate + ")scale(" + d3.event.scale + ")");
}
d3.select(self.frameElement).style("height", h + "px");
</script>
</body>
</html>
Modified http://d3js.org/d3.v3.min.js to a secure url
Modified http://d3js.org/topojson.v1.min.js to a secure url
https://d3js.org/d3.v3.min.js
https://d3js.org/topojson.v1.min.js