v0.02 sync x axis

This commit is contained in:
T__o 2020-04-26 23:04:17 +02:00
parent 54b47af0dc
commit aae0790c27
6 changed files with 113 additions and 43 deletions

View File

@ -1,4 +1,4 @@
# covcharts
# CovCharts
Charts on COVID 19
@ -6,4 +6,14 @@ Using vuejs and d3
Data source from : https://github.com/pomber/covid19
**Numbers are not reality**
## Features :
- sync X axis at a value
- reset (broken, need reload page too)
- set a limit for y axis
- select first and last day
- select data source (confirmed, deaths, recovered)
- select scale (log/linear)
- select countries

1
doc.md
View File

@ -3,6 +3,7 @@
# Changelog
v0.02 sync x axis
v0.01 repack, data auto loading

View File

@ -34,13 +34,13 @@
<v-row align="center" justify="center" id="maincontent" ref="maincontent">
<v-col class="shrink">
<MultiCountryChart
:countries="countriesData"
:scaleType="chartConfig.scaleSelected"
:dataType="chartConfig.typeSelected"
:width="chartWidth"
:height="chartWidth * (2/3)"
:since="syncSinceInt"
/>
<MultiBarChartSingle
@ -75,6 +75,8 @@
import DataLoader from './components/DataLoader'
MultiBarChartSingle
let limit = (value, min, max) => {
return value > max ? max : value < min ? min : value
}
@ -102,6 +104,7 @@
dayStart: 30,
dayEnd: 0,
ymax: 0,
syncSince: 0,
resetConfig: false,
},
countriesConfig: {
@ -133,6 +136,7 @@
// Todo list of all countries using localstorage
//all: Object.keys(AllData).sort(),
},
debug: false,
}),
watch: {
drawer() {
@ -163,27 +167,36 @@
},
methods: {
loadConfig() {
let uc = localStorage.getItem('userConfig')
if (uc && uc !== 'null') {
uc = JSON.parse(uc)
this.countriesConfig = uc.countriesConfig
this.chartConfig = uc.chartConfig
this.ccc("loadConfig storage")
} else {
this.countriesConfig = defaultUserConfig.countriesConfig
this.chartConfig = defaultUserConfig.chartConfig
this.ccc("loadConfig default")
}
},
saveConfig() {
this.ccc("saveConfig")
let userConfig = {countriesConfig: this.countriesConfig, chartConfig: this.chartConfig}
localStorage.setItem('userConfig', JSON.stringify(userConfig))
},
resetConfig() {
localStorage.setItem('userConfig', 'null')
this.ccc("resetConfig")
this.loadConfig()
},
ccc(a, b) {
if (this.debug) console.log(a, b)
},
},
computed: {
syncSinceInt() {
return parseInt(this.chartConfig.syncSince)
},
countriesData() {
if (!('France' in this.allData)) {
@ -195,11 +208,29 @@
this.countriesConfig.selected.map((country) => {
let cdata = JSON.parse(JSON.stringify(this.allData[country.name]))
let itemsCount = cdata.length
let filtered = cdata.filter((e, i) =>
let filtered = JSON.parse(JSON.stringify(this.allData[country.name]))
if (this.syncSinceInt !== 0) {
filtered = filtered.filter((e) => {
//console.log(' e', e[this.chartConfig.typeSelected], syncSince, typeof this.syncSince)
return e[this.chartConfig.typeSelected] >= this.syncSinceInt
}
)
}
if (this.chartConfig.ymax > 0) {
filtered = filtered.map((d) => {
this.configLists.typesList.map(e => {
d[e] = d[e] > this.chartConfig.ymax ? NaN : d[e]
})
return d
})
}
filtered = filtered.filter((e, i) =>
i >= (this.chartConfig.dayStart - 1) &&
i < (itemsCount - this.chartConfig.dayEnd))
i < (filtered.length - this.chartConfig.dayEnd)
)
if (addSomeDays) {
// Adding addDays data points
@ -215,14 +246,6 @@
}
}
if (this.chartConfig.ymax > 0) {
filtered = filtered.map((d) => {
this.configLists.typesList.map(e => {
d[e] = d[e] > this.chartConfig.ymax ? this.chartConfig.ymax : d[e]
})
return d
})
}
// // Get ymax
// filtered.map(d => {
// ymax = d[this.dataSelected] > ymax ? d[this.dataSelected] : ymax
@ -231,7 +254,6 @@
country.list = filtered
formatedData.push(country)
})
return formatedData
}
}

View File

@ -17,6 +17,7 @@
</v-list-item>
<v-list-item>
<v-list-item-action>Type</v-list-item-action>
<v-list-item-content>
@ -56,12 +57,12 @@
</v-list-item>
<v-list-item>
<v-list-item-action> y Max</v-list-item-action>
<v-list-item-action>Sync X </v-list-item-action>
<v-list-item-content>
<v-text-field
class="ymax"
v-model="configs.ymax"
label="ymaxx"
class="numField"
v-model="configs.syncSince"
label="syncSince"
solo
hide-details
single-line
@ -70,6 +71,22 @@
</v-list-item-content>
</v-list-item>
<v-list-item>
<v-list-item-action>Limit Y </v-list-item-action>
<v-list-item-content>
<v-text-field
class="numField"
v-model="configs.ymax"
label="ymaxx"
solo
hide-details
single-line
/>
</v-list-item-content>
</v-list-item>
<v-list-item>
<v-list-item-action></v-list-item-action>
<v-list-item-content>
@ -95,6 +112,13 @@
return {
}
},
watch:{
'configs.syncSince': function(value){
if ( ! (value > 0 ) ){
this.configs.syncSince = 0
}
}
},
methods: {
resetConfig() {
this.configs.resetConfig = true
@ -111,7 +135,7 @@
margin: 0px;
}
.ymax {
.numField {
max-width: 50%;
}

View File

@ -7,7 +7,7 @@
:x="scales.x(new Date(day.date))"
:y="scales.y(day.value)"
:width="colsize"
:height="height-scales.y(day.value)"
:height="calcHeight(day.value)"
class="barChartRect"
></rect>
<!-- <path-->
@ -69,6 +69,7 @@
},
},
computed: {
colsize() {
return this.scales.x(new Date(this.dataChart[1].date)) - 1
},
@ -113,6 +114,10 @@
},
},
methods: {
calcHeight(value){
let v = this.height-this.scales.y(value)
return v > 0 ? v: 0
},
calculatePath(data) {
//console.log('datata',data)

View File

@ -1,6 +1,7 @@
<template>
<div>
<svg :class="svgClass" :width="width" :height="height">
<g style="transform: translate(2px, 2px)">
@ -17,7 +18,7 @@
<circle v-for="(point,i) in (cinfo.list)"
:key="'c'+i"
:style="{fill:cinfo.color}"
:cx="scales.x(new Date(point.date))"
:cx="scales.x(xconvert(point,i))"
:cy="scales.y(point[dataType])"
r="2"
/>
@ -25,14 +26,14 @@
<circle v-for="(point,i) in (cinfo.list)"
opacity="0"
:key="'cinv'+i"
:cx="scales.x(new Date(point.date))"
:cx="scales.x(xconvert(point,i))"
:cy="scales.y(point[dataType])"
r="7"
@mouseover="overPoint(point,cinfo.color)"
@mouseover="overPoint(point,i,cinfo.color)"
/>
<rect :x="overpoint.x"
:y="overpoint.y-10"
:y="overpoint.y"
:width=" (6+overpoint.text.toString().length) * 4"
:height="18"
/>
@ -73,6 +74,7 @@
dataType: String,
width: Number,
height: Number,
since: Number,
},
data() {
return {
@ -91,6 +93,7 @@
},
mounted() {
this.drawAxis()
},
watch: {
scaleType() {
@ -104,16 +107,18 @@
minmax() {
let max = {x: 0, y: 0}
let min = {x: new Date(), y: undefined}
let min = {x: undefined, y: undefined}
this.countries.forEach(country => {
country.list.forEach((item) => {
country.list.forEach((item, i) => {
let value = item[this.dataType]
let dayvalue = new Date(item.date)
let dayvalue = this.xconvert(item, i)
max.x = max.x < dayvalue ? dayvalue : max.x
max.y = max.y < value ? value : max.y
if (typeof min.x === "undefined") min.x = dayvalue
min.x = min.x > dayvalue ? dayvalue : min.x
if (typeof min.y === "undefined") min.y = value
min.y = min.y > value ? value : min.y
@ -121,15 +126,14 @@
})
})
//console.log(' {min: min, max: max} ', min.y, max, this.scaleType)
return {min: min, max: max}
},
scales() {
let scales = {}
scales.x = scaleTime()
.domain([this.minmax.min.x, this.minmax.max.x])
scales.x = parseInt(this.since) > 0 ? scaleLinear() : scaleTime()
scales.x = scales.x.domain([this.minmax.min.x, this.minmax.max.x])
.range([0, this.width - 2 * this.margin.x])
// !!scaleLog need to start at 1 not 0!!
@ -143,8 +147,13 @@
},
methods: {
overPoint(point, color) {
xconvert(d, i) {
if (parseInt(this.since) > 0) {
return i
}
return new Date(d.date)
},
overPoint(point,i, color) {
if (point === 'reset') {
this.overpoint = {
x: 0, y: 0, text: ""
@ -153,17 +162,16 @@
}
this.overpoint = {
x: this.scales.x(new Date(point.date)),
x: this.scales.x(this.xconvert(point,i)),
y: this.scales.y(point [this.dataType]),
text: point.date.slice(5, 10) + ": " + point [this.dataType],
color: color,
}
},
calculatePath(data) {
//console.log('datata',data)
const path = line()
.x((d) => this.scales.x(new Date(d.date)))
.x((d, i) => this.scales.x(this.xconvert(d, i)))
.y(d => this.scales.y(d[this.dataType] === 0 ? 1 : d[this.dataType]))
return path(data)