Skip to content

Instantly share code, notes, and snippets.

@shimizu
Last active December 4, 2017 08:42
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
Star You must be signed in to star a gist
Save shimizu/f3b13ab8b506d257f861875993b65371 to your computer and use it in GitHub Desktop.
interpolate latitude and longitude
license: mit

D3を使って2点間の緯度経度を補完し、トランジションさせる。

Built with blockbuilder.org

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge"/>
<title></title>
<link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/leaflet/0.7.7/leaflet.css"/>
<style>
html, body {
padding: 0px;
margin: 0px;
}
html, body, #map {
width: 100%;
height: 100%;
}
.tick line {
stroke-dasharray: 2 2 ;
stroke: #ccc;
}
#interface {
position: absolute;
top:10px;
left: 40px;
width: 308px;
height: 28px;
padding: 4px;
background-color: white;
z-index: 9999;
}
#interface button {
color:white;
background-color: blue;
}
</style>
</head>
<body>
<div id="interface">
<select id="ease-type">
<option>easeLinear</option>
<option>easeElastic</option>
<option>easeBounce</option>
<option>easeSin</option>
<option>easeQuad</option>
<option>easeCubic</option>
<option>easePoly</option>
<option>easeCircle</option>
<option>easeExp</option>
<option>easeBack</option>
</select>
<input id="duration" type="number" value="1500"></input>
<button id="startBtn">transition</button>
</div>
<div id="map"></div>
<script src="//cdnjs.cloudflare.com/ajax/libs/d3/4.1.1/d3.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/leaflet/0.7.7/leaflet-src.js"></script>
<script>
!(function(){
"use strict"
var map //leaflet obj
var soruce = {
lat:36.3219088,
lng:139.0032936,
}
var current = {
lat:soruce.lat,
lng:soruce.lng
}
var target = {
lat:35.6811673,
lng:139.76705160000006,
}
var data = {soruce:soruce, current:current, target:target}
main();
function main(data) {
addLmaps()
renderCircle()
}
function addLmaps() {
//Leaflet初期設定
map = L.map('map').setView([36.058829 , 139.50993900000003], 9);
L.tileLayer('https:\/\/a.tiles.mapbox.com\/v4\/mapbox.streets\/{z}\/{x}\/{y}.png?access_token=pk.eyJ1IjoibWFwYm94IiwiYSI6ImNpejY4NDg1bDA1cjYzM280NHJ5NzlvNDMifQ.d6e-nNyBDtmQCVwVNivz7A', {
attribution: '&copy; <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
}).addTo(map);
//Leafletに用意されたsvgを使う
map._initPathRoot();
}
//位置→座標変換
function projectPoint(x, y) {
var point = map.latLngToLayerPoint(new L.LatLng(y, x));
return point;
}
function renderCircle() {
var svg = d3.select("#map").select("svg");
var circle = svg.append("circle")
.datum(data)
.attr("stroke", "gray")
.attr("fill", "red")
.attr("fill-opacity", 0.6)
.attr("r", 20)
.on("click", function(d){
moveTween(d.soruce, d.target, 3000, d3.easeBounce)
})
map.on("viewreset", update);
update();
//サークルを地図上でトランジションさせる。
d3.select("#startBtn").on("click", function(){
var easeType = document.querySelector("#ease-type").value;
var duration = document.querySelector("#duration").value;
reset();
moveTween(data.soruce, data.target, duration, d3[easeType]);
})
//緯度経度を画面座標に変換してcircleの位置を移動する
function update() {
circle.attr("transform", function(d){
var p = projectPoint(d.current.lng, d.current.lat);
return "translate("+[p.x,p.y]+")";
});
}
//位置をリセット
function reset(){
data.current.lat = data.soruce.lat;
data.current.lng = data.soruce.lng;
circle.datum(data);
update();
}
//2点間の緯度経度を補完する
function moveTween(soruce, target, duration, ease) {
if(!ease) ease = d3.easeLinear;
var scale = d3.scaleLinear().domain([0, duration]).range([0, 1]).clamp(true);
var interpolateLat = d3.interpolate(soruce.lat, target.lat);
var interpolateLng = d3.interpolate(soruce.lng, target.lng);
var t = d3.timer(function(elapsed) {
var c = ease(scale(elapsed));
data.current.lat = interpolateLat(c);
data.current.lng = interpolateLng(c);
circle.datum(data);
update()
if (elapsed > duration) t.stop();
}, 100);
}
}
}());
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment