diff --git a/index.html b/index.html index 5e671d1d34c8cc6e39e4da296aeb99f3330e8912..5959f1e00fb7cc3952120c669b3ae39510b0e57c 100644 --- a/index.html +++ b/index.html @@ -19,6 +19,17 @@ </div> <div class="bubble-chart-settings"> + <div class="color-by"> + <label for="group-by-setting">Einfärben nach:</label> + + <select id="color-by-setting" name="color-by-setting"> + <option value="default" selected>---</option> + <option value="team">Team</option> + <option value="nation">Nation</option> + <option value="pos">Position</option> + <option value="league">Liga</option> + </select> + </div> <div class="group-by"> <label for="group-by-setting">Gruppieren nach:</label> diff --git a/src/charts/bubbleChart.ts b/src/charts/bubbleChart.ts index e599d0ad4de75b30d695e44fc65bdc3dc6ce0205..5c31a4049f0166dcf144f2c9b470c73ffc9d247b 100644 --- a/src/charts/bubbleChart.ts +++ b/src/charts/bubbleChart.ts @@ -99,6 +99,7 @@ export default class BubbleChart extends SearchableChart { let vis: BubbleChart = this; vis.updatePackRoot() + vis.updateColorScale() const node = vis.chart .selectAll("g") @@ -187,7 +188,7 @@ export default class BubbleChart extends SearchableChart { private getFillForNode(node: HierarchyNode<any>) { if (node.children) return "transparent" if (!this.colorScale) return 'var(--primary)' - return this.colorScale(this.config.colorAccessor(node) as NumberValue) + return this.colorScale(this.config.colorAccessor(node.data) as NumberValue) } search(input: string): void { @@ -214,7 +215,10 @@ export default class BubbleChart extends SearchableChart { ) as [number, number] ) } else { - this.colorScale = d3.scaleOrdinal(d3.schemeCategory10) + this.colorScale = d3.scaleOrdinal( + new Set(this.data.map((d: any) => this.config.colorAccessor(d))), + d3.schemeCategory10, + ) } } @@ -244,7 +248,7 @@ export default class BubbleChart extends SearchableChart { d3.select(`circle[data-player="${this.highlightedNode.data.player}"]`) .transition() .duration(700) - .attr('fill', 'var(--primary)') + .attr('fill', (d: any) => this.getFillForNode(d)) } d3.select(`circle[data-player="${dataPoint.data.player}"]`) .transition() diff --git a/src/main.ts b/src/main.ts index ed758ad906f9f134cb82602ac9c21b68ec19b0ff..4495694d9010df4c02c696c834e19dc03cf25f7e 100644 --- a/src/main.ts +++ b/src/main.ts @@ -3,6 +3,7 @@ import {dsv} from "d3-fetch"; import BubbleChart, {BubbleChartConfigParam} from "@/charts/bubbleChart.ts"; import Search from "@/search.ts"; import {countries} from "@/countries.ts"; +import {Player} from "@/player.ts"; // const radarChartWrapper = document.querySelector('#radar-chart-wrapper') as HTMLDivElement; const bubbleChartWrapper = document.querySelector('#bubble-chart-wrapper') as HTMLDivElement; @@ -28,11 +29,18 @@ groupBySetting.oninput = (event) => { } } +const colorBySetting = document.querySelector('#color-by-setting') as HTMLInputElement +colorBySetting.oninput = (event) => { + if (bubbleChart) { + bubbleChart.updateVisConfig({colorAccessor: (d: any) => d[event.target?.value]} as BubbleChartConfigParam) + } +} + dsv(';', 'data/output.csv').then(data => { const parsedData = data.map((d: any) => ({ - ...d, - nation: countries.find(c => c.code === d.nation)?.name ?? d.nation, - }) + ...d, + nation: countries.find(c => c.code === d.nation)?.name ?? d.nation, + } as Player) ) bubbleChart = new BubbleChart(parsedData, { @@ -45,7 +53,6 @@ dsv(';', 'data/output.csv').then(data => { if (sliderBlocked) return zoomSlider.value = event.transform.k.toString() }, - groupAccessor: (d: any) => d['nation'], }) bubbleChart.renderVis() diff --git a/src/player.ts b/src/player.ts new file mode 100644 index 0000000000000000000000000000000000000000..5eb7b49863e32c77bcfa3c666949ca9f82371ed7 --- /dev/null +++ b/src/player.ts @@ -0,0 +1,40 @@ +export type Player = { + league: string; + season: string; + team: string; + player: string; + nation: string; + pos: string; + age: string; + born: string; + playingTime: number; + performance: number; + expected_0: number; + progression: number; + per90Minutes: number; + standard: number; + expected_1: number; + total: number; + short: number; + medium: number; + long: number; + ast: number; + xAG: number; + expected: number; + KP: number; + '1/3': number; + PPA: number; + CrsPA: number; + PrgP: number; + SCA: number; + GCA: number; + tackles: number; + blocks: number; + Int: number; + TklInt: number; + Clr: number; + Err: number; + touches: number; + penaltyKicks: number; + expected_2: number; +} \ No newline at end of file