visualization with legend

This commit is contained in:
Hugoren Martinako 2020-12-12 13:55:49 +01:00
parent b6197fea33
commit 77b505ccfa
19 changed files with 5472 additions and 9546 deletions

10
.editorconfig Normal file
View File

@ -0,0 +1,10 @@
# editorconfig.org
root = true
[*]
charset = utf-8
indent_size = 2
indent_style = space
insert_final_newline = true
trim_trailing_whitespace = true

194
.gitattributes vendored Normal file
View File

@ -0,0 +1,194 @@
## GITATTRIBUTES FOR WEB PROJECTS
#
# These settings are for any web project.
#
# Details per file setting:
# text These files should be normalized (i.e. convert CRLF to LF).
# binary These files are binary and should be left untouched.
#
# Note that binary is a macro for -text -diff.
######################################################################
## AUTO-DETECT
## Handle line endings automatically for files detected as
## text and leave all files detected as binary untouched.
## This will handle all files NOT defined below.
* text=auto
## SOURCE CODE
*.bat text eol=crlf
*.coffee text
*.css text
*.htm text
*.html text
*.inc text
*.ini text
*.js text
*.json text
*.jsx text
*.less text
*.od text
*.onlydata text
*.php text
*.pl text
*.py text
*.rb text
*.sass text
*.scm text
*.scss text
*.sh text eol=lf
*.sql text
*.styl text
*.tag text
*.ts text
*.tsx text
*.xml text
*.xhtml text
## DOCKER
*.dockerignore text
Dockerfile text
## DOCUMENTATION
*.markdown text
*.md text
*.mdwn text
*.mdown text
*.mkd text
*.mkdn text
*.mdtxt text
*.mdtext text
*.txt text
AUTHORS text
CHANGELOG text
CHANGES text
CONTRIBUTING text
COPYING text
copyright text
*COPYRIGHT* text
INSTALL text
license text
LICENSE text
NEWS text
readme text
*README* text
TODO text
## TEMPLATES
*.dot text
*.ejs text
*.haml text
*.handlebars text
*.hbs text
*.hbt text
*.jade text
*.latte text
*.mustache text
*.njk text
*.phtml text
*.tmpl text
*.tpl text
*.twig text
## LINTERS
.babelrc text
.csslintrc text
.eslintrc text
.htmlhintrc text
.jscsrc text
.jshintrc text
.jshintignore text
.prettierrc text
.stylelintrc text
## CONFIGS
*.bowerrc text
*.cnf text
*.conf text
*.config text
.browserslistrc text
.editorconfig text
.gitattributes text
.gitconfig text
.gitignore text
.htaccess text
*.npmignore text
*.yaml text
*.yml text
browserslist text
Makefile text
makefile text
## HEROKU
Procfile text
.slugignore text
## GRAPHICS
*.ai binary
*.bmp binary
*.eps binary
*.gif binary
*.ico binary
*.jng binary
*.jp2 binary
*.jpg binary
*.jpeg binary
*.jpx binary
*.jxr binary
*.pdf binary
*.png binary
*.psb binary
*.psd binary
*.svg text
*.svgz binary
*.tif binary
*.tiff binary
*.wbmp binary
*.webp binary
## AUDIO
*.kar binary
*.m4a binary
*.mid binary
*.midi binary
*.mp3 binary
*.ogg binary
*.ra binary
## VIDEO
*.3gpp binary
*.3gp binary
*.as binary
*.asf binary
*.asx binary
*.fla binary
*.flv binary
*.m4v binary
*.mng binary
*.mov binary
*.mp4 binary
*.mpeg binary
*.mpg binary
*.ogv binary
*.swc binary
*.swf binary
*.webm binary
## ARCHIVES
*.7z binary
*.gz binary
*.jar binary
*.rar binary
*.tar binary
*.zip binary
## FONTS
*.ttf binary
*.eot binary
*.otf binary
*.woff binary
*.woff2 binary
## EXECUTABLES
*.exe binary
*.pyc binary

27
.gitignore vendored
View File

@ -1,23 +1,6 @@
.DS_Store
# Include your project-specific ignores in this file
# Read about how to use .gitignore: https://help.github.com/articles/ignoring-files
# Useful .gitignore templates: https://github.com/github/gitignore
node_modules
/dist
# local env files
.env.local
.env.*.local
# Log files
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
# Editor directories and files
.idea
.vscode
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?
dist
.cache

1225
.htaccess Normal file

File diff suppressed because it is too large Load Diff

View File

@ -1,24 +0,0 @@
# 1calle1nombre
## Project setup
```
npm install
```
### Compiles and hot-reloads for development
```
npm run serve
```
### Compiles and minifies for production
```
npm run build
```
### Lints and fixes files
```
npm run lint
```
### Customize configuration
See [Configuration Reference](https://cli.vuejs.org/config/).

View File

@ -1,5 +0,0 @@
module.exports = {
presets: [
'@vue/cli-plugin-babel/preset'
]
}

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

6
index.html Normal file
View File

@ -0,0 +1,6 @@
<html>
<body>
<div id="map"></div>
<script src="./index.js"></script>
</body>
</html>

91
index.js Normal file
View File

@ -0,0 +1,91 @@
import { geoMercator, geoPath } from "d3-geo"
import { select } from "d3-selection"
import { dsv } from "d3-fetch"
import { extent } from "d3-array"
import { scaleQuantile } from "d3-scale"
import { schemeGreens } from "d3-scale-chromatic"
import { feature } from "topojson-client"
import data from "./data/valladolid.topo.json"
const projection = geoMercator()
const path = geoPath(projection)
const feat = feature(data, data.objects.valladolid)
const styler = (node, style = {}) => Object.entries(style).forEach(([prop,val]) => node.style(prop,val))
const map = select("#map")
styler(map, { width: "100%", height: "100%" })
const { width, height } = map.node().getBoundingClientRect()
const svg = map
.append("svg")
.attr("viewBox", [0, 0, width, height])
const tooltip = map.append("div")
.style("position", "absolute")
.style("opacity", 0)
dsv(";", "./data/report.202012.csv", ({ name, a, b, date: d }) => ({ name, result: +b !== 0 ? 1 - (+a/+b) : 0, date: new Date(d) })).then(r => {
const months = [... new Set(r.map(({ date }) => date.getMonth()))].sort()
const [currentMonth] = months.slice(-1)
const { features } = feat
const edited = features.map(f => {
const { properties: { nombre }} = f
const match = r.find(({ name, date }) => name === nombre && date.getMonth() === currentMonth)
return { ...f, properties: { ...f.properties, ...match }}
})
feat.features = edited
projection.fitSize([width,height], feat);
const range = schemeGreens[5]
const color = scaleQuantile(range).domain(extent(r, d => d.result))
const items = svg.append("g").selectAll("path").data(feat.features)
const legend = svg.append("g").selectAll("rect").data(range)
legend
.enter()
.append("rect")
.attr("width", "10px")
.attr("height", "10px")
.attr("y", (_, i) => `${i}em`)
.attr("fill", d => d)
legend
.enter()
.append("text")
.attr("dominant-baseline", "hanging")
.attr("dx", "15px")
.attr("dy", (_, i) => `${i}em`)
.text(d => {
const [start, end] = color.invertExtent(d)
const percent = (num = 0)=> num.toLocaleString(undefined, { style: "percent" })
return `${percent(start)} - ${percent(end)}`
})
legend
.exit()
.remove()
items
.enter()
.append("path")
.attr("d", d => path(d))
.attr("fill", ({ properties: { result }}) => color(result))
.attr("stroke","steelblue")
.on("mouseenter", ({ pageX, pageY }, { properties: {name, date, result} }) => {
styler(tooltip, { opacity: 1, top: `${pageY}px`, left: `${pageX}px`, background: "#fff", border: "1px solid #eee", padding: "5px", "box-shadow": "0px 0px 10px 0px rgba(0,0,0,0.75)", "border-radius": "5px", "transition": "opacity 250ms" })
tooltip.html(`${name} (${date.toLocaleDateString(undefined, { year: "2-digit", month: "short"})}): ${result.toLocaleString(undefined, { style: "percent" })}`)
})
.on("mouseleave", (e) => {
styler(tooltip, { opacity: 0 })
})
items
.exit()
.remove()
})

91
index.js~ Normal file
View File

@ -0,0 +1,91 @@
import { geoMercator, geoPath } from "d3-geo"
import { select } from "d3-selection"
import { dsv } from "d3-fetch"
import { extent } from "d3-array"
import { scaleQuantile } from "d3-scale"
import { schemeGreens } from "d3-scale-chromatic"
import { feature } from "topojson-client"
import data from "./data/valladolid.topo.json"
const projection = geoMercator()
const path = geoPath(projection)
const feat = feature(data, data.objects.valladolid)
const styler = (node, style = {}) => Object.entries(style).forEach(([prop,val]) => node.style(prop,val))
const map = select("#map")
styler(map, { width: "100%", height: "100%" })
const { width, height } = map.node().getBoundingClientRect()
const svg = map
.append("svg")
.attr("viewBox", [0, 0, width, height])
const tooltip = map.append("div")
.style("position", "absolute")
.style("opacity", 0)
dsv(";", "./data/report.202012.csv", ({ name, a, b, date: d }) => ({ name, result: +b !== 0 ? 1 - (+a/+b) : 0, date: new Date(d).getMonth() })).then(r => {
const months = [... new Set(r.map(({ date }) => date))].sort()
const [currentMonth] = months.slice(-1)
const { features } = feat
const edited = features.map(f => {
const { properties: { nombre }} = f
const match = r.find(({ name, date }) => name === nombre && date === currentMonth)
return { ...f, properties: { ...f.properties, ...match }}
})
feat.features = edited
projection.fitSize([width,height], feat);
const range = schemeGreens[5]
const color = scaleQuantile(range).domain(extent(r, d => d.result))
const items = svg.append("g").selectAll("path").data(feat.features)
const legend = svg.append("g").selectAll("rect").data(range)
legend
.enter()
.append("rect")
.attr("width", "10px")
.attr("height", "10px")
.attr("y", (_, i) => `${i}em`)
.attr("fill", d => d)
legend
.enter()
.append("text")
.attr("dominant-baseline", "hanging")
.attr("dx", "15px")
.attr("dy", (_, i) => `${i}em`)
.text(d => {
const [start, end] = color.invertExtent(d)
const percent = (num = 0)=> num.toLocaleString(undefined, { style: "percent" })
return `${percent(start)} - ${percent(end)}`
})
legend
.exit()
.remove()
items
.enter()
.append("path")
.attr("d", d => path(d))
.attr("fill", ({ properties: { result }}) => color(result))
.attr("stroke","steelblue")
.on("mouseenter", ({ pageX, pageY }, { properties: {name, date, result} }) => {
styler(tooltip, { opacity: 1, top: `${pageY}px`, left: `${pageX}px`, background: "#fff", border: "1px solid #eee", padding: "5px", "box-shadow": "0px 0px 10px 0px rgba(0,0,0,0.75)", "border-radius": "5px", "transition": "opacity 250ms" })
tooltip.html(`${name} (${date.toLocaleDateString(undefined, { year: "2-digit", month: "short"})}): ${result.toLocaleString(undefined, { style: "percent" })}`)
})
.on("mouseleave", (e) => {
styler(tooltip, { opacity: 0 })
})
items
.exit()
.remove()
})

9134
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -1,42 +1,24 @@
{
"name": "1calle1nombre",
"version": "0.1.0",
"private": true,
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"serve": "vue-cli-service serve",
"build": "vue-cli-service build",
"lint": "vue-cli-service lint"
"start": "parcel index.html",
"test": "echo \"Error: no test specified\" && exit 1"
},
"repository": {
"type": "git",
"url": "gitea@pi2:Crashillo/1calle1nombre.git"
},
"author": "",
"license": "ISC",
"dependencies": {
"core-js": "^3.6.5",
"vue": "^3.0.0"
},
"devDependencies": {
"@vue/cli-plugin-babel": "~4.5.0",
"@vue/cli-plugin-eslint": "~4.5.0",
"@vue/cli-service": "~4.5.0",
"@vue/compiler-sfc": "^3.0.0",
"babel-eslint": "^10.1.0",
"eslint": "^6.7.2",
"eslint-plugin-vue": "^7.0.0-0"
},
"eslintConfig": {
"root": true,
"env": {
"node": true
},
"extends": [
"plugin:vue/vue3-essential",
"eslint:recommended"
],
"parserOptions": {
"parser": "babel-eslint"
},
"rules": {}
},
"browserslist": [
"> 1%",
"last 2 versions",
"not dead"
]
"d3": "^6.3.1",
"d3-color-legend": "^1.3.1",
"d3-svg-legend": "^2.25.6",
"data": "^0.6.1",
"parcel-bundler": "^1.12.4",
"topojson-client": "^3.1.0"
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.2 KiB

View File

@ -1,17 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
<title><%= htmlWebpackPlugin.options.title %></title>
</head>
<body>
<noscript>
<strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
</noscript>
<div id="app"></div>
<!-- built files will be auto injected -->
</body>
</html>

View File

@ -1,26 +0,0 @@
<template>
<img alt="Vue logo" src="./assets/logo.png">
<HelloWorld msg="Welcome to Your Vue.js App"/>
</template>
<script>
import HelloWorld from './components/HelloWorld.vue'
export default {
name: 'App',
components: {
HelloWorld
}
}
</script>
<style>
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
</style>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.7 KiB

View File

@ -1,58 +0,0 @@
<template>
<div class="hello">
<h1>{{ msg }}</h1>
<p>
For a guide and recipes on how to configure / customize this project,<br>
check out the
<a href="https://cli.vuejs.org" target="_blank" rel="noopener">vue-cli documentation</a>.
</p>
<h3>Installed CLI Plugins</h3>
<ul>
<li><a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-babel" target="_blank" rel="noopener">babel</a></li>
<li><a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-eslint" target="_blank" rel="noopener">eslint</a></li>
</ul>
<h3>Essential Links</h3>
<ul>
<li><a href="https://vuejs.org" target="_blank" rel="noopener">Core Docs</a></li>
<li><a href="https://forum.vuejs.org" target="_blank" rel="noopener">Forum</a></li>
<li><a href="https://chat.vuejs.org" target="_blank" rel="noopener">Community Chat</a></li>
<li><a href="https://twitter.com/vuejs" target="_blank" rel="noopener">Twitter</a></li>
<li><a href="https://news.vuejs.org" target="_blank" rel="noopener">News</a></li>
</ul>
<h3>Ecosystem</h3>
<ul>
<li><a href="https://router.vuejs.org" target="_blank" rel="noopener">vue-router</a></li>
<li><a href="https://vuex.vuejs.org" target="_blank" rel="noopener">vuex</a></li>
<li><a href="https://github.com/vuejs/vue-devtools#vue-devtools" target="_blank" rel="noopener">vue-devtools</a></li>
<li><a href="https://vue-loader.vuejs.org" target="_blank" rel="noopener">vue-loader</a></li>
<li><a href="https://github.com/vuejs/awesome-vue" target="_blank" rel="noopener">awesome-vue</a></li>
</ul>
</div>
</template>
<script>
export default {
name: 'HelloWorld',
props: {
msg: String
}
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
h3 {
margin: 40px 0 0;
}
ul {
list-style-type: none;
padding: 0;
}
li {
display: inline-block;
margin: 0 10px;
}
a {
color: #42b983;
}
</style>

View File

@ -1,4 +0,0 @@
import { createApp } from 'vue'
import App from './App.vue'
createApp(App).mount('#app')