Responsive Heatmap
by ramnathv
HTML
<script src="//d3js.org/d3.v3.min.js"></script>
<script src="//rawgit.com/kristw/75b61f9beeab9b530612/raw/389e984e4041117a9185cf6edad9f6b85a38097a/d3kit.min.js"></script>
<script src="//rawgit.com/gka/d3-jetpack/master/d3-jetpack.js"></script>
<script src="//rawgit.com/Caged/d3-tip/master/index.js"></script>
<link rel="stylesheet" href="//rawgit.com/Caged/d3-tip/master/examples/example-styles.css">
<script src="//rawgit.com/ramnathv/a5a3199538f86817ec1b/raw/f6627fc544e65d8e6186ba87556f743caa3f2730/visutils.js"></script>
<script src="//rawgit.com/ramnathv/1838a632793dc787ca68/raw/1f1bd60ecd673e983320eb4777c1f333a4934594/testdata.js"></script>
<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css">
<script src="//maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>
<!-- Nav tabs -->
<div class="btn-group" role="group" aria-label="...">
<a type="button" class="btn btn-default" href='#chart' id='showChart' data-toggle='tab'>Left</a>
<a type="button" href='#messages' class="btn btn-default data" data-set='iris' data-toggle='tab'>Iris</a>
<a type="button" href='#messages2' class="btn btn-default data" data-set='iris2' data-toggle='tab'>Iris</a>
<a type="button" href='#messages4' class="btn btn-default data" data-set='iris' data-toggle='tab'>Iris</a>
</div>
<!-- Tab panes -->
<div class="tab-content">
<div role="tabpanel" class="tab-pane fade heatmap" id="chart"></div>
<div role="tabpanel" class="active tab-pane fade heatmap" id="messages"></div>
<div role="tabpanel" class="tab-pane" id="settings">...</div>
</div>
</div>
CSS
body{
font-family: "Helvetica";
font-size: 13px;
padding-top: 40px;
}
.heatmap .y-axis-layer path,
.heatmap .y-axis-layer line{
fill: none;
}
.heatmap .x-axis-layer path,
.heatmap .x-axis-layer line{
fill: none;
}
.heatmap .y-axis-layer text,
.heatmap .x-axis-layer text{
font-size: 11px;
fill-opacity: 0.6;
}
/*
.heatmap .cell {
stroke: #ddd;
}
*/
.heatmap .cell .label{
stroke: black;
font-size: 10px;
font-weight: normal;
}
.d3-tip{
font-weight: normal;
line-height: 1.4em;
pointer-events: none !important;
}
CoffeeScript
heatMapConstructor = (skeleton) ->
layers = skeleton.getLayerOrganizer()
S =
x: d3.scale.ordinal()
y: d3.scale.ordinal()
c: d3.scale.linear()
A =
x: (d) -> d.x
y: (d) -> d.y
c: (d) -> d.c
layers.create(['cells', 'y-axis', 'x-axis', 'accuracy'])
visualize = ->
data = skeleton.data()
opts = skeleton.options()
x = Math.min(
skeleton.getInnerWidth(), skeleton.getInnerHeight()
)
W_ = x; H_ = x;
S.x.rangeRoundBands([0, W_]).domain data.map(A.x)
S.y.rangeRoundBands([0, H_]).domain data.map(A.y)
#S.c.range(['crimson', 'white', 'purple'])
# .domain [-1, 0, 1]
S.c.range(['white', 'rgb(0, 158, 115)'])
.domain([0, 1])
S.c2 = S.c.copy()
.range(['white', 'darkred'])
cells = layers.get('cells').selectAll('.cell')
.data(data)
cells.enter().append('rect.cell')
cells.attr
x: (d) -> S.x A.x(d)
y: (d) -> S.y A.y(d)
width: S.x.rangeBand()
height: S.y.rangeBand()
stroke: (d) ->
'#ddd'
fill: (d) ->
if d.x is "Sum" or d.y is "Sum"
'#fff'
else if (d.x is d.y)
S.c A.c(d)
else
S.c2 A.c(d)
cells.exit().remove()
tooltipFn = (d) ->
if (d.x is 'Sum' or d.y is 'Sum')
return "Count of #{d.y}: #{d.Freq}"
if (d.x is d.y)
prefix = 'correctly'
else
prefix = 'incorrectly'
"""
#{d3.format('%.2f')(d.c)} of <b>#{d.y}</b> are <br/> #{prefix} classified as <b>#{d.x}</b>
"""
cells
.filter((d) -> d.y != 'Sum')
.call attachTooltip, {html: tooltipFn}
labels = layers.get('cells').selectAll('.hlabel')
.data(data)
labels.enter().append('text.hlabel')
labels.attr
x: (d) -> S.x(A.x(d)) + S.x.rangeBand()/2
y: (d) -> S.y(A.y(d)) + S.y.rangeBand()/2
"text-anchor": "middle"
"alignment-baseline": "middle"
"pointer-events": "none"
"fill-opacity": 0.8
...