Declarative web data visualization using ClojureScript

Preview:

Citation preview

Agenda

Friday, July 20, 12

Agenda

?1WhatVisualization

is

Friday, July 20, 12

Agenda

2doin’ itInternetson the

Friday, July 20, 12

Agenda

3Examplean

Friday, July 20, 12

Agenda

4Why

(not)

ClojureFriday, July 20, 12

Agenda

0 Talk

Anti-

Techideas

Friday, July 20, 12

Friday, July 20, 12

?1WhatVisualization

is

Friday, July 20, 12

Bioinformatics

Friday, July 20, 12

Wind energy

Friday, July 20, 12

Doc & patient,meet

DataFriday, July 20, 12

Friday, July 20, 12

Friday, July 20, 12

(didn’t make this, just ♥ it)

Friday, July 20, 12

?Whathave in

common do these things

Friday, July 20, 12

Data

VisualFriday, July 20, 12

0 25 50 75 100

Data: [17, 26, 53, 96]

Friday, July 20, 12

0

5

10

15

20

0 3 6 9 12 15

Data: [[1, 2] [3, 4] [5, 5] [6, 8] [8, 13] [9, 16] [11, 18]]

Friday, July 20, 12

Agenda

2doin’ itInternetson the

Friday, July 20, 12

D3: Data Driven Documents (2011)Mike Bostock Vadim OgievetskyJeffrey Heer

+

Friday, July 20, 12

D3 (JavaScript)

DOM

d3.select("body").selectAll("div")  .data([17, 26, 53, 96])  .enter().append("div")  .style("width", function(d){d+"px";});

Friday, July 20, 12

Awesome Declarative

Familiar representationHTML, CSS, SVG; dev toolsNo reinvented wheels

Easy to think, exploreOptimizable

Friday, July 20, 12

Awesomer Clojure(Script)

Rich data structuresNamespacesDeliberate state/mutation

Friday, July 20, 12

ClojurePhilosophy

Friday, July 20, 12

Treat yourlike Datadata

It is better to have 100 functions operate on one data structure than 10 functions on 10 data structures.

Alan Perlis

Friday, July 20, 12

D3 (JavaScript)d3.select("body").selectAll("div")  .data([17, 26, 53, 96])  .enter().append("div")  .style("width", function(d){d+"px";});

Friday, July 20, 12

D3 (JavaScript)d3.select("body").selectAll("div")  .data([17, 26, 53, 96])  .enter().append("div")  .style("width", function(d){d+"px";});

Friday, July 20, 12

D3 (JavaScript)d3.select("body").selectAll("div")  .data([17, 26, 53, 96])  .enter().append("div")  .style("width", function(d){d+"px";});

Can we do better?Friday, July 20, 12

Agenda

3Examplean

Friday, July 20, 12

Friday, July 20, 12

Friday, July 20, 12

[{:flight-no 2, :price 106, :carrier "Alaska" :depart 16.91, :arrive 21.42}

{:flight-no 1, :price 190, :carrier "United" :depart 6.20, :arrive 10.87}

{:flight-no 5, :price 213, :carrier "United" :depart 4.73, :arrive 9.48} ... ]

Start with your data

Friday, July 20, 12

Friday, July 20, 12

Friday, July 20, 12

(unify! "#chart" flight-data (fn [{:keys [price carrier depart arrive]} idx] [:div.row [:button.price (str "$" price)] [:div.flight {:style {:left (time-scale depart) :width (time-scale (- arrive depart))} :carrier carrier} [:span carrier]]]))

Friday, July 20, 12

(unify! "#chart" flight-data (fn [{:keys [price carrier depart arrive]} idx] [:div.row [:button.price (str "$" price)] [:div.flight {:style {:left (time-scale depart) :width (time-scale (- arrive depart))} :carrier carrier} [:span carrier]]]))

Friday, July 20, 12

(unify! "#chart" flight-data (fn [{:keys [price carrier depart arrive]} idx] [:div.row [:button.price (str "$" price)] [:div.flight {:style {:left (time-scale depart) :width (time-scale (- arrive depart))} :carrier carrier} [:span carrier]]]))

Friday, July 20, 12

(unify! "#chart" flight-data (fn [{:keys [price carrier depart arrive]} idx] [:div.row [:button.price (str "$" price)] [:div.flight {:style {:left (time-scale depart) :width (time-scale (- arrive depart))} :carrier carrier} [:span carrier]]]))

Friday, July 20, 12

(unify! "#chart" flight-data (fn [{:keys [price carrier depart arrive]} idx] [:div.row [:button.price (str "$" price)] [:div.flight {:style {:left (time-scale depart) :width (time-scale (- arrive depart))} :carrier carrier} [:span carrier]]]))

(let [time-scale (scale/linear :domain [0 24] :range :percent)]

(time-scale 0) ;=> “0%” (time-scale 12) ;=> “50%” (time-scale 24) ;=> “100%”)

Friday, July 20, 12

(unify! "#chart" flight-data (fn [{:keys [price carrier depart arrive]} idx] [:div.row [:button.price (str "$" price)] [:div.flight {:style {:left (time-scale depart) :width (time-scale (- arrive depart))} :carrier carrier} [:span carrier]]]))

Friday, July 20, 12

(unify! "#chart" flight-data (fn [{:keys [price carrier depart arrive]} idx] [:div.row [:button.price (str "$" price)] [:div.flight {:style {:left (time-scale depart) :width (time-scale (- arrive depart))} :carrier carrier} [:span carrier]]]))

Friday, July 20, 12

(unify! "#chart" flight-data (fn [{:keys [price carrier depart arrive]} idx] [:div.row [:button.price (str "$" price)] [:div.flight {:style {:left (time-scale depart) :width (time-scale (- arrive depart))} :carrier carrier} [:span carrier]]]))

Friday, July 20, 12

(unify! "#chart" flight-data (fn [{:keys [price carrier depart arrive]} idx] [:div.row [:button.price (str "$" price)] [:div.flight {:style {:left (time-scale depart) :width (time-scale (- arrive depart))} :carrier carrier} [:span carrier]]]))

Friday, July 20, 12

(unify! "#chart" flight-data (fn [{:keys [price carrier depart arrive]}] [:div.row [:button.price (str "$" price)] [:div.flight {:style {:left (time-scale depart) :width (time-scale (- arrive depart))} :carrier carrier} [:span carrier]]]))

Friday, July 20, 12

(map flight-data (fn [{:keys [price carrier depart arrive]}] [:div.row [:button.price (str "$" price)] [:div.flight {:style {:left (time-scale depart) :width (time-scale (- arrive depart))} :carrier carrier} [:span carrier]]]))

Friday, July 20, 12

(map flight-data (fn [{:keys [price carrier depart arrive]}] [:div.row [:button.price (str "$" price)] [:div.flight {:style {:left (time-scale depart) :width (time-scale (- arrive depart))} :carrier carrier} [:span carrier]]]))

Friday, July 20, 12

C2http://keminglabs.com/c2http://github.com/lynaghk/c2

Friday, July 20, 12

Advantagesof the

dataapproach

Friday, July 20, 12

Declarative

(fn [{:keys [price carrier depart arrive]}] [:div.row [:button.price (str "$" price)] [:div.flight {:style {:left (time-scale depart) :width (time-scale (- arrive depart))} :carrier carrier} [:span carrier]]])

Friday, July 20, 12

Declarative

(fn [{:keys [price carrier depart arrive]}] [:div.row [:button.price (str "$" price)] [:div.flight {:style (flight-style depart arrive)

:carrier carrier} [:span carrier]]])

Friday, July 20, 12

Declarative

(fn [{:keys [price carrier depart arrive]}] [:div.row [:button.price (str "$" price)] [:div.flight {:style (merge {:background-color "blue"} (flight-style depart arrive)) :carrier carrier} [:span carrier]]])

Friday, July 20, 12

Decoupled2) rendering1) construction

Friday, July 20, 12

Agenda

4Why

(not)

ClojureFriday, July 20, 12

Why Clojure

SaneOpinionated

&Friday, July 20, 12

Why Clojure

Runtimes:JVMCLR

JavaScript

Lua CFriday, July 20, 12

NotClojure

Friday, July 20, 12

Why not Clojure

WTFis Clojure?

Friday, July 20, 12

Why not Clojure

Clojure is the #23 most popular language on GitHub

Friday, July 20, 12

Why not Clojure

Assembly is the #18 most popular language on GitHub

Friday, July 20, 12

Why not Clojure

900+ forks

Friday, July 20, 12

Friday, July 20, 12

Keming Labs

Kevin Lynagh@lynaghk

Friday, July 20, 12

Recommended