▶︎ Data source: 国営木曽三川公園Webサイト, 社会実情データ図録, Geocoding
Built with blockbuilder.org
| Mapbox - Extruding circles (choropleth) | |
| license: mit |
▶︎ Data source: 国営木曽三川公園Webサイト, 社会実情データ図録, Geocoding
Built with blockbuilder.org
| <!DOCTYPE html> | |
| <head> | |
| <meta charset="utf-8"> | |
| <script src='https://api.mapbox.com/mapbox-gl-js/v2.1.1/mapbox-gl.js'></script> | |
| <link href='https://api.mapbox.com/mapbox-gl-js/v2.1.1/mapbox-gl.css' rel='stylesheet' /> | |
| <script src="https://cdn.jsdelivr.net/npm/@turf/turf@5/turf.min.js"></script> | |
| <script src="https://d3js.org/d3.v5.min.js"></script> | |
| <style> | |
| #mapID { height: 700px; } | |
| #position { | |
| position:absolute; top: 0; height: 70px; width: 500px; | |
| background-color: #fff; | |
| padding: 30px; | |
| margin: 10px; | |
| font-family: 'Courier New', Courier, monospace; | |
| } | |
| h4 { | |
| margin: 0 0 5px 0; | |
| } | |
| p { | |
| margin: 0 0 5px 0; | |
| } | |
| </style> | |
| </head> | |
| <body> | |
| <div id="mapID"></div> | |
| <script src="map.js"></script> | |
| <div id="position"> | |
| <h4>Visualize: Japanese towers with observation decks</h4> | |
| <p>Let's touch the polygon, and check the tower info.</p> | |
| <p style="color: grey;">(Other Ver. <a href="https://bl.ocks.org/hirosaji/04b37b81e05800f4531b8941da42eec1">simple</a>/<a href="https://bl.ocks.org/hirosaji/868b7f86af4b1fce305c5963684f29e6">stacked</a>/<a href="https://bl.ocks.org/hirosaji/adf6a4c8d1995c3b6276569dac760f78">gradient</a>)</p> | |
| </body> |
| (function () { | |
| "use strict"; | |
| mapboxgl.accessToken = 'pk.eyJ1IjoiaGlyb3NhamkiLCJhIjoiY2szOWlqZWNzMDJueTNjcWhyNjhqdXBnOSJ9._6mJT202QqpnMuK-jvMr3g'; | |
| const mapObj = new mapboxgl.Map({ | |
| container: 'mapID', | |
| style: 'mapbox://styles/hirosaji/cklfggkyj4ytl17qhtxrp2qco', | |
| center: [135.68380, 36.85676], | |
| zoom: 5.2, | |
| pitch: 60.00, | |
| bearing: -17.60, | |
| interactive: true | |
| }); | |
| const loadFiles = [ | |
| d3.csv("tower_height.csv") | |
| ]; | |
| let hoveredTowerId; | |
| Promise.all(loadFiles).then(function (csv) { | |
| const geojson = { | |
| "type": "FeatureCollection", | |
| "features": csv[0].map(function(d) { | |
| return { | |
| type: "Feature", | |
| properties: { | |
| name: d.name, | |
| full_value: parseFloat(d.full_height), | |
| observatory_value: parseFloat(d.observatory_height) | |
| }, | |
| geometry: { | |
| type: "Point", | |
| coordinates: [ | |
| parseFloat(d.lng), | |
| parseFloat(d.lat) | |
| ] | |
| } | |
| } | |
| }) | |
| } | |
| const position = d3.select("#position"); | |
| mapObj.on('load', function() { | |
| mapObj.addLayer({ | |
| 'id': 'sky', | |
| 'type': 'sky', | |
| 'paint': { | |
| 'sky-type': 'atmosphere', | |
| 'sky-atmosphere-sun': [0.0, 0.0], | |
| 'sky-atmosphere-sun-intensity': 15 | |
| } | |
| }); | |
| mapObj.addSource("data", { | |
| type: "geojson", | |
| data: geojson, | |
| }); | |
| mapObj.addLayer({ | |
| 'id': 'tower_points', | |
| 'type': 'circle', | |
| 'source': 'data', | |
| 'paint': { | |
| 'circle-opacity': 0 | |
| } | |
| }); | |
| mapObj.addSource('extrusion_source', { | |
| "type": "geojson", | |
| "data": { | |
| type: 'FeatureCollection', | |
| features: [] | |
| } | |
| }); | |
| mapObj.addLayer({ | |
| 'id': 'extrusion', | |
| 'type': 'fill-extrusion', | |
| 'source': 'extrusion_source', | |
| 'paint': { | |
| 'fill-extrusion-color': [ | |
| 'case', | |
| ['boolean', ['feature-state', 'hover'], false], | |
| ['get', 'hovered_color'], | |
| ['get', 'base_color'] | |
| ], | |
| 'fill-extrusion-height': ['get', 'height'], | |
| 'fill-extrusion-base': ['get', 'base'], | |
| 'fill-extrusion-opacity': 0.6 | |
| } | |
| }); | |
| function update() { | |
| const qfs = mapObj.queryRenderedFeatures({ | |
| layers: ['tower_points'] | |
| }); | |
| const data = { | |
| "type": "FeatureCollection", | |
| "features": [] | |
| }; | |
| const radiusPX = 3; | |
| qfs.forEach(function (object, i) { | |
| const center = object.geometry.coordinates | |
| let xy = mapObj.project(center); | |
| xy.x += radiusPX; | |
| let LL = mapObj.unproject(xy); | |
| LL = turf.point([LL.lng, LL.lat]); | |
| const radius = turf.distance(center, LL, { | |
| units: 'meters' | |
| }) + 0.00000001; | |
| const bcolor = d3 | |
| .scaleSequential(d3.interpolateYlOrRd) | |
| // .scaleLinear() | |
| // .range(["white", "blue"]) | |
| .domain([50, 150]); | |
| const hColor = d3 | |
| .scaleSequential(d3.interpolateYlGnBu) | |
| // .scaleLinear() | |
| // .range(["white", "red"]) | |
| .domain([50, 150]); | |
| object.properties.height = object.properties.full_value * 600; | |
| object.properties.base = 0; | |
| object.properties.index = i; | |
| object.properties.base_color = bcolor(object.properties.full_value); | |
| object.properties.hovered_color = hColor(object.properties.full_value); | |
| const options = { | |
| steps: 16, | |
| units: 'meters', | |
| properties: object.properties | |
| }; | |
| const feature = turf.circle(center, radius, options); | |
| feature.id = i; | |
| data.features.push(feature); | |
| }) | |
| mapObj.getSource('extrusion_source').setData(data); | |
| } | |
| mapObj.on('data', function(e) { | |
| if (e.sourceId !== 'data') return | |
| update() | |
| }) | |
| }) | |
| mapObj.on('mousemove', 'extrusion', function(e) { | |
| mapObj.getCanvasContainer().style.cursor = 'pointer'; | |
| if (hoveredTowerId) { | |
| mapObj.setFeatureState( | |
| { source: 'extrusion_source', id: hoveredTowerId }, | |
| { hover: false } | |
| ); | |
| } | |
| hoveredTowerId = e.features[0].id; | |
| mapObj.setFeatureState( | |
| { source: 'extrusion_source', id: hoveredTowerId }, | |
| { hover: true } | |
| ); | |
| updatePosition(e.features[0].properties) | |
| }); | |
| mapObj.on('mouseleave', 'extrusion', function() { | |
| mapObj.getCanvasContainer().style.cursor = 'default'; | |
| mapObj.setFeatureState( | |
| { source: 'extrusion_source', id: hoveredTowerId }, | |
| { hover: false } | |
| ); | |
| hoveredTowerId = null; | |
| }); | |
| const updatePosition = function(props) { | |
| const info = | |
| '<p>Name: ' + props.name + '</p>' + | |
| '<p>Height of tower: ' + props.full_value + 'm</p>' + | |
| '<p>Height of observatory: ' + props.observatory_value + 'm</p>'; | |
| position.html(info); | |
| }; | |
| }) | |
| })(); |
| name | full_height | observatory_height | lat | lng | |
|---|---|---|---|---|---|
| 東京スカイツリー | 634 | 451.2 | 35.70998 | 139.810643 | |
| 東京タワー | 332.6 | 250 | 35.658617 | 139.745552 | |
| 福岡タワー | 234 | 123 | 33.593331 | 130.351525 | |
| 名古屋テレビ塔 | 180 | 100 | 35.17155 | 136.907637 | |
| 梅田スカイビル | 173 | 170 | 34.705374 | 135.490524 | |
| ゴールドタワー | 158 | 127 | 34.31177 | 133.808595 | |
| 海峡ゆめタワー | 153 | 143 | 33.95065 | 130.928888 | |
| さっぽろテレビ塔 | 147.2 | 90.38 | 43.061132 | 141.35639 | |
| 秋田市ポートタワー | 143 | 100 | 39.75176 | 140.061947 | |
| ツインアーチ138 | 138 | 100 | 35.357704 | 136.80906 | |
| 東山スカイタワー | 134 | 100 | 35.156694 | 136.97884 | |
| 瀬戸大橋タワー | 132 | 108 | 34.352083 | 133.825236 | |
| 千葉ポートタワー | 125 | 112 | 35.600432 | 140.097845 | |
| クロスランドタワー | 118 | 100 | 36.656613 | 136.87863 | |
| 神戸ポートタワー | 108 | 90.8 | 34.684904 | 135.18552 | |
| 五稜郭タワー | 107 | 90 | 41.794766 | 140.754021 | |
| 横浜マリンタワー | 106 | 100 | 35.446179 | 139.635689 | |
| 通天閣 | 103 | 91 | 34.651962 | 135.506152 | |
| 別府タワー | 90 | 55 | 33.281325 | 131.506216 | |
| 銚子ポートタワー | 57.5 | 46.95 | 35.740915 | 140.862859 | |
| 東尋坊タワー | 55 | 52 | 36.166928 | 136.231465 | |
| 夢みなとタワー | 43 | 37 | 35.519779 | 133.259184 |