block by shimizu fb1323d5d1e6dd8566a6c5046d30946a

D3 v4 - Smooth path

Full Screen

D3のInterpolation機能を使って、地図上のパスを滑らかに補完する。

Smooth pathのD3 ver.4版

Built with blockbuilder.org

index.js

//Gmap スタイル指定
const style_array_from_above_here = [
	{
		featureType: 'water',
		elementType: 'all',
		stylers: [ { hue: '#e9ebed' }, { saturation: -78 }, { lightness: 67 }, { visibility: 'simplified' } ]
	},
	{
		featureType: 'landscape',
		elementType: 'all',
		stylers: [ { hue: '#ffffff' }, { saturation: -100 }, { lightness: 100 }, { visibility: 'simplified' } ]
	},
	{
		featureType: 'road',
		elementType: 'geometry',
		stylers: [ { hue: '#bbc0c4' }, { saturation: -93 }, { lightness: 31 }, { visibility: 'simplified' } ]
	},
	{
		featureType: 'poi',
		elementType: 'all',
		stylers: [ { hue: '#ffffff' }, { saturation: -100 }, { lightness: 100 }, { visibility: 'off' } ]
	},
	{
		featureType: 'road.local',
		elementType: 'geometry',
		stylers: [ { hue: '#e9ebed' }, { saturation: -90 }, { lightness: -8 }, { visibility: 'simplified' } ]
	},
	{
		featureType: 'transit',
		elementType: 'all',
		stylers: [ { hue: '#e9ebed' }, { saturation: 10 }, { lightness: 69 }, { visibility: 'on' } ]
	},
	{
		featureType: 'administrative.locality',
		elementType: 'all',
		stylers: [ { hue: '#2c2e33' }, { saturation: 7 }, { lightness: 19 }, { visibility: 'on' } ]
	},
	{
		featureType: 'road',
		elementType: 'labels',
		stylers: [ { hue: '#bbc0c4' }, { saturation: -93 }, { lightness: 31 }, { visibility: 'on' } ]
	},
	{
		featureType: 'road.arterial',
		elementType: 'labels',
		stylers: [ { hue: '#bbc0c4' }, { saturation: -93 }, { lightness: -2 }, { visibility: 'simplified' } ]
	}
];

//Google Map 初期化
const mapOpotion = {
	zoom: 4,
	mapTypeId: google.maps.MapTypeId.ROADMAP,
	styles: style_array_from_above_here,
	center: new google.maps.LatLng(24.3408621, 124.1614194)
};

const map1 = new google.maps.Map(document.getElementById('map1'), mapOpotion);
const map2 = new google.maps.Map(document.getElementById('map2'), mapOpotion);

//データセット読み込み
d3.json('line.geojson', main);

function main(data) {
	const drawAction = function() {
		//オーバーレイ設定
		const layer = d3.select(this.getPanes().overlayLayer).append('div').attr('class', 'SvgOverlay');
		const svg = layer.append('svg');
		const layergroup = svg.append('g').attr('class', 'd3maplayear');
		const markerOverlay = this;
		const overlayProjection = markerOverlay.getProjection();

		//Google Projection作成
		const googleMapProjection = d3.geoTransform({
			point: function(x, y) {
				const d = overlayProjection.fromLatLngToDivPixel(new google.maps.LatLng(y, x));
				this.stream.point(d.x + 4000, d.y + 4000);
			}
		});

		//パスジェネレーター作成
		const path = d3.geoPath().projection(googleMapProjection);
		const interpolate = d3.line().x((d) => d[0]).y((d) => d[1]).curve(d3.curveBasis);

		const smoothPath = (pstr) => {
			const sp = path(pstr).replace(/M|Z/, '').split('L').map((d) => d.split(','));
			return interpolate(sp);
		};

		//オーバーレイ描画イベント
		this.draw = draw;

		function draw() {
			const currentMap = this.getMap();

			const line = layergroup.selectAll('path').data(data.features);

			line.attr('d', (d) => {
				if (currentMap == map2) return smoothPath(d);
				return path(d);
			});

			const enter = line.enter().append('path');

			line
				.merge(enter)
				.attr('d', (d) => {
					if (currentMap == map2) return smoothPath(d);
					return path(d);
				})
				.attr('stroke', 'orange')
				.attr('stroke-width', 4)
				.attr('fill', 'none');
		}
	};

	const overlay1 = new google.maps.OverlayView(); //OverLayオブジェクトの作成
	const overlay2 = new google.maps.OverlayView(); //OverLayオブジェクトの作成
	overlay1.onAdd = drawAction;
	overlay2.onAdd = drawAction;

	//作成したSVGを地図にオーバーレイする

	overlay1.setMap(map1);
	overlay2.setMap(map2);
}

index.html

<!DOCTYPE html>
<html>
<head>
<title>Smooth path</title>
<style type="text/css">
html, body {
    width: 100%;
    height: 100%;
    margin: 0px;
    padding: 0px;
}
#map1{
	float: right;
    width: 50%;
    height: 100%;
}
#map2{
	float: left;
    width: 50%;
    height: 100%;
}

.SvgOverlay {
	position: relative;
	width: 500px;
	height: 500px;           
}

.SvgOverlay svg {
	position: absolute;
	top: -4000px;
	left: -4000px;
	width: 8000px;
	height: 8000px;        
}
</style>
</head>
<body>
<div id="map1"></div>	
<div id="map2"></div>	


<script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyA8X-e3Naz_Pu50cP8bdDQUZukKrXMqDGs&libraries=visualization"></script>
<script src="//unpkg.com/d3@4.12.2/build/d3.min.js"></script>    

<script src="index.js"></script>
</body>
</html>

line.geojson

{
  "type": "FeatureCollection",
  "features": [
    {
      "type": "Feature",
      "properties": {},
      "geometry": {
        "type": "LineString",
        "coordinates": [
          [
            140.80078125,
            45.644768217751924
          ],
          [
            134.47265625,
            41.96765920367816
          ],
          [
            138.25195312499997,
            40.84706035607122
          ],
          [
            131.66015625,
            38.34165619279595
          ],
          [
            134.12109375,
            37.37015718405753
          ],
          [
            125.33203125,
            31.57853542647338
          ],
          [
            130.166015625,
            27.371767300523047
          ],
          [
            125.94726562499999,
            18.646245142670608
          ],
          [
            134.560546875,
            12.039320557540584
          ],
          [
            141.85546875,
            14.008696370634658
          ],
          [
            150.29296875,
            20.632784250388028
          ],
          [
            148.0078125,
            14.093957177836236
          ],
          [
            152.138671875,
            16.804541076383455
          ],
          [
            151.34765625,
            13.239945499286312
          ],
          [
            153.193359375,
            14.264383087562662
          ],
          [
            153.6328125,
            11.78132529611229
          ]
        ]
      }
    }
  ]
}