-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #836 from explorable-viz/example-fluid
Bubble Chart First Impl
- Loading branch information
Showing
7 changed files
with
184 additions
and
8 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,4 @@ | ||
[ | ||
{country: "Germany", cities: 1000, farms: 150, industry:500 , energy: 450, popMil: 81}, | ||
{country: "Germany", cities: 900, farms: 150, industry:500 , energy: 450, popMil: 81}, | ||
{country: "UK", cities: 800, farms: 200, industry: 400, energy: 700, popMil: 67} | ||
] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,5 @@ | ||
let ratioFor country = | ||
sum [row.popMil / row.farms | row <- data, row.country == country]; | ||
let countryData = [{x: country.country, y: ratioFor country.country} | country <- data] | ||
in BarChart { | ||
let countryData = [{x: country.cities, y: country.farms, z: country.popMil} | country <- data] | ||
in BubbleChart { | ||
caption: "Ratio of farmland consumption to population in millions", | ||
data: countryData | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,120 @@ | ||
"use strict" | ||
|
||
import * as d3 from "d3" | ||
import * as d3tip from "d3-tip" | ||
|
||
// This prelude currently duplicated across all FFI implementations. | ||
function curry2 (f) { | ||
return x1 => x2 => f(x1, x2) | ||
} | ||
|
||
function curry3 (f) { | ||
return x1 => x2 => x3 => f(x1, x2, x3) | ||
} | ||
|
||
function curry4 (f) { | ||
return x1 => x2 => x3 => x4 => f(x1, x2, x3, x4) | ||
} | ||
|
||
// https://stackoverflow.com/questions/5560248 | ||
function colorShade(col, amt) { | ||
col = col.replace(/^#/, '') | ||
if (col.length === 3) col = col[0] + col[0] + col[1] + col[1] + col[2] + col[2] | ||
|
||
let [r, g, b] = col.match(/.{2}/g); | ||
([r, g, b] = [parseInt(r, 16) + amt, parseInt(g, 16) + amt, parseInt(b, 16) + amt]) | ||
|
||
r = Math.max(Math.min(255, r), 0).toString(16) | ||
g = Math.max(Math.min(255, g), 0).toString(16) | ||
b = Math.max(Math.min(255, b), 0).toString(16) | ||
|
||
const rr = (r.length < 2 ? '0' : '') + r | ||
const gg = (g.length < 2 ? '0' : '') + g | ||
const bb = (b.length < 2 ? '0' : '') + b | ||
|
||
return `#${rr}${gg}${bb}` | ||
} | ||
|
||
function drawBubbleChart_ ( | ||
id, | ||
childIndex, | ||
{ | ||
caption, // String | ||
data, // Array BubbleRecord | ||
}, | ||
listener | ||
) { | ||
return () => { | ||
const childId = id + '-' + childIndex | ||
const margin = {top: 15, right: 0, bottom: 40, left: 30}, | ||
width = 200 - margin.left - margin.right, | ||
height = 185 - margin.top - margin.bottom | ||
const div = d3.select('#' + id) | ||
|
||
div.selectAll('#' + childId).remove() | ||
|
||
const svg = div | ||
.append('svg') | ||
.attr('width', width + margin.left + margin.right) | ||
.attr('height', height + margin.top + margin.bottom) | ||
.attr('id', childId) | ||
.append('g') | ||
.attr('transform', `translate(${margin.left}, ${margin.top})`) | ||
|
||
const tip = d3tip.default() | ||
.attr('class', 'd3-tip') | ||
.offset([0, 0]) | ||
.html((_, d) => d.y_1) | ||
|
||
svg.call(tip) | ||
|
||
const x_max = Math.ceil(Math.max(...data.map(d => d.x._1 + d.z._1))) | ||
const y_max = Math.ceil(Math.max(...data.map(d => d.y._1 + d.z._1))) | ||
const z_max = Math.ceil(Math.max(...data.map(d => d.z._1))) | ||
const x = d3.scaleLinear() | ||
.domain([0,x_max]) | ||
.range([0, width]) | ||
svg.append('g') | ||
.attr('transform', "translate(0," + height + ")") | ||
.call(d3.axisBottom(x)) | ||
.selectAll('text') | ||
.style('text-anchor', 'middle') | ||
|
||
const y = d3.scaleLinear() | ||
.domain([0, y_max]) | ||
.range([height,0]) | ||
svg.append('g') | ||
.call(d3.axisLeft(y)) | ||
|
||
const z = d3.scaleLinear() | ||
.domain([1, z_max]) | ||
.range([1, 30]) | ||
|
||
const dotFill = '#dcdcdc' | ||
svg.append('g') | ||
.selectAll('dot') | ||
.data([...data.entries()]) | ||
.enter() | ||
.append('circle') | ||
.attr('cx', ([, d]) => x(d.x._1)) | ||
.attr('cy', ([, d]) => y(d.y._1)) | ||
.attr('r', ([, d]) => z(d.z._1)) | ||
.attr('stroke', 'black') | ||
.style('fill', ([, d]) => d.y._2 ? colorShade(dotFill, -40) : dotFill) | ||
.style('class', ([, d]) => d.y._2 ? 'dot-selected' : 'dot-unselected') | ||
.on('mousedown', (e, d) => { | ||
console.log(`mousedown ${d[0]}`) | ||
listener(e) | ||
}) | ||
|
||
svg.append('text') | ||
.text(caption._1) | ||
.attr('x', width / 2) | ||
.attr('y', height + 35) | ||
.attr('class', 'title-text') | ||
.attr('dominant-baseline', 'bottom') | ||
.attr('text-anchor', 'middle') | ||
} | ||
} | ||
|
||
export var drawBubbleChart = curry4(drawBubbleChart_) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
module App.BubbleChart where | ||
|
||
import Prelude hiding (absurd) | ||
|
||
import App.Util (class Reflect, Renderer, Handler, from, get_intOrNumber, record) | ||
import App.Util.Select (constrArg, field, listElement) | ||
import Data.Maybe (Maybe) | ||
import DataType (cBubbleChart, f_caption, f_data, f_x, f_y, f_z) | ||
import Dict (Dict, get) | ||
import Lattice (𝔹, neg) | ||
import Primitive (string) | ||
import Test.Util (Selector) | ||
import Unsafe.Coerce (unsafeCoerce) | ||
import Util (type (×), definitely', (!)) | ||
import Val (Val) | ||
import Web.Event.Event (target) | ||
import Web.Event.Internal.Types (EventTarget) | ||
|
||
newtype BubbleChart = BubbleChart { caption :: String × 𝔹, data :: Array BubbleChartRecord } | ||
newtype BubbleChartRecord = BubbleChartRecord { x :: Number × 𝔹, y :: Number × 𝔹, z :: Number × 𝔹 } | ||
|
||
foreign import drawBubbleChart :: Renderer BubbleChart | ||
|
||
instance Reflect (Dict (Val 𝔹)) BubbleChartRecord where | ||
from r = BubbleChartRecord | ||
{ x: get_intOrNumber f_x r | ||
, y: get_intOrNumber f_y r | ||
, z: get_intOrNumber f_z r | ||
} | ||
|
||
instance Reflect (Dict (Val 𝔹)) BubbleChart where | ||
from r = BubbleChart | ||
{ caption: string.unpack (get f_caption r) | ||
, data: record from <$> from (get f_data r) | ||
} | ||
|
||
bubbleChartHandler :: Handler | ||
bubbleChartHandler ev = toggleDot $ unsafeDotIndex $ target ev | ||
where | ||
toggleDot :: Int -> Selector Val | ||
toggleDot i = | ||
constrArg cBubbleChart 0 | ||
$ field f_data | ||
$ listElement i | ||
$ neg | ||
|
||
unsafeDotIndex :: Maybe EventTarget -> Int | ||
unsafeDotIndex tgt_opt = | ||
let | ||
tgt = definitely' $ tgt_opt | ||
in | ||
(unsafeCoerce tgt).__data__ ! 0 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters