Permalink
Cannot retrieve contributors at this time
Join GitHub today
GitHub is home to over 28 million developers working together to host and review code, manage projects, and build software together.
Sign up
Fetching contributors…

<!DOCTYPE html> | |
<html> | |
<head> | |
<meta charset="utf-8"> | |
<meta name=”twitter:card” content=”summary_large_image”> | |
<meta name=”twitter:site” content=”@ceddc> | |
<meta name=”twitter:creator” content=”@ceddc> | |
<meta name=”twitter:title” content=”Evolution de l'année de construction des bâtiments de Paris entre 1600 et 2017”> | |
<meta name=”twitter:description” content=”Evolution de l'année de construction des bâtiments de Paris entre 1600 et 2017 avec l'API ArcGIS API for JavaScript”> | |
<meta name=”twitter:image” content=”https://ceddc.github.io/BitsofStuff/ArcGIS-Javascript-45-Paris-Buildings/newcard.png“> | |
<meta name="viewport" content="initial-scale=1,maximum-scale=1,user-scalable=no"> | |
<title>Evolution de l'année de construction des bâtiments de Paris entre 1600 et 2017</title> | |
<link rel="stylesheet" href="https://js.arcgis.com/4.5/esri/themes/dark-blue/main.css"> | |
<script> | |
var dojoConfig = { | |
has: { | |
// Enable webgl for feature layer in MapView | |
"esri-featurelayer-webgl": 1 | |
} | |
}; | |
</script> | |
<!-- Global Site Tag (gtag.js) - Google Analytics --> | |
<script async src="https://www.googletagmanager.com/gtag/js?id=UA-92318045-2"></script> | |
<script> | |
window.dataLayer = window.dataLayer || []; | |
function gtag(){dataLayer.push(arguments);} | |
gtag('js', new Date()); | |
gtag('config', 'UA-92318045-2'); | |
</script> | |
<script src="https://js.arcgis.com/4.5/"></script> | |
<style> | |
html, | |
body { | |
width: 100%; | |
height: 100%; | |
padding: 0; | |
margin: 0; | |
} | |
#applicationDiv { | |
position: absolute; | |
width: 100%; | |
height: 100%; | |
display: flex; | |
flex-direction: column; | |
overflow: hidden; | |
} | |
#viewDiv { | |
flex: 1 1 auto; | |
order: 1; | |
} | |
#titleDiv { | |
font-weight: 400; | |
font-style: normal; | |
font-size: 1.2019rem; | |
padding: 10px; | |
} | |
#sliderContainer { | |
flex: 0 0 80px; | |
order: 2; | |
display: flex; | |
flex-flow: row; | |
padding: 0 12px; | |
} | |
#sliderValue { | |
flex: 0 0 100px; | |
order: 1; | |
display: flex; | |
justify-content: center; | |
flex-direction: column; | |
text-align: center; | |
font-size: 300%; | |
} | |
#sliderInnerContainer { | |
flex: 1 1 auto; | |
order: 2; | |
display: flex; | |
flex-direction: column; | |
justify-content: center; | |
padding: 0 20px; | |
} | |
#sliderLabels { | |
flex: 1 1 auto; | |
order: 1; | |
display: flex; | |
justify-content: space-between; | |
margin-top: 20px; | |
} | |
#rangeWrapper { | |
flex: 1 1 auto; | |
order: 2; | |
position: relative; | |
padding: 0 20px; | |
} | |
#slider { | |
width: 100%; | |
} | |
/** | |
* Play/Stop toggle button | |
*/ | |
#playButton { | |
flex: 0 0 100px; | |
order: 3; | |
margin: 20px 0; | |
} | |
.toggle-button { | |
display: flex; | |
} | |
.toggle-button.toggled .toggle-button-icon { | |
color: #CC1B1B; | |
} | |
.toggle-button .toggle-button-icon { | |
color: #1BCC1B; | |
} | |
.toggle-button> :nth-child(2) { | |
display: none; | |
} | |
.toggle-button.toggled> :nth-child(1) { | |
display: none; | |
} | |
.toggle-button.toggled> :nth-child(2) { | |
display: block; | |
} | |
/** | |
* Hover tooltip | |
*/ | |
.tooltip { | |
position: absolute; | |
pointer-events: none; | |
transition: opacity 200ms; | |
} | |
.tooltip>div { | |
margin: 0 auto; | |
padding: 12px; | |
border-radius: 4px; | |
box-shadow: 0px 0px 4px rgba(255, 255, 255, 0.75); | |
transform: translate3d(-50%, -125%, 0); | |
} | |
</style> | |
<script> | |
require([ | |
"esri/Map", | |
"esri/layers/FeatureLayer", | |
"esri/views/MapView", | |
"esri/widgets/Legend", | |
"esri/widgets/Home", | |
"dojo/domReady!" | |
], function( | |
Map, | |
FeatureLayer, | |
MapView, | |
Legend, Home | |
) { | |
//-------------------------------------------------------------------------- | |
// | |
// Setup Map and View | |
// | |
//-------------------------------------------------------------------------- | |
var layer = new FeatureLayer({ | |
portalItem: { | |
id: "d50dd448c80e46cdbcee8adcd9945a0f" | |
}, | |
definitionExpression: "AN_CONST > 0", | |
title: "Bâtiment avec année de construction connue", | |
minScale: 144447.638572, | |
//racourcis | |
copyright: "<a href=\"http://opendata.apur.org\">Plateforme Open Data - Apur</a> | <a href=\"https://github.com/ceddc/BitsofStuff/tree/master/ArcGIS-Javascript-45-Paris-Buildings\">About</a> this dataviz" | |
}); | |
var map = new Map({ | |
basemap: { | |
portalItem: { | |
id: "4f2e99ba65e34bb8af49733d9778fb8e" | |
} | |
}, | |
layers: [layer] | |
}); | |
view = new MapView({ | |
map: map, | |
container: "viewDiv", | |
center: [2.349014, 48.864716], | |
zoom: 12, | |
constraints: { | |
snapToZoom: false, | |
minScale: 144447.638572 | |
}, | |
// This ensures that when going fullscreen | |
// The top left corner of the view extent | |
// stays aligned with the top left corner | |
// of the view's container | |
resizeAlign: "top-left" | |
}); | |
//-------------------------------------------------------------------------- | |
// | |
// Setup UI | |
// | |
//-------------------------------------------------------------------------- | |
var applicationDiv = document.getElementById("applicationDiv"); | |
var fullScreenButton = document.getElementById("fullScreenButton"); | |
var slider = document.getElementById("slider"); | |
var sliderValue = document.getElementById("sliderValue"); | |
var playButton = document.getElementById("playButton"); | |
var titleDiv = document.getElementById("titleDiv"); | |
var animation = null; | |
// When user drags the slider: | |
// - stops the animation | |
// - set the visualized year to the slider one. | |
slider.addEventListener("input", function() { | |
stopAnimation(); | |
setYear(parseInt(slider.value)); | |
}); | |
// Toggle animation on/off when user | |
// clicks on the play button | |
playButton.addEventListener("click", function() { | |
if (playButton.classList.contains("toggled")) { | |
stopAnimation(); | |
} | |
else { | |
startAnimation(); | |
} | |
}); | |
view.ui.empty("top-left"); | |
view.ui.add(titleDiv, "top-left"); | |
view.ui.add(new Home({ | |
view: view | |
}), "top-left"); | |
view.ui.add(new Legend({ | |
view: view | |
}), "bottom-left"); | |
// When the layerview is available, setup hovering interactivity | |
view.whenLayerView(layer).then(setupHoverTooltip); | |
view.whenLayerView(layer).then(layer.fetchAttributionData()) | |
// Starts the application by visualizing year 1984 | |
setYear(1789); | |
//-------------------------------------------------------------------------- | |
// | |
// Methods | |
// | |
//-------------------------------------------------------------------------- | |
/** | |
* Sets the current visualized construction year. | |
*/ | |
function setYear(value) { | |
sliderValue.innerHTML = Math.floor(value); | |
slider.value = Math.floor(value); | |
layer.renderer = createRenderer(value); | |
} | |
/** | |
* Returns a renderer with a color visual variable driven by the input | |
* year. The selected year will always render buildings built in that year | |
* with a light blue color. Buildings built 20+ years before the indicated | |
* year are visualized with a pink color. Buildings built within that | |
* 20-year time frame are assigned a color interpolated between blue and pink. | |
*/ | |
function createRenderer(year) { | |
var opacityStops = [ | |
{ | |
opacity: 1, | |
value: year | |
}, | |
{ | |
opacity: 0, | |
value: year + 1 | |
}]; | |
return { | |
type: "simple", | |
symbol: { | |
type: "simple-fill", | |
color: "rgb(0, 0, 0)", | |
outline: null | |
}, | |
visualVariables: [{ | |
type: "opacity", | |
field: "AN_CONST", | |
stops: opacityStops, | |
legendOptions: { | |
showLegend: false | |
} | |
}, { | |
type: "color", | |
field: "AN_CONST", | |
legendOptions: { | |
title: "Bâtiments construits:" | |
}, | |
stops: [{ | |
value: year, | |
color: "#0ff", | |
label: "en " + Math.floor(year) | |
}, { | |
value: year - 10, | |
color: "#f0f", | |
label: "en " + (Math.floor(year) - 20) | |
}, { | |
value: year - 50, | |
color: "#404", | |
label: "avant " + (Math.floor(year) - 50) | |
}] | |
}] | |
}; | |
} | |
/** | |
* Sets up a moving tooltip that displays | |
* the construction year of the hovered building. | |
*/ | |
function setupHoverTooltip(layerview) { | |
var promise; | |
var highlight; | |
var tooltip = createTooltip(); | |
view.on("pointer-move", function(event) { | |
if (promise) { | |
promise.cancel(); | |
} | |
promise = view.hitTest(event.x, event.y) | |
.then(hit => { | |
promise = null; | |
// remove current highlighted feature | |
if (highlight) { | |
highlight.remove(); | |
highlight = null; | |
} | |
// highlight the hovered feature | |
// or hide the tooltip | |
if (hit.results.length) { | |
var graphic = hit.results[0].graphic; | |
var screenPoint = hit.screenPoint; | |
highlight = layerview.highlight(graphic); | |
tooltip.show(screenPoint, "Bâtiment construit en " + graphic.getAttribute( | |
"AN_CONST")); | |
} | |
else { | |
tooltip.hide(); | |
} | |
}); | |
}); | |
} | |
/** | |
* Starts the animation that cycle | |
* through the construction years. | |
*/ | |
function startAnimation() { | |
stopAnimation(); | |
animation = animate(parseFloat(slider.value)); | |
playButton.classList.add("toggled"); | |
} | |
/** | |
* Stops the animations | |
*/ | |
function stopAnimation() { | |
if (!animation) { | |
return; | |
} | |
animation.remove(); | |
animation = null; | |
playButton.classList.remove("toggled"); | |
} | |
/** | |
* Animates the color visual variable continously | |
*/ | |
function animate(startValue) { | |
var animating = true; | |
var value = startValue; | |
var frame = function(timestamp) { | |
if (!animating) { | |
return; | |
} | |
value += 0.5; | |
if (value > 2017) { | |
value = 1600; | |
} | |
setYear(value); | |
// Update at 30fps | |
setTimeout(function() { | |
requestAnimationFrame(frame); | |
}, 1000 / 30); | |
} | |
frame(); | |
return { | |
remove: function() { | |
animating = false; | |
} | |
}; | |
} | |
/** | |
* Fullscreen API to easily move the application fullscreen | |
*/ | |
var fullscreenAPI = null; | |
var fullScreenFnNames = ["requestFullscreen", | |
"webkitRequestFullscreen", "mozRequestFullScreen", | |
"msRequestFullscreen" | |
]; | |
var fullscreenElementNames = ["fullscreenElement", | |
"webkitFullscreenElement", "mozFullScreenElement", | |
"msFullscreenElement" | |
]; | |
var exitFullscreenFnNames = ["exitFullscreen", "webkitExitFullscreen", | |
"mozCancelFullScreen", "msExitFullscreen" | |
]; | |
var fullScreenEventNames = ["fullscreenchange", | |
"webkitfullscreenchange", "mozfullscreenchange", | |
"MSFullscreenChange" | |
]; | |
fullScreenFnNames.some(function(fnName, index) { | |
if (!view.container[fnName]) { | |
fullscreenAPI = { | |
supported: false | |
}; | |
return false; | |
} | |
fullscreenAPI = { | |
supported: true, | |
eventName: fullScreenEventNames[index], | |
isFullscreen: function() { | |
return document[fullscreenElementNames[index]]; | |
}, | |
toggle: function() { | |
if (!document[fullscreenElementNames[index]]) { | |
applicationDiv[fnName](); | |
} else { | |
document[exitFullscreenFnNames[index]](); | |
} | |
} | |
} | |
return true; | |
}); | |
if (!fullscreenAPI.supported) { | |
fullScreenButton.parentElement.removeChild(fullScreenButton); | |
} | |
else { | |
fullScreenButton.addEventListener("click", fullscreenAPI.toggle) | |
document.addEventListener(fullscreenAPI.eventName, function() { | |
if (fullscreenAPI.isFullscreen()) { | |
fullScreenButton.firstChild.className = | |
"esri-icon-zoom-in-fixed"; | |
} | |
else { | |
fullScreenButton.firstChild.className = | |
"esri-icon-zoom-out-fixed"; | |
} | |
}); | |
view.ui.add(fullScreenButton, "top-right"); | |
} | |
/** | |
* Creates a tooltip to display a the construction year of a building. | |
*/ | |
function createTooltip() { | |
var tooltip = document.createElement("div"); | |
var style = tooltip.style; | |
tooltip.setAttribute("role", "tooltip"); | |
tooltip.classList.add("tooltip"); | |
var textElement = document.createElement("div"); | |
textElement.classList.add("esri-widget"); | |
tooltip.appendChild(textElement); | |
view.container.appendChild(tooltip); | |
var x = 0; | |
var y = 0; | |
var targetX = 0; | |
var targetY = 0; | |
var visible = false; | |
// move the tooltip progressively | |
function move() { | |
x += (targetX - x) * 0.1; | |
y += (targetY - y) * 0.1; | |
if (Math.abs(targetX - x) < 1 && Math.abs(targetY - y) < 1) { | |
x = targetX; | |
y = targetY; | |
} | |
else { | |
requestAnimationFrame(move); | |
} | |
style.transform = "translate3d(" + Math.round(x) + "px," + Math.round( | |
y - view.height) + "px, 0)"; | |
} | |
return { | |
show: function(point, text) { | |
if (!visible) { | |
x = point.x; | |
y = point.y; | |
} | |
targetX = point.x; | |
targetY = point.y; | |
style.opacity = 1; | |
visible = true; | |
textElement.innerHTML = text; | |
move(); | |
}, | |
hide: function() { | |
style.opacity = 0; | |
visible = false; | |
} | |
} | |
} | |
}); | |
</script> | |
</head> | |
<body> | |
<div id="applicationDiv"> | |
<div id="viewDiv"> | |
<div id="titleDiv" class="esri-widget">Evolution de l'année de construction des bâtiments de Paris entre 1600 et 2017</div> | |
<div id="fullScreenButton" class="esri-widget esri-widget-button"> | |
<span class="esri-icon-zoom-out-fixed" aria-label="fullscreen icon"></span> | |
</div> | |
</div> | |
<div id="sliderContainer" class="esri-widget"> | |
<span id="sliderValue"></span> | |
<div id="sliderInnerContainer"> | |
<div id="sliderLabels"> | |
<span>1600</span> | |
<span>2017</span> | |
</div> | |
<div id="rangeWrapper"> | |
<input id="slider" type="range" min="1600" max="2017" step="1" value="1789" /> | |
</div> | |
</div> | |
<div id="playButton" class="esri-widget esri-widget-button toggle-button"> | |
<div><span class="toggle-button-icon esri-icon-play" aria-label="play icon"></span> Play</div> | |
<div><span class="toggle-button-icon esri-icon-pause" aria-label="pause icon"></span> Pause</div> | |
</div> | |
</div> | |
</div> | |
</body> | |
</html> |