forked from palantir/plottable
-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.html
346 lines (305 loc) · 16.1 KB
/
index.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
<!DOCTYPE html>
<html>
<head>
<meta charset='utf-8' />
<meta http-equiv="X-UA-Compatible" content="chrome=1" />
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
<meta name="description" content="Plottable.js: a library for easily creating powerful, flexible, interactive charts. Built on D3.js." />
<title>Plottable.js</title>
<!-- bootstrap -->
<link rel="stylesheet" href="examples/landing/bootstrap.min.css">
<link rel="stylesheet" href="examples/landing/prettify.css">
<!-- plottable and dependencies -->
<script src="bower_components/d3/d3.min.js"></script>
<link href="plottable.css" type="text/css" rel="stylesheet" />
<script src="plottable.js"></script>
<script src="examples/main-page/commit-chart-shared.js"></script>
<script src="examples/main-page/commit-chart.js"></script>
<script src="examples/main-page/commit-dashboard-data-manager.js"></script>
<script src="examples/main-page/commit-dashboard.js"></script>
<script src="examples/landing/customProjectors.js"></script>
<script src="examples/landing/mobilecheck.js"></script>
<script src="examples/landing/basicChart.js"></script>
<script src="examples/landing/plugins.js"></script>
<script src="examples/data/xyData.js"></script>
<script src="examples/landing/layout.js"></script>
<script src="examples/landing/run_prettify.js"></script>
<!-- glue -->
<script>
function sizeSVG(selection) {
var svg = d3.select(selection);
var width = Plottable._Util.DOM.getSVGPixelWidth(svg);
svg.attr("width", width);
var height = Math.min(width*.6, 500);
svg.attr("height", height);
return svg;
}
window.onload = function() {
d3.json("examples/data/gitstats2.json", function(data) {
data.forEach(function(d) {
d.date = new Date(d.date);
d.name = d.name === "ashwinraman9" ? "aramaswamy" : d.name;
});
var dataManager = makeCommitDataManager(data);
var interactiveSVG = d3.select("#interactive-demo");
sizeSVG("#layout");
sizeSVG("#basicChart");
sizeSVG("#customProjectors");
sizeSVG("#plugins");
sizeSVG("#interactive-demo");
commitDashboard(dataManager, interactiveSVG);
makeBasicChart();
customProjectorChart(data);
layoutChart(data);
pluginsChart(data);
});
d3.json("bower.json", function(json) {
var v = json.version;
var button = d3.select("h2 a .plottable-dl");
button.text("plottable.zip - v" + v);
})
}
</script>
<!-- style -->
<style type="text/css">
body > .container {
padding-top: 70px;
}
.container {
}
.svg-container {
border: 2px solid #CCC;
}
.plottable circle {
opacity: 0.8;
}
#layout .bounding-box {
stroke: #ccc;
}
h1 {
text-align: center;
font-size: 56px;
}
h2 {
text-align: center;
font-size: 40px;
}
body {
background-color: #f8f8f8;
}
.internal {
background-color: #fff;
border: 25px solid #fff;
}
.button.primary {
color: #fff;
/*text-shadow: 0 -1px 0;*/
background-color: #60b044;
background-image: linear-gradient(#8add6d, #60b044);
background-repeat: repeat-x;
border-color: #5ca941;
position: relative;
display: inline-block;
padding: 7px 12px;
font-size: 18px;
font-weight: bold;
border-radius: 3px;
border: 1px solid #d5d5d5;
font: Helvetica;
}
</style>
<link rel="stylesheet" type="text/css" href="examples/landing/desktop.css" />
<link rel="stylesheet" type="text/css" media="only screen and (max-device-width: 480px)" href="examples/landing/mobile.css" />
</head>
<body>
<!-- fork me on GitHub! -->
<a href="https://github.com/palantir/plottable"><img style="z-index: 100000; position: fixed; top: 0; right: 0; border: 0;" src="https://camo.githubusercontent.com/38ef81f8aca64bb9a64448d0d70f1308ef5341ab/68747470733a2f2f73332e616d617a6f6e6177732e636f6d2f6769746875622f726962626f6e732f666f726b6d655f72696768745f6461726b626c75655f3132313632312e706e67" alt="Fork me on GitHub" data-canonical-src="https://s3.amazonaws.com/github/ribbons/forkme_right_darkblue_121621.png"></a>
<div class="container">
<div class="internal">
<h1>Plottable.js</h1>
<h2><a href="plottable.zip" rel="nofollow" class="button primary">
<span class="octicon octicon-arrow-down"></span>
<span class="tooltipped tooltipped-s plottable-dl" aria-label="68.8 KB">plottable.zip - vx.xx.x</span>
</a></h2>
<h2>What is Plottable?</h2>
<p>
Plottable.js is a library for data visualization and charting, under development by Palantir Technologies.
Plottable is built on D3 and provides higher-level components like a CirclePlot, Legend, and TitleLabel. These components are
bundled with a layout engine that can position them in complex arrangements and size them. Plottable is flexible, pluggable, performant, and interactive.
</p>
<p>
Here's an example of a complex dashboard, written in Plottable, that
shows Plottable's git commit history, including breakdown by contributor and directory.
</p>
<div class="svg-container"><svg id="interactive-demo" width="100%"></svg></div>
<br><br><h2>Easy</h2>
<p>
Because Plottable includes high level components, throwing together simple charts is easy.
Here's an example of a basic Plottable chart, and the 20 lines of associated code.
</p>
<div class="svg-container"><svg id="basicChart" width="100%"></svg></div>
<br>
<pre class="prettyprint"><code>function makeBasicChart() {
// These scales are Plottable wrappers for a d3.scale object.
// Like D3 scales, they manage a mapping from data to visual properties; pixel positions in this case
// Unlike D3 scales, they automatically set their domain and range, and have event handling to update dependent components on changes
var xScale = new Plottable.Scale.Linear();
var yScale = new Plottable.Scale.Linear();
// The Axes and LinePlot are all Components, meaning they take up visual space and are placed by the layout engine
var xAxis = new Plottable.Axis.XAxis(xScale, "bottom", d3.format("d"));
var yAxis = new Plottable.Axis.YAxis(yScale, "left");
// In this case, the xyData is organized to be an array of {x, y} points. The Renderer automatically accesses these attributes.
var renderer = new Plottable.Plot.Line(xyData, xScale, yScale);
// Now we'll make a Table to organize the layout of the components. The first row will have a yAxis and renderer; the second will
// only have the xAxis, and it will be aligned to the column of the renderer.
// The yAxis is fixed-width and the xAxis is fixed-height, so the renderer will naturally expand to take up all free space
var chart = new Plottable.Component.Table([
[yAxis, renderer],
[null, xAxis ]
]);
chart.renderTo("#basicChart");
}
</code></pre>
<br><br><h2>Powerful</h2>
<p>
We've also designed Plottable to be highly flexible and customizable. Plottable renderers are agonstic to the way data is structured,
and support setting arbitrary SVG attributes based on functions and scales they are given. In the example below, we have a CirclePlot that
uses an accessor function to compute some derived attributes from the data on-the-fly, and uses that data to set the fill on the circles.
</p>
<div class="svg-container"><svg id="customProjectors" width="100%"></svg></div>
<br>
<pre class="prettyprint"><code>function customProjectorChart(data) {
var xScale = new Plottable.Scale.Linear().domain([-5, 100]);
var yScale = new Plottable.Scale.Log().domain([0.5, 100000]);
var xAxis = new Plottable.Axis.XAxis(xScale, "bottom", d3.format("d"));
var yAxis = new Plottable.Axis.YAxis(yScale, "left");
var renderer = new Plottable.Plot.Scatter(data, xScale, yScale);
// By calling renderer.project(attribute=x, accessor="day_delta", scale=xScale), we tell the renderer to set the "x"
// attribute on data using the given accessor and scale. In general, an accessor is a function that takes in a data
// object and returns a piece of data. String arguments are automagically converted into key functions, as follows:
// project(attr, "day_delta", scale) => project(attr, function(d) { return d.day_delta; }, scale).
// Renderer.project is a core part of the API, and sets up bindings between the data, the scale, and the renderer.
// These bindings handle event propogation, updating, and scale auto-domaining.
renderer.project("x", "day_delta", xScale);
function linesChangedAccessor(d) { return d.additions + d.deletions; }
renderer.project("y", linesChangedAccessor, yScale);
function additionsOverLinesChanged(d) {
if (d.deletions + d.additions === 0) {
return 0.5;
}
return d.additions / (d.deletions + d.additions);
}
// This scale interpolates between red for commits with mostly deletions, and green for commits with mostly additions.
var colorScale = new Plottable.Scale.InterpolatedColor(["#FF0000", "#008B00"]);
renderer.project("fill", additionsOverLinesChanged, colorScale);
var chart = new Plottable.Template.StandardChart()
.xAxis(xAxis).yAxis(yAxis)
.center(renderer)
.xLabel("days since start of project")
.yLabel("Total lines changed by commit")
.titleLabel("Commits colored by additions relative to deletions")
.renderTo("#customProjectors");
}
</code></pre>
<br><br><h2>Flexible</h2>
<p>
Rather than supporting only a small set of predefined chart templates, Plottable has an expressive Table-based layout engine for
constructing arbitrary dashboards. This layout engine handles a lot of the detail work of setting up a chart, like making sure that
axes are aligned properly or computing the height of text to place labels properly. In the example below, we use the layout engine to create
a dashboard with two subplots, a shared x-axis, and y-axes on opposite sides of the plots.
</p>
<p>
In the example below, the component's bounding boxes have been given a stroke, so it's easier to see how the Table is arranged.
</p>
<div class="svg-container"><svg id="layout" width="100%"></svg></div>
<br>
<pre class="prettyprint"><code>function layoutChart(data) {
// The two subplots will share an xScale, but have two seperate yScales for their data
var xScale = new Plottable.Scale.Linear().domain([0, 100]);
var yScaleCommits = new Plottable.Scale.Linear();
var yScaleLOC = new Plottable.Scale.Linear();
var xAxis = new Plottable.Axis.XAxis(xScale, "bottom").showEndTickLabels(true);
var yAxisCommits = new Plottable.Axis.YAxis(yScaleCommits, "left");
var yAxisLOC = new Plottable.Axis.YAxis(yScaleLOC, "right");
// A Dataset is a Plottable object that maintains data and metadata, and updates dependents when it changes
// In the previous example, we implicitly created a Dataset by putting the data directly into the Renderer constructor
var gitDataset = new Plottable.Dataset(data);
var commitsPlot = new Plottable.Plot.Line(gitDataset, xScale, yScaleCommits);
var locPlot = new Plottable.Plot.Area(gitDataset, xScale, yScaleLOC);
commitsPlot.project("x", "day_delta", xScale);
locPlot .project("x", "day_delta", xScale);
commitsPlot.project("y", "commit_number", yScaleCommits);
locPlot .project("y", "lines_of_code", yScaleLOC);
var commitsTitle = new Plottable.Component.TitleLabel("# of Commits Over Time");
var locTitle = new Plottable.Component.TitleLabel("# of Lines Of Code Over Time");
// A Table is the principle abstraction for laying out Plottable Components.
// The rows and columns express alignment constraints between objects, and Tables can be nested inside other
// Tables to allow for complex arrangements.
// In this case, we just put the axes into the first and third columns, with everything else in the second column.
// YAxes are fixed-width, but the Renderers are variable-width, so they automatically expand to fill all space
// left over by the Axes.
// If we had multiple columns with variable-width components, we could let Plottable balance the columns between them,
// or set proportional "weights" on each column.
var chart = new Plottable.Component.Table([
[null , commitsTitle , null ],
[yAxisCommits, commitsPlot, null ],
[null , locTitle , null ],
[null , locPlot , yAxisLOC ],
[null , xAxis , null ]
]);
chart.renderTo("#layout");
}
</code></pre>
<br><br><h2>Pluggable</h2>
<p>
Plottable consists of a small core architecture and a large set of lightweight plugins. In the example below, almost everything is
a plugin: the CirclePlot, the Gridlines, the Legend, and the DragBoxInteraction. Adding a new Component or Interaction - say, a DragBox that
can be dragged and repositioned after it is created - would only be 10-20 lines of Typescript code. </p>
<p>
The chart below is interactive - try dragging out a box on it, or double-click to reset.
</p>
<div class="svg-container"><svg id="plugins" width="100%"></svg></div>
<br>
<pre class="prettyprint"><code>function pluginsChart(gitData) {
var xScale = new Plottable.Scale.Linear().domain([-0.03, 1.03]);
var yScale = new Plottable.Scale.Log().domain([0.9, 100000]);
var colorScale = new Plottable.Scale.Color("category10");
// The Axes and LinePlot are all Components,
// meaning they take up visual space and are placed by the layout engine
var xAxis = new Plottable.Axis.XAxis(xScale, "bottom", d3.format("%"));
var yAxis = new Plottable.Axis.YAxis(yScale, "left");
var linesChanged = function(d) { return d.additions + d.deletions; };
var percentAdditions = function(d) {
return (linesChanged(d) === 0) ? 0.5 : d.additions / linesChanged(d);
}
var renderer = new Plottable.Plot.Scatter(gitData, xScale, yScale)
.project("x", percentAdditions, xScale)
.project("y", linesChanged, yScale)
.project("fill", "name", colorScale)
var gridlines = new Plottable.Component.Gridlines(xScale, yScale);
var legend = new Plottable.Component.Legend(colorScale).xOffset(-80).minimumWidth(200);
var center = renderer.merge(gridlines).merge(legend);
var dragBox = new Plottable.Interaction.XYDragBox(center).registerWithComponent();
Plottable.setupDragBoxZoom(dragBox, xScale, yScale);
// Now we'll make a Table to organize the layout of the components. The first row will have a yAxis and renderer; the second will
// only have the xAxis, and it will be aligned to the column of the renderer.
// The yAxis is fixed-width and the xAxis is fixed-height, so the renderer will naturally expand to take up all free space
new Plottable.Template.StandardChart().xAxis(xAxis).yAxis(yAxis).center(center)
.xLabel("% of Lines Changed that were Additions")
.yLabel("# of Lines Changed")
.titleLabel("Commits by Lines Changed and % Additions")
.renderTo("#plugins");
}
</code></pre>
<!-- TODO sections -->
<!--
<div class="page-header"><h1>Plot</h1></div>
<div class="page-header"><h1>Layout</h1></div>
<div class="page-header"><h1>Interact<h1></div>
<div class="page-header"><h1>Synced</h1></div>
-->
<!-- TODO built by palantir -->
</div>
</div>
</body>
</html>