Skip to content

Instantly share code, notes, and snippets.

@ivanmalagon
Created June 6, 2018 16:33
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ivanmalagon/d4ea54eab95b33553033ddb56e790725 to your computer and use it in GitHub Desktop.
Save ivanmalagon/d4ea54eab95b33553033ddb56e790725 to your computer and use it in GitHub Desktop.
Madrid commuting - Hackarto VL
/******/ (function(modules) { // webpackBootstrap
/******/ // The module cache
/******/ var installedModules = {};
/******/
/******/ // The require function
/******/ function __webpack_require__(moduleId) {
/******/
/******/ // Check if module is in cache
/******/ if(installedModules[moduleId])
/******/ return installedModules[moduleId].exports;
/******/
/******/ // Create a new module (and put it into the cache)
/******/ var module = installedModules[moduleId] = {
/******/ i: moduleId,
/******/ l: false,
/******/ exports: {}
/******/ };
/******/
/******/ // Execute the module function
/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
/******/
/******/ // Flag the module as loaded
/******/ module.l = true;
/******/
/******/ // Return the exports of the module
/******/ return module.exports;
/******/ }
/******/
/******/
/******/ // expose the modules object (__webpack_modules__)
/******/ __webpack_require__.m = modules;
/******/
/******/ // expose the module cache
/******/ __webpack_require__.c = installedModules;
/******/
/******/ // identity function for calling harmony imports with the correct context
/******/ __webpack_require__.i = function(value) { return value; };
/******/
/******/ // define getter function for harmony exports
/******/ __webpack_require__.d = function(exports, name, getter) {
/******/ if(!__webpack_require__.o(exports, name)) {
/******/ Object.defineProperty(exports, name, {
/******/ configurable: false,
/******/ enumerable: true,
/******/ get: getter
/******/ });
/******/ }
/******/ };
/******/
/******/ // getDefaultExport function for compatibility with non-harmony modules
/******/ __webpack_require__.n = function(module) {
/******/ var getter = module && module.__esModule ?
/******/ function getDefault() { return module['default']; } :
/******/ function getModuleExports() { return module; };
/******/ __webpack_require__.d(getter, 'a', getter);
/******/ return getter;
/******/ };
/******/
/******/ // Object.prototype.hasOwnProperty.call
/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
/******/
/******/ // __webpack_public_path__
/******/ __webpack_require__.p = "";
/******/
/******/ // Load entry module and return exports
/******/ return __webpack_require__(__webpack_require__.s = 1);
/******/ })
/************************************************************************/
/******/ ([
/* 0 */,
/* 1 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var minutesToPlainEnglish = __webpack_require__(2);
var map = new mapboxgl.Map({
container: 'map',
style: 'https://basemaps.cartocdn.com/gl/dark-matter-gl-style/style.json',
center: [-3.7038, 40.4168],
zoom: 9,
dragRotate: false
});
carto.setDefaultAuth({
user: 'hacheka',
apiKey: 'Za3L-od8m-R1AODP_qDP2Q'
});
var s = carto.expressions;
// Sources
var routes = new carto.source.Dataset('commuting_routes');
var homes = new carto.source.Dataset('home');
var workplaces = new carto.source.SQL('select a.*, b.duration from mad_comm_work a, commuting_routes b where a.cartodb_id = b.cartodb_id');
// Variables
var postalCodeProp = s.prop('postalcode');
var homeCpProp = s.prop('home_cp');
var workCpProp = s.prop('home_cp');
var workCommutersProp = s.prop('commuters');
var durationProp = s.prop('duration');
var duration = s.prop('duration');
var commutersProp = s.prop('commuters');
// Viz Taylor
var routesViz = new carto.Viz({
variables: {
duration: durationProp,
homeCp: homeCpProp,
commuters: commutersProp
},
width: s.mul(s.div(s.log(commutersProp), s.log(s.globalMax(commutersProp))), 5),
color: s.ramp(s.globalQuantiles(duration, 4), s.palettes.TROPIC),
filter: 0
});
var homesViz = new carto.Viz({
variables: {
postalCode: postalCodeProp,
selectedPoly: 0
},
// color: s.blend(s.rgba(114, 170, 161, 0.2), s.rgba(0, 147, 146, 0.2), s.var('polyColor')),
color: s.rgba(114, 170, 161, 0.2),
strokeColor: s.blend(s.rgba(255, 255, 255, 0.2), s.rgba(159, 227, 221, 1), s.var('selectedPoly')),
strokeWidth: s.blend(0.5, 2, s.var('selectedPoly'))
});
var workplacesViz = new carto.Viz({
variables: {
polyColor: 0
},
color: s.ramp(s.prop('comm_norm'), [s.rgba(114, 170, 161, 0.2), s.rgba(114, 170, 161, 0.8)]),
strokeWidth: 0,
filter: 0
});
// Layers
var routesLayer = new carto.Layer('routesLayer', routes, routesViz);
var homesLayer = new carto.Layer('homesLayer', homes, homesViz);
var workplacesLayer = new carto.Layer('workplacesLayer', workplaces, workplacesViz);
homesLayer.addTo(map);
workplacesLayer.addTo(map);
routesLayer.addTo(map);
var intervalId = 0;
// Interactivity
var isTorqueApplied = false;
var routesTorque = null;
var homesInteractivity = new carto.Interactivity(homesLayer);
homesInteractivity.on('featureClick', function (event) {
if (event.features.length === 0) {
return;
}
var postalCode = event.features[0].variables.postalCode.value;
homesViz.variables.selectedPoly.blendTo(s.eq(postalCodeProp, postalCode));
routesTorque = s.torque(durationProp, 20, s.fade(0.1, 1000));
routesViz.filter = s.and(routesTorque, s.eq(homeCpProp, postalCode));
workplacesViz.filter = s.and(s.torque(durationProp, 20, s.fade(0.1, 1000)), s.eq(workCpProp, postalCode));
var cpEl = document.getElementById('cp');
cpEl.textContent = 'CP ' + postalCode;
isTorqueApplied = true;
});
homesInteractivity.on('featureClickOut', function (event) {
clearInterval(intervalId);
homesViz.variables.selectedPoly.blendTo(0);
routesLayer.filter = 0;
workplacesViz.filter = 0;
isTorqueApplied = false;
});
var lastTimestamp = '';
setInterval(function () {
if (isTorqueApplied && routesTorque) {
var simTime = routesTorque.getSimTime();
if (simTime !== lastTimestamp) {
lastTimestamp = simTime;
var formula = document.getElementById('formula');
var msg = '';
formula.className = 'short';
if (lastTimestamp <= 15) {
msg += '😀';
} else if (lastTimestamp <= 30) {
msg += '🙂';
} else if (lastTimestamp <= 45) {
msg += '😐';
formula.className = 'long';
} else if (lastTimestamp <= 60) {
msg += '🙁';
formula.className = 'long';
} else if (lastTimestamp <= 80) {
msg += '😥';
formula.className = 'hell';
} else if (lastTimestamp <= 120) {
msg += '😰';
formula.className = 'hell';
} else if (lastTimestamp <= 240) {
msg += '😱';
formula.className = 'hell';
} else {
msg += '🤬';
formula.className = 'hell';
}
msg += ' ' + minutesToPlainEnglish(lastTimestamp);
formula.textContent = msg;
}
}
}, 50);
window.s = s;
/***/ }),
/* 2 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
function minutesToPlainEnglish(duration) {
if (duration <= 0) {
return '0m';
}
var hours = Math.floor(duration / 60);
var minutes = Math.floor(duration % 60);
return hours + 'h ' + minutes + 'm';
}
module.exports = minutesToPlainEnglish;
/***/ })
/******/ ]);
//# sourceMappingURL=bundle.js.map
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Madrid Commuting Patterns</title>
<meta name="description" content="Hackarto VL">
<link rel="stylesheet" href="./styles.css">
<link href="https://fonts.googleapis.com/css?family=Squada+One" rel="stylesheet">
<link href="https://fonts.googleapis.com/css?family=Sunflower:500,700" rel="stylesheet">
<script src="https://libs.cartocdn.com/carto-vl/v0.5.0-beta.2/carto-vl.js"></script>
<script src="https://libs.cartocdn.com/mapbox-gl/v0.45.0-carto1/mapbox-gl.js"></script>
<link href="https://libs.cartocdn.com/mapbox-gl/v0.45.0-carto1/mapbox-gl.css" rel="stylesheet" />
</head>
<body>
<main>
<div id="map"></div>
</main>
<aside>
<h1>MADRID COMMUTING PATTERNS</h1>
<p>Click on the different postal codes to watch how people go from their <i class="homes">homes</i> to their workplaces in Madrid.</p>
<p id="cp"></p>
<p id="formula"></p>
</aside>
<script src="./bundle.js"></script>
</body>
</html>
/* CSS Reset */
html, body, div, span, applet, object, iframe,
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
a, abbr, acronym, address, big, cite, code,
del, dfn, em, img, ins, kbd, q, s, samp,
small, strike, strong, sub, sup, tt, var,
b, u, i, center,
dl, dt, dd, ol, ul, li,
fieldset, form, label, legend,
table, caption, tbody, tfoot, thead, tr, th, td,
article, aside, canvas, details, embed,
figure, figcaption, footer, header, hgroup,
menu, nav, output, ruby, section, summary,
time, mark, audio, video {
margin: 0;
padding: 0;
border: 0;
font-size: 100%;
font: inherit;
vertical-align: baseline;
}
/* HTML5 display-role reset for older browsers */
article, aside, details, figcaption, figure,
footer, header, hgroup, menu, nav, section {
display: block;
}
body {
line-height: 1;
}
ol, ul {
list-style: none;
}
blockquote, q {
quotes: none;
}
blockquote:before, blockquote:after,
q:before, q:after {
content: '';
content: none;
}
table {
border-collapse: collapse;
border-spacing: 0;
}
/* Custom styles */
h1 {
font-family: 'Squada One';
font-size: 32px;
margin: 16px;
color: white;
}
p {
font-family: 'Sunflower', sans-serif;
font-size: 16px;
margin: 16px;
line-height: 24px;
}
#formula {
font-size: 32px;
}
#cp {
font-size: 24px;
color: white;
}
i.homes {
color: rgba(159, 227, 221, 1);
}
#map {
position: absolute;
height: 100%;
width: 100%;
}
aside {
position: absolute;
top: 16px;
left: 16px;
background-color: rgba(255, 255, 255, 0.4);
min-width: 256px;
max-width: 256px;
}
.short {
color: rgba(1, 154, 158, 1);
}
.long {
color: rgba(179, 212, 212, 1);
}
.hell {
color: rgba(223, 34, 195, 1);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment