Skip to content

Instantly share code, notes, and snippets.

@shimizu
Last active May 22, 2021 16:32
Embed
What would you like to do?
D3 v4 - Voronoi diagram on Google Maps
license: mit

高崎市 燃料給油所(GS) ボロノイ図

D3 ver.4を使ったGoogleMap上でのボロノイ図描画サンプル。

燃料給油所のデータは国土数値情報より。

Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
<!DOCTYPE html>
<html>
<head>
<style type="text/css">
html, body {
margin: 0px;
padding: 0px;
width: 100%;
height: 100%;
}
#map {
width:980px;
height: 500px;
}
.SvgOverlay {
position: relative;
width: 900px;
height: 600px;
}
.SvgOverlay svg {
position: absolute;
top: -4000px;
left: -4000px;
width: 8000px;
height: 8000px;
}
</style>
</head>
<body>
<div id="map"></div>
<script src="http://maps.googleapis.com/maps/api/js?sensor=false"></script>
<script src="//unpkg.com/d3@4.12.2/build/d3.min.js"></script>
<script>
d3.json('gasStation.geojson', main);
function main(pointjson) {
//Google Map 初期化
const map = new google.maps.Map(document.getElementById('map'), {
zoom: 11,
mapTypeId: google.maps.MapTypeId.ROADMAP,
center: new google.maps.LatLng(36.322356, 139.013057),
});
const overlay = new google.maps.OverlayView(); //OverLayオブジェクトの作成
//オーバレイ追加
overlay.onAdd = function () {
const layer = d3.select(this.getPanes().overlayLayer).append("div").attr("class", "SvgOverlay");
const svg = layer.append("svg");
const svgOverlay = svg.append("g").attr("class", "AdminDivisions");
const pointLayer = svgOverlay.append("g");
const voronoiLayer = svgOverlay.append("g");
const markerOverlay = this;
const overlayProjection = markerOverlay.getProjection();
//Google Mapの投影法設定
const googleMapProjection = coordinates => {
const googleCoordinates = new google.maps.LatLng(coordinates[1], coordinates[0]);
const pixelCoordinates = overlayProjection.fromLatLngToDivPixel(googleCoordinates);
return [pixelCoordinates.x + 4000, pixelCoordinates.y + 4000];
}
//再描画時に呼ばれるコールバック
overlay.draw = function () {
const width = svg.node().clientWidth;
const height = svg.node().clientHeight;
//母点位置情報
const pointdata = pointjson.features;
//ピクセルポジション情報
const positions = [];
pointdata.forEach(d => {
positions.push(googleMapProjection(d.geometry.coordinates)); //位置情報→ピクセル
});
//母点表示
const updatePoint = pointLayer.selectAll(".point").data(positions)
const enterPoint = updatePoint.enter()
.append("circle")
.attr("class", "point")
.attr("r", 2);
const point = updatePoint.merge(enterPoint)
.attr("transform", d => `translate(${d[0]}, ${d[1]})` )
//ボロノイ変換関数
const voronoi = d3.voronoi()
.extent([[-1, -1],[width+1, height+1]]);
//ボロノイ境界ポリゴンデータを生成する
const polygons = voronoi(positions).polygons();
//境界表示
voronoiLayer.selectAll(".cell").remove(); //一旦全消しして際appendする方がスムーズに地図が動いた。
voronoiLayer.selectAll(".cell").data(polygons)
.enter()
.append("path")
.attr("class", "cell")
.attr("fill", "none")
.attr("stroke", "red")
.attr("d", d => {
if(!d) return null
return "M" + d.filter( df => df != null ).join("L") + "Z"
})
};
};
//作成したSVGを地図にオーバーレイする
overlay.setMap(map);
};
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment