Skip to content

Instantly share code, notes, and snippets.

@shimizu
Last active March 23, 2018 02:38
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save shimizu/00138ff01086f1dfb98725315a60d581 to your computer and use it in GitHub Desktop.
Save shimizu/00138ff01086f1dfb98725315a60d581 to your computer and use it in GitHub Desktop.
地図変形・散布図
license: mit

クリックすると地形から散布図へ遷移します。

Built with blockbuilder.org

if(!d3.geo2circle) d3.geo2circle = function(coordinates, radius) {
radius = (radius) ? radius : Math.sqrt(Math.abs(area) / Math.PI)
//circle 生成用の変数
var circle = []
var length = 0
var lengths = [length]
var p0 = coordinates[0]
var p1
var x
var y
var i = 0
var n = coordinates.length
// coordinatesの前後間の距離を求める
while (++i < n) {
p1 = coordinates[i]
//console.log(p1);
x = p1[0] - p0[0]
y = p1[1] - p0[1]
lengths.push(length += Math.sqrt(x * x + y * y))
p0 = p1;
}
var centroid =d3.polygonCentroid(coordinates)
var angle
var i = -1
var k = 2 * Math.PI / lengths[lengths.length - 1];
// 円を描画するための座標を求める
while (++i < n) {
angle = lengths[i] * k;
circle.push([
centroid[0] + radius * Math.cos(angle),
centroid[1] + radius * Math.sin(angle)
]);
}
return circle;
};
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge"/>
<title>地図・散布図遷移</title>
<style>
html, body {
width: 100%;
height: 100%;
}
#stage {
width: 900px;
height: 500px;
}
svg {
width: 100%;
height: 100%;
}
</style>
</head>
<body>
<div id="stage"></div>
<script src="//cdnjs.cloudflare.com/ajax/libs/d3/4.1.1/d3.min.js"></script>
<script src="d3.geo2circle.js"></script>
<script>
!(function(){
"use strict"
var margin = { top: 40, right: 20, bottom: 40, left: 50}
var width = document.querySelector("#stage").clientWidth
var height = document.querySelector("#stage").clientHeight
var stageW = width - (margin.left + margin.right)
var stageH = height - (margin.top + margin.bottom)
var svg = d3.select("#stage").append("svg")
var axisLayer = svg.append("g").attr("class", "axisLayer").attr("opacity", 0)
var mapLayer = svg.append("g").attr("class", "mapLayer")
.attr("width", stageW)
.attr("height", stageH)
.attr("transform", "translate("+[margin.left, margin.top]+")")
var xScale = d3.scaleLinear().domain([0, 100]).range([0, stageW])
var yScale = d3.scaleLinear().domain([0, 100]).range([stageH, 0])
var projection = d3.geoMercator()
.scale(stageW*1.4)
.translate([stageW/2,250])
.center([139.0032936, 36.3219088]);
var path = d3.geoPath().projection(projection); 
d3.json('japan.geojson', main)
function main(json) {
var data = convert(json)
drawAxis(data)
drawMaps(data)
var toggleFn = toggle(
function() {
axisLayer.transition().duration(1400).attr("opacity", 1)
changeScatter()
},
function () {
axisLayer.transition().duration(1400).attr("opacity", 0)
changeMap()
}
)
d3.select("body").on("click", toggleFn)
d3.select("body").on("touchend", toggleFn)
}
function drawAxis() {
axisLayer.append("g")
.attr("transform", "translate("+[margin.left, margin.top]+")")
.attr("class", "axis y")
.call(d3.axisLeft(yScale))
axisLayer.append("g")
.attr("class", "axis x")
.attr("transform", "translate("+[margin.left, stageH+margin.top]+")")
.call(d3.axisBottom(xScale))
}
function drawMaps(data) {
data.sort(function(a,b){ return a.properties["JIS-CODE"] - b.properties["JIS-CODE"]})
var selector = mapLayer.selectAll(".land")
.data(data, function(d){ return d.properties.ObjName})
var newSelector = selector.enter().append("path")
newSelector.merge(selector)
.attr("class", "land")
.attr("d", function(d){ return d.geoPath })
.attr("stroke", "green")
.attr("fill", "#ccffcc")
.attr("fill-opacity", 0.5)
}
function changeMap() {
mapLayer.selectAll(".land")
.transition()
.duration(1200)
.attr("transform", function(){
return "translate("+[0, 0]+")"
})
.call(endAll, function(){
mapLayer.selectAll(".land")
.transition()
.delay(function(d, i){ return i * 100 })
.duration(1000)
.attr("d", function(d){ return d.geoPath })
})
}
function changeScatter() {
mapLayer.selectAll(".land")
.transition()
.delay(function(d, i){ return i * 100 })
.duration(1000)
.attr("d", function(d){ return d.scatterPath })
.call(endAll, function(){
mapLayer.selectAll(".land")
.transition()
.duration(1200)
.attr('transform', function(d, i){
var center = path.centroid(d.properties.geometry);
var x = ~~center[0];
var y = ~~center[1];
var nx = xScale(Math.random()*100)
var ny = yScale(Math.random()*100)
return 'translate('+(0-x)+','+(0-y)+'),translate('+nx+','+ny+')';
});
})
}
function endAll(transition, callback) {
var n = 0;
transition
.each(function() { ++n; })
.on('end', function() { if (!--n) callback.apply(this, arguments); });
}
function convert(json) {
var calcCoords = function(polygon, properties) {
var geoCoords = polygon.map(projection);
var scatterCoords = d3.geo2circle(geoCoords, 6);
var scatterPathString = 'M' + scatterCoords.join('L') + 'Z';
var geoPathString = 'M' + geoCoords.join('L') + 'Z';
return { scatterPath: scatterPathString, geoPath: geoPathString , properties:properties};
};
var reslut = [];
for (var i = 0; i < json.features.length; i++) {
var geometry = json.features[i].geometry;
var properties =json.features[i].properties;
properties.geometry = geometry;
if (geometry.type == 'Polygon') {
reslut.push(calcCoords(geometry.coordinates[0], properties));
} else if (geometry.type == 'MultiPolygon') {
geometry.coordinates.forEach(function(coordinates){
reslut.push(calcCoords(coordinates[0], properties));
});
}
}
return reslut
}
function toggle(){
var fn = arguments;
var l = arguments.length;
var i = 0;
return function(){
if(l <= i) i=0;
fn[i++]();
}
}
function endall(transition, callback) {
var n = 0;
transition
.each(function() { ++n; })
.each('end', function() { if (!--n) callback.apply(this, arguments); });
}
}());
</script>
</body>
</html>
Display the source blob
Display the rendered blob
Raw
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment