Commit 752c1f5a6ed9d9528e4ed1d1a74a16d5976f7f19
1 parent
42187739
updated d3-scatterplot-matrix
Showing
8 changed files
with
571 additions
and
3 deletions
bower.json
@@ -20,7 +20,7 @@ | @@ -20,7 +20,7 @@ | ||
20 | "iron-icon": "PolymerElements/iron-icon#~1.0.7", | 20 | "iron-icon": "PolymerElements/iron-icon#~1.0.7", |
21 | "iron-icons": "PolymerElements/iron-icons#~1.1.2", | 21 | "iron-icons": "PolymerElements/iron-icons#~1.1.2", |
22 | "paper-toast": "PolymerElements/paper-toast#~1.2.1", | 22 | "paper-toast": "PolymerElements/paper-toast#~1.2.1", |
23 | - "d3-scatterplot-matrix": "^0.1.0", | ||
24 | - "d3-scatterplot": "^1.1.0" | 23 | + "d3-scatterplot-matrix": "latest", |
24 | + "d3-scatterplot": "latest" | ||
25 | } | 25 | } |
26 | } | 26 | } |
bower_components/d3-scatterplot-matrix/LICENSE
0 → 100644
1 | +The MIT License (MIT) | ||
2 | + | ||
3 | +Copyright (c) 2016 Michał | ||
4 | + | ||
5 | +Permission is hereby granted, free of charge, to any person obtaining a copy | ||
6 | +of this software and associated documentation files (the "Software"), to deal | ||
7 | +in the Software without restriction, including without limitation the rights | ||
8 | +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
9 | +copies of the Software, and to permit persons to whom the Software is | ||
10 | +furnished to do so, subject to the following conditions: | ||
11 | + | ||
12 | +The above copyright notice and this permission notice shall be included in all | ||
13 | +copies or substantial portions of the Software. | ||
14 | + | ||
15 | +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
16 | +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
17 | +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
18 | +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
19 | +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
20 | +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
21 | +SOFTWARE. |
bower_components/d3-scatterplot-matrix/bower.json
0 → 100644
1 | +{ | ||
2 | + "name": "d3-scatterplot-matrix", | ||
3 | + "homepage": "https://github.com/mwasiluk/d3-scatterplot-matrix", | ||
4 | + "authors": [ | ||
5 | + "Michal Wasiluk" | ||
6 | + ], | ||
7 | + "description": "", | ||
8 | + "main": "", | ||
9 | + "keywords": [ | ||
10 | + "scatterplot", | ||
11 | + "d3", | ||
12 | + "matrix" | ||
13 | + | ||
14 | + ], | ||
15 | + "license": "MIT", | ||
16 | + "ignore": [ | ||
17 | + "**/.*", | ||
18 | + "node_modules", | ||
19 | + "bower_components", | ||
20 | + "test", | ||
21 | + "tests" | ||
22 | + ], | ||
23 | + "dependencies": { | ||
24 | + "d3": "^3.5.17" | ||
25 | + } | ||
26 | +} |
bower_components/d3-scatterplot-matrix/dist/d3-scatterplot-matrix.css
0 → 100644
1 | +svg.mw-d3-scatterplot-matrix { | ||
2 | + background-color: white; | ||
3 | + font-size: 11px; | ||
4 | + height: 100%; } | ||
5 | + svg.mw-d3-scatterplot-matrix .mw-axis { | ||
6 | + shape-rendering: crispEdges; } | ||
7 | + svg.mw-d3-scatterplot-matrix .mw-axis path { | ||
8 | + display: none; } | ||
9 | + svg.mw-d3-scatterplot-matrix .mw-axis line { | ||
10 | + stroke: #ddd; } | ||
11 | + svg.mw-d3-scatterplot-matrix .mw-axis.mw-no-guides line { | ||
12 | + display: none; } | ||
13 | + svg.mw-d3-scatterplot-matrix .mw-frame { | ||
14 | + shape-rendering: crispEdges; | ||
15 | + fill: none; | ||
16 | + stroke: #aaa; } | ||
17 | + svg.mw-d3-scatterplot-matrix .mw-cell text { | ||
18 | + font-weight: bold; | ||
19 | + text-transform: capitalize; } | ||
20 | + svg.mw-d3-scatterplot-matrix circle { | ||
21 | + fill-opacity: .7; } | ||
22 | + svg.mw-d3-scatterplot-matrix circle.hidden { | ||
23 | + fill: #ccc !important; } | ||
24 | + svg.mw-d3-scatterplot-matrix .extent { | ||
25 | + fill: #000; | ||
26 | + fill-opacity: .125; | ||
27 | + stroke: #fff; } | ||
28 | + | ||
29 | +.mw-tooltip { | ||
30 | + position: absolute; | ||
31 | + pointer-events: none; | ||
32 | + font-size: 11px; | ||
33 | + background: #fdfdfd; | ||
34 | + padding: 3px 5px; | ||
35 | + border-radius: 8px; | ||
36 | + box-shadow: 1px 3px 3px #b7b7b7; } |
bower_components/d3-scatterplot-matrix/dist/d3-scatterplot-matrix.js
0 → 100644
1 | +function D3ScatterPlotMatrixUtils() { | ||
2 | +} | ||
3 | + | ||
4 | +// usage example deepExtend({}, objA, objB); => should work similar to $.extend(true, {}, objA, objB); | ||
5 | +D3ScatterPlotMatrixUtils.prototype.deepExtend = function (out) { //TODO consider using jquery / lo-dash / underscore / ECMA6 ; fallbacks? | ||
6 | + | ||
7 | + var utils = this; | ||
8 | + var emptyOut = {}; | ||
9 | + | ||
10 | + | ||
11 | + if (!out && arguments.length > 1 && Array.isArray(arguments[1])) { | ||
12 | + out = []; | ||
13 | + } | ||
14 | + out = out || {}; | ||
15 | + | ||
16 | + for (var i = 1; i < arguments.length; i++) { | ||
17 | + var source = arguments[i]; | ||
18 | + if (!source) | ||
19 | + continue; | ||
20 | + | ||
21 | + for (var key in source) { | ||
22 | + if (!source.hasOwnProperty(key)) { | ||
23 | + continue; | ||
24 | + } | ||
25 | + var isArray = Array.isArray(out[key]); | ||
26 | + var isObject = utils.isObject(out[key]); | ||
27 | + var srcObj = utils.isObject(source[key]); | ||
28 | + | ||
29 | + if (isObject && !isArray && srcObj) { | ||
30 | + utils.deepExtend(out[key], source[key]); | ||
31 | + } else { | ||
32 | + out[key] = source[key]; | ||
33 | + } | ||
34 | + } | ||
35 | + } | ||
36 | + | ||
37 | + return out; | ||
38 | +}; | ||
39 | + | ||
40 | +D3ScatterPlotMatrixUtils.prototype.cross = function (a, b) { | ||
41 | + var c = [], n = a.length, m = b.length, i, j; | ||
42 | + for (i = -1; ++i < n;) for (j = -1; ++j < m;) c.push({x: a[i], i: i, y: b[j], j: j}); | ||
43 | + return c; | ||
44 | +}; | ||
45 | + | ||
46 | +D3ScatterPlotMatrixUtils.prototype.inferTraits = function (data, categoryKey, includeCategory) { | ||
47 | + var res = []; | ||
48 | + if (data.length) { | ||
49 | + var d = data[0]; | ||
50 | + if (d instanceof Array) { | ||
51 | + res= d.map(function (v, i) { | ||
52 | + return i; | ||
53 | + }); | ||
54 | + }else if (typeof d === 'object'){ | ||
55 | + | ||
56 | + for (var prop in d) { | ||
57 | + if(!d.hasOwnProperty(prop)) continue; | ||
58 | + | ||
59 | + res.push(prop); | ||
60 | + } | ||
61 | + } | ||
62 | + } | ||
63 | + if(!includeCategory){ | ||
64 | + var index = res.indexOf(categoryKey); | ||
65 | + if (index > -1) { | ||
66 | + res.splice(index, 1); | ||
67 | + } | ||
68 | + } | ||
69 | + return res | ||
70 | +}; | ||
71 | + | ||
72 | + | ||
73 | +D3ScatterPlotMatrixUtils.prototype.isObject = function(a) { | ||
74 | + return a !== null && typeof a === 'object'; | ||
75 | +}; | ||
76 | +D3ScatterPlotMatrixUtils.prototype.isNumber = function(a) { | ||
77 | + return !isNaN(a) && typeof a === 'number'; | ||
78 | +}; | ||
79 | +D3ScatterPlotMatrixUtils.prototype.isFunction = function(a) { | ||
80 | + return typeof a === 'function'; | ||
81 | +}; | ||
82 | + | ||
83 | +D3ScatterPlotMatrixUtils.prototype.selectOrAppend = function (parent, selector, element) { | ||
84 | + var selection = parent.select(selector); | ||
85 | + if(selection.empty()){ | ||
86 | + return parent.append(element || selector); | ||
87 | + } | ||
88 | + return selection; | ||
89 | +}; | ||
90 | +function D3ScatterPlotMatrix(placeholderSelector, data, config) { | ||
91 | + this.utils = new D3ScatterPlotMatrixUtils(); | ||
92 | + this.placeholderSelector = placeholderSelector; | ||
93 | + this.svg = null; | ||
94 | + this.defaultConfig = { | ||
95 | + width: 0, | ||
96 | + size: 200, //cell size | ||
97 | + padding: 20, //cell padding | ||
98 | + brush: true, | ||
99 | + guides: true, | ||
100 | + tooltip: true, | ||
101 | + ticks: null, | ||
102 | + margin: { | ||
103 | + left: 30, | ||
104 | + right: 30, | ||
105 | + top: 30, | ||
106 | + bottom: 30 | ||
107 | + }, | ||
108 | + x: {// X axis config | ||
109 | + orient: "bottom", | ||
110 | + scale: "linear" | ||
111 | + }, | ||
112 | + y: {// Y axis config | ||
113 | + orient: "left", | ||
114 | + scale: "linear" | ||
115 | + }, | ||
116 | + dot: { | ||
117 | + radius: 2, | ||
118 | + color: null, // string or function returning color's value for color scale | ||
119 | + d3ColorCategory: 'category10' | ||
120 | + }, | ||
121 | + traits: { | ||
122 | + labels: [], //optional array of trait labels | ||
123 | + keys: [], //optional array of trait keys | ||
124 | + categoryKey: null, | ||
125 | + includeCategoryInPlot: false, | ||
126 | + value: function (d, traitKey) {// trait value accessor | ||
127 | + return d[traitKey]; | ||
128 | + } | ||
129 | + } | ||
130 | + }; | ||
131 | + | ||
132 | + if (config) { | ||
133 | + this.setConfig(config); | ||
134 | + } | ||
135 | + | ||
136 | + if (data) { | ||
137 | + this.setData(data); | ||
138 | + } | ||
139 | + | ||
140 | + this.init(); | ||
141 | +} | ||
142 | + | ||
143 | +D3ScatterPlotMatrix.prototype.setData = function (data) { | ||
144 | + this.data = data; | ||
145 | + | ||
146 | + | ||
147 | + return this; | ||
148 | +}; | ||
149 | + | ||
150 | +D3ScatterPlotMatrix.prototype.setConfig = function (config) { | ||
151 | + this.config = this.utils.deepExtend({}, this.defaultConfig, config); | ||
152 | + return this; | ||
153 | +}; | ||
154 | +D3ScatterPlotMatrix.prototype.initPlot = function () { | ||
155 | + | ||
156 | + | ||
157 | + var self = this; | ||
158 | + var margin = this.config.margin; | ||
159 | + var conf = this.config; | ||
160 | + this.plot = { | ||
161 | + x: {}, | ||
162 | + y: {}, | ||
163 | + dot: { | ||
164 | + color: null//color scale mapping function | ||
165 | + } | ||
166 | + }; | ||
167 | + | ||
168 | + this.setupTraits(); | ||
169 | + | ||
170 | + this.plot.size = conf.size; | ||
171 | + | ||
172 | + | ||
173 | + var width = conf.width; | ||
174 | + var placeholderNode = d3.select(this.placeholderSelector).node(); | ||
175 | + | ||
176 | + if (!width) { | ||
177 | + var maxWidth = margin.left + margin.right + this.plot.traits.length*this.plot.size; | ||
178 | + width = Math.min(placeholderNode.getBoundingClientRect().width, maxWidth); | ||
179 | + | ||
180 | + } | ||
181 | + var height = width; | ||
182 | + if (!height) { | ||
183 | + height = placeholderNode.getBoundingClientRect().height; | ||
184 | + } | ||
185 | + | ||
186 | + this.plot.width = width - margin.left - margin.right; | ||
187 | + this.plot.height = height - margin.top - margin.bottom; | ||
188 | + | ||
189 | + | ||
190 | + | ||
191 | + | ||
192 | + if(conf.ticks===null){ | ||
193 | + conf.ticks = this.plot.size / 40; | ||
194 | + } | ||
195 | + | ||
196 | + this.setupX(); | ||
197 | + this.setupY(); | ||
198 | + | ||
199 | + if (conf.dot.d3ColorCategory) { | ||
200 | + this.plot.dot.colorCategory = d3.scale[conf.dot.d3ColorCategory](); | ||
201 | + } | ||
202 | + var colorValue = conf.dot.color; | ||
203 | + if (colorValue) { | ||
204 | + this.plot.dot.colorValue = colorValue; | ||
205 | + | ||
206 | + if (typeof colorValue === 'string' || colorValue instanceof String) { | ||
207 | + this.plot.dot.color = colorValue; | ||
208 | + } else if (this.plot.dot.colorCategory) { | ||
209 | + this.plot.dot.color = function (d) { | ||
210 | + return self.plot.dot.colorCategory(self.plot.dot.colorValue(d)); | ||
211 | + } | ||
212 | + } | ||
213 | + | ||
214 | + | ||
215 | + }else if(conf.traits.categoryKey){ | ||
216 | + this.plot.dot.color = function (d) { | ||
217 | + return self.plot.dot.colorCategory(d[conf.traits.categoryKey]); | ||
218 | + } | ||
219 | + } | ||
220 | + | ||
221 | + | ||
222 | + | ||
223 | + return this; | ||
224 | + | ||
225 | +}; | ||
226 | + | ||
227 | +D3ScatterPlotMatrix.prototype.setupTraits = function () { | ||
228 | + var traitsConf = this.config.traits; | ||
229 | + | ||
230 | + var data = this.data; | ||
231 | + var plot = this.plot; | ||
232 | + plot.domainByTrait = {}; | ||
233 | + plot.traits = traitsConf.keys; | ||
234 | + if(!plot.traits || !plot.traits.length){ | ||
235 | + plot.traits = this.utils.inferTraits(data, traitsConf.categoryKey, traitsConf.includeCategoryInPlot); | ||
236 | + } | ||
237 | + | ||
238 | + plot.labels = []; | ||
239 | + plot.labelByTrait = {}; | ||
240 | + plot.traits.forEach(function(traitKey, index) { | ||
241 | + plot.domainByTrait[traitKey] = d3.extent(data, function(d) { return traitsConf.value(d, traitKey) }); | ||
242 | + var label = traitKey; | ||
243 | + if(traitsConf.labels && traitsConf.labels.length>index){ | ||
244 | + | ||
245 | + label = traitsConf.labels[index]; | ||
246 | + } | ||
247 | + plot.labels.push(label); | ||
248 | + plot.labelByTrait[traitKey] = label; | ||
249 | + }); | ||
250 | + | ||
251 | + console.log(plot.labelByTrait); | ||
252 | + | ||
253 | + plot.subplots = []; | ||
254 | +}; | ||
255 | + | ||
256 | +D3ScatterPlotMatrix.prototype.setupX = function () { | ||
257 | + | ||
258 | + var plot = this.plot; | ||
259 | + var x = plot.x; | ||
260 | + var conf = this.config; | ||
261 | + | ||
262 | + x.value = conf.traits.value; | ||
263 | + x.scale = d3.scale[conf.x.scale]().range([conf.padding / 2, plot.size - conf.padding / 2]); | ||
264 | + x.map = function (d, trait) { | ||
265 | + return x.scale(x.value(d, trait)); | ||
266 | + }; | ||
267 | + x.axis = d3.svg.axis().scale(x.scale).orient(conf.x.orient).ticks(conf.ticks); | ||
268 | + x.axis.tickSize(plot.size * plot.traits.length); | ||
269 | + | ||
270 | +}; | ||
271 | + | ||
272 | +D3ScatterPlotMatrix.prototype.setupY = function () { | ||
273 | + | ||
274 | + var plot = this.plot; | ||
275 | + var y = plot.y; | ||
276 | + var conf = this.config; | ||
277 | + | ||
278 | + y.value = conf.traits.value; | ||
279 | + y.scale = d3.scale[conf.y.scale]().range([ plot.size - conf.padding / 2, conf.padding / 2]); | ||
280 | + y.map = function (d, trait) { | ||
281 | + return y.scale(y.value(d, trait)); | ||
282 | + }; | ||
283 | + y.axis= d3.svg.axis().scale(y.scale).orient(conf.y.orient).ticks(conf.ticks); | ||
284 | + y.axis.tickSize(-plot.size * plot.traits.length); | ||
285 | +}; | ||
286 | + | ||
287 | + | ||
288 | +D3ScatterPlotMatrix.prototype.drawPlot = function () { | ||
289 | + var self =this; | ||
290 | + var n = self.plot.traits.length; | ||
291 | + var conf = this.config; | ||
292 | + self.svgG.selectAll(".mw-axis-x.mw-axis") | ||
293 | + .data(self.plot.traits) | ||
294 | + .enter().append("g") | ||
295 | + .attr("class", "mw-axis-x mw-axis"+(conf.guides ? '' : ' mw-no-guides')) | ||
296 | + .attr("transform", function(d, i) { return "translate(" + (n - i - 1) * self.plot.size + ",0)"; }) | ||
297 | + .each(function(d) { self.plot.x.scale.domain(self.plot.domainByTrait[d]); d3.select(this).call(self.plot.x.axis); }); | ||
298 | + | ||
299 | + self.svgG.selectAll(".mw-axis-y.mw-axis") | ||
300 | + .data(self.plot.traits) | ||
301 | + .enter().append("g") | ||
302 | + .attr("class", "mw-axis-y mw-axis"+(conf.guides ? '' : ' mw-no-guides')) | ||
303 | + .attr("transform", function(d, i) { return "translate(0," + i * self.plot.size + ")"; }) | ||
304 | + .each(function(d) { self.plot.y.scale.domain(self.plot.domainByTrait[d]); d3.select(this).call(self.plot.y.axis); }); | ||
305 | + | ||
306 | + | ||
307 | + if(conf.tooltip){ | ||
308 | + self.plot.tooltip = this.utils.selectOrAppend(d3.select(self.placeholderSelector), 'div.mw-tooltip', 'div') | ||
309 | + .attr("class", "mw-tooltip") | ||
310 | + .style("opacity", 0); | ||
311 | + } | ||
312 | + | ||
313 | + var cell = self.svgG.selectAll(".mw-cell") | ||
314 | + .data(self.utils.cross(self.plot.traits, self.plot.traits)) | ||
315 | + .enter().append("g") | ||
316 | + .attr("class", "mw-cell") | ||
317 | + .attr("transform", function(d) { return "translate(" + (n - d.i - 1) * self.plot.size + "," + d.j * self.plot.size + ")"; }); | ||
318 | + | ||
319 | + if(conf.brush){ | ||
320 | + this.drawBrush(cell); | ||
321 | + } | ||
322 | + | ||
323 | + cell.each(plotSubplot); | ||
324 | + | ||
325 | + | ||
326 | + | ||
327 | + //Labels | ||
328 | + cell.filter(function(d) { return d.i === d.j; }).append("text") | ||
329 | + .attr("x", conf.padding) | ||
330 | + .attr("y", conf.padding) | ||
331 | + .attr("dy", ".71em") | ||
332 | + .text(function(d) { return self.plot.labelByTrait[d.x]; }); | ||
333 | + | ||
334 | + | ||
335 | + | ||
336 | + | ||
337 | + function plotSubplot(p) { | ||
338 | + var plot = self.plot; | ||
339 | + plot.subplots.push(p); | ||
340 | + var cell = d3.select(this); | ||
341 | + | ||
342 | + plot.x.scale.domain(plot.domainByTrait[p.x]); | ||
343 | + plot.y.scale.domain(plot.domainByTrait[p.y]); | ||
344 | + | ||
345 | + cell.append("rect") | ||
346 | + .attr("class", "mw-frame") | ||
347 | + .attr("x", conf.padding / 2) | ||
348 | + .attr("y", conf.padding / 2) | ||
349 | + .attr("width", conf.size - conf.padding) | ||
350 | + .attr("height", conf.size - conf.padding); | ||
351 | + | ||
352 | + | ||
353 | + p.update = function(){ | ||
354 | + var subplot = this; | ||
355 | + var dots = cell.selectAll("circle") | ||
356 | + .data(self.data); | ||
357 | + | ||
358 | + dots.enter().append("circle"); | ||
359 | + | ||
360 | + dots.attr("cx", function(d){return plot.x.map(d, subplot.x)}) | ||
361 | + .attr("cy", function(d){return plot.y.map(d, subplot.y)}) | ||
362 | + .attr("r", self.config.dot.radius); | ||
363 | + | ||
364 | + if (plot.dot.color) { | ||
365 | + dots.style("fill", plot.dot.color) | ||
366 | + } | ||
367 | + | ||
368 | + if(plot.tooltip){ | ||
369 | + dots.on("mouseover", function(d) { | ||
370 | + plot.tooltip.transition() | ||
371 | + .duration(200) | ||
372 | + .style("opacity", .9); | ||
373 | + plot.tooltip.html("(" + plot.x.value(d, subplot.x) | ||
374 | + + ", " +plot.y.value(d, subplot.y) + ")") | ||
375 | + .style("left", (d3.event.pageX + 5) + "px") | ||
376 | + .style("top", (d3.event.pageY - 28) + "px"); | ||
377 | + }) | ||
378 | + .on("mouseout", function(d) { | ||
379 | + plot.tooltip.transition() | ||
380 | + .duration(500) | ||
381 | + .style("opacity", 0); | ||
382 | + }); | ||
383 | + } | ||
384 | + | ||
385 | + dots.exit().remove(); | ||
386 | + }; | ||
387 | + | ||
388 | + p.update(); | ||
389 | + } | ||
390 | + | ||
391 | + | ||
392 | +}; | ||
393 | + | ||
394 | +D3ScatterPlotMatrix.prototype.update = function () { | ||
395 | + this.plot.subplots.forEach(function(p){p.update()}); | ||
396 | +}; | ||
397 | + | ||
398 | + | ||
399 | +D3ScatterPlotMatrix.prototype.initSvg = function () { | ||
400 | + | ||
401 | + var self = this; | ||
402 | + var config = this.config; | ||
403 | + | ||
404 | + | ||
405 | + | ||
406 | + var width = self.plot.width+ config.margin.left + config.margin.right; | ||
407 | + var height = self.plot.height+ config.margin.top + config.margin.bottom; | ||
408 | + var aspect = width / height; | ||
409 | + | ||
410 | + | ||
411 | + | ||
412 | + self.svg = d3.select(self.placeholderSelector).select("svg"); | ||
413 | + if(!self.svg.empty()){ | ||
414 | + self.svg.remove(); | ||
415 | + | ||
416 | + } | ||
417 | + self.svg = d3.select(self.placeholderSelector).append("svg"); | ||
418 | + | ||
419 | + self.svg | ||
420 | + .attr("width", width) | ||
421 | + .attr("height", height) | ||
422 | + .attr("viewBox", "0 0 "+" "+width+" "+height) | ||
423 | + .attr("preserveAspectRatio", "xMidYMid meet") | ||
424 | + .attr("class", "mw-d3-scatterplot-matrix"); | ||
425 | + | ||
426 | + self.svgG = self.svg.append("g") | ||
427 | + .attr("class", "mw-container") | ||
428 | + .attr("transform", "translate(" + config.margin.left + "," + config.margin.top + ")"); | ||
429 | + | ||
430 | + | ||
431 | + if(!config.width || config.height ){ | ||
432 | + d3.select(window) | ||
433 | + .on("resize", function() { | ||
434 | + //TODO add responsiveness if width/height not specified | ||
435 | + }); | ||
436 | + } | ||
437 | +}; | ||
438 | + | ||
439 | +D3ScatterPlotMatrix.prototype.init = function () { | ||
440 | + var self = this; | ||
441 | + self.initPlot(); | ||
442 | + self.initSvg(); | ||
443 | + self.drawPlot(); | ||
444 | +}; | ||
445 | + | ||
446 | +D3ScatterPlotMatrix.prototype.drawBrush = function (cell) { | ||
447 | + var self = this; | ||
448 | + var brush = d3.svg.brush() | ||
449 | + .x(self.plot.x.scale) | ||
450 | + .y(self.plot.y.scale) | ||
451 | + .on("brushstart", brushstart) | ||
452 | + .on("brush", brushmove) | ||
453 | + .on("brushend", brushend); | ||
454 | + | ||
455 | + cell.append("g").call(brush); | ||
456 | + | ||
457 | + | ||
458 | + var brushCell; | ||
459 | + | ||
460 | + // Clear the previously-active brush, if any. | ||
461 | + function brushstart(p) { | ||
462 | + if (brushCell !== this) { | ||
463 | + d3.select(brushCell).call(brush.clear()); | ||
464 | + self.plot.x.scale.domain(self.plot.domainByTrait[p.x]); | ||
465 | + self.plot.y.scale.domain(self.plot.domainByTrait[p.y]); | ||
466 | + brushCell = this; | ||
467 | + } | ||
468 | + } | ||
469 | + | ||
470 | + // Highlight the selected circles. | ||
471 | + function brushmove(p) { | ||
472 | + var e = brush.extent(); | ||
473 | + self.svgG.selectAll("circle").classed("hidden", function (d) { | ||
474 | + return e[0][0] > d[p.x] || d[p.x] > e[1][0] | ||
475 | + || e[0][1] > d[p.y] || d[p.y] > e[1][1]; | ||
476 | + }); | ||
477 | + } | ||
478 | + // If the brush is empty, select all circles. | ||
479 | + function brushend() { | ||
480 | + if (brush.empty()) self.svgG.selectAll(".hidden").classed("hidden", false); | ||
481 | + } | ||
482 | +}; | ||
483 | + |
bower_components/d3-scatterplot-matrix/dist/d3-scatterplot-matrix.min.css
0 → 100644
1 | +svg.mw-d3-scatterplot-matrix .mw-axis path,svg.mw-d3-scatterplot-matrix .mw-axis.mw-no-guides line{display:none}svg.mw-d3-scatterplot-matrix{background-color:#fff;font-size:11px;height:100%}svg.mw-d3-scatterplot-matrix .mw-axis{shape-rendering:crispEdges}svg.mw-d3-scatterplot-matrix .mw-axis line{stroke:#ddd}svg.mw-d3-scatterplot-matrix .mw-frame{shape-rendering:crispEdges;fill:none;stroke:#aaa}svg.mw-d3-scatterplot-matrix .mw-cell text{font-weight:700;text-transform:capitalize}svg.mw-d3-scatterplot-matrix circle{fill-opacity:.7}svg.mw-d3-scatterplot-matrix circle.hidden{fill:#ccc!important}svg.mw-d3-scatterplot-matrix .extent{fill:#000;fill-opacity:.125;stroke:#fff}.mw-tooltip{position:absolute;pointer-events:none;font-size:11px;background:#fdfdfd;padding:3px 5px;border-radius:8px;box-shadow:1px 3px 3px #b7b7b7} | ||
0 | \ No newline at end of file | 2 | \ No newline at end of file |
bower_components/d3-scatterplot-matrix/dist/d3-scatterplot-matrix.min.js
0 → 100644
1 | +function D3ScatterPlotMatrixUtils(){}D3ScatterPlotMatrixUtils.prototype.deepExtend=function(t){var r=this;!t&&arguments.length>1&&Array.isArray(arguments[1])&&(t=[]),t=t||{};for(var e=1;e<arguments.length;e++){var i=arguments[e];if(i)for(var n in i)if(i.hasOwnProperty(n)){var o=Array.isArray(t[n]),a=r.isObject(t[n]),p=r.isObject(i[n]);a&&!o&&p?r.deepExtend(t[n],i[n]):t[n]=i[n]}}return t},D3ScatterPlotMatrixUtils.prototype.cross=function(t,r){var e,i,n=[],o=t.length,a=r.length;for(e=-1;++e<o;)for(i=-1;++i<a;)n.push({x:t[e],i:e,y:r[i],j:i});return n},D3ScatterPlotMatrixUtils.prototype.inferTraits=function(t,r,e){var i=[];if(t.length){var n=t[0];if(n instanceof Array)i=n.map(function(t,r){return r});else if("object"==typeof n)for(var o in n)n.hasOwnProperty(o)&&i.push(o)}if(!e){var a=i.indexOf(r);a>-1&&i.splice(a,1)}return i},D3ScatterPlotMatrixUtils.prototype.isObject=function(t){return null!==t&&"object"==typeof t},D3ScatterPlotMatrixUtils.prototype.isNumber=function(t){return!isNaN(t)&&"number"==typeof t},D3ScatterPlotMatrixUtils.prototype.isFunction=function(t){return"function"==typeof t},D3ScatterPlotMatrixUtils.prototype.selectOrAppend=function(t,r,e){var i=t.select(r);return i.empty()?t.append(e||r):i}; | ||
2 | +function D3ScatterPlotMatrix(t,i,e){this.utils=new D3ScatterPlotMatrixUtils,this.placeholderSelector=t,this.svg=null,this.defaultConfig={width:0,size:200,padding:20,brush:!0,guides:!0,tooltip:!0,ticks:null,margin:{left:30,right:30,top:30,bottom:30},x:{orient:"bottom",scale:"linear"},y:{orient:"left",scale:"linear"},dot:{radius:2,color:null,d3ColorCategory:"category10"},traits:{labels:[],keys:[],categoryKey:null,includeCategoryInPlot:!1,value:function(t,i){return t[i]}}},e&&this.setConfig(e),i&&this.setData(i),this.init()}D3ScatterPlotMatrix.prototype.setData=function(t){return this.data=t,this},D3ScatterPlotMatrix.prototype.setConfig=function(t){return this.config=this.utils.deepExtend({},this.defaultConfig,t),this},D3ScatterPlotMatrix.prototype.initPlot=function(){var t=this,i=this.config.margin,e=this.config;this.plot={x:{},y:{},dot:{color:null}},this.setupTraits(),this.plot.size=e.size;var a=e.width,o=d3.select(this.placeholderSelector).node();if(!a){var l=i.left+i.right+this.plot.traits.length*this.plot.size;a=Math.min(o.getBoundingClientRect().width,l)}var r=a;r||(r=o.getBoundingClientRect().height),this.plot.width=a-i.left-i.right,this.plot.height=r-i.top-i.bottom,null===e.ticks&&(e.ticks=this.plot.size/40),this.setupX(),this.setupY(),e.dot.d3ColorCategory&&(this.plot.dot.colorCategory=d3.scale[e.dot.d3ColorCategory]());var s=e.dot.color;return s?(this.plot.dot.colorValue=s,"string"==typeof s||s instanceof String?this.plot.dot.color=s:this.plot.dot.colorCategory&&(this.plot.dot.color=function(i){return t.plot.dot.colorCategory(t.plot.dot.colorValue(i))})):e.traits.categoryKey&&(this.plot.dot.color=function(i){return t.plot.dot.colorCategory(i[e.traits.categoryKey])}),this},D3ScatterPlotMatrix.prototype.setupTraits=function(){var t=this.config.traits,i=this.data,e=this.plot;e.domainByTrait={},e.traits=t.keys,e.traits&&e.traits.length||(e.traits=this.utils.inferTraits(i,t.categoryKey,t.includeCategoryInPlot)),e.labels=[],e.labelByTrait={},e.traits.forEach(function(a,o){e.domainByTrait[a]=d3.extent(i,function(i){return t.value(i,a)});var l=a;t.labels&&t.labels.length>o&&(l=t.labels[o]),e.labels.push(l),e.labelByTrait[a]=l}),void 0,e.subplots=[]},D3ScatterPlotMatrix.prototype.setupX=function(){var t=this.plot,i=t.x,e=this.config;i.value=e.traits.value,i.scale=d3.scale[e.x.scale]().range([e.padding/2,t.size-e.padding/2]),i.map=function(t,e){return i.scale(i.value(t,e))},i.axis=d3.svg.axis().scale(i.scale).orient(e.x.orient).ticks(e.ticks),i.axis.tickSize(t.size*t.traits.length)},D3ScatterPlotMatrix.prototype.setupY=function(){var t=this.plot,i=t.y,e=this.config;i.value=e.traits.value,i.scale=d3.scale[e.y.scale]().range([t.size-e.padding/2,e.padding/2]),i.map=function(t,e){return i.scale(i.value(t,e))},i.axis=d3.svg.axis().scale(i.scale).orient(e.y.orient).ticks(e.ticks),i.axis.tickSize(-t.size*t.traits.length)},D3ScatterPlotMatrix.prototype.drawPlot=function(){function t(t){var e=i.plot;e.subplots.push(t);var o=d3.select(this);e.x.scale.domain(e.domainByTrait[t.x]),e.y.scale.domain(e.domainByTrait[t.y]),o.append("rect").attr("class","mw-frame").attr("x",a.padding/2).attr("y",a.padding/2).attr("width",a.size-a.padding).attr("height",a.size-a.padding),t.update=function(){var t=this,a=o.selectAll("circle").data(i.data);a.enter().append("circle"),a.attr("cx",function(i){return e.x.map(i,t.x)}).attr("cy",function(i){return e.y.map(i,t.y)}).attr("r",i.config.dot.radius),e.dot.color&&a.style("fill",e.dot.color),e.tooltip&&a.on("mouseover",function(i){e.tooltip.transition().duration(200).style("opacity",.9),e.tooltip.html("("+e.x.value(i,t.x)+", "+e.y.value(i,t.y)+")").style("left",d3.event.pageX+5+"px").style("top",d3.event.pageY-28+"px")}).on("mouseout",function(t){e.tooltip.transition().duration(500).style("opacity",0)}),a.exit().remove()},t.update()}var i=this,e=i.plot.traits.length,a=this.config;i.svgG.selectAll(".mw-axis-x.mw-axis").data(i.plot.traits).enter().append("g").attr("class","mw-axis-x mw-axis"+(a.guides?"":" mw-no-guides")).attr("transform",function(t,a){return"translate("+(e-a-1)*i.plot.size+",0)"}).each(function(t){i.plot.x.scale.domain(i.plot.domainByTrait[t]),d3.select(this).call(i.plot.x.axis)}),i.svgG.selectAll(".mw-axis-y.mw-axis").data(i.plot.traits).enter().append("g").attr("class","mw-axis-y mw-axis"+(a.guides?"":" mw-no-guides")).attr("transform",function(t,e){return"translate(0,"+e*i.plot.size+")"}).each(function(t){i.plot.y.scale.domain(i.plot.domainByTrait[t]),d3.select(this).call(i.plot.y.axis)}),a.tooltip&&(i.plot.tooltip=this.utils.selectOrAppend(d3.select(i.placeholderSelector),"div.mw-tooltip","div").attr("class","mw-tooltip").style("opacity",0));var o=i.svgG.selectAll(".mw-cell").data(i.utils.cross(i.plot.traits,i.plot.traits)).enter().append("g").attr("class","mw-cell").attr("transform",function(t){return"translate("+(e-t.i-1)*i.plot.size+","+t.j*i.plot.size+")"});a.brush&&this.drawBrush(o),o.each(t),o.filter(function(t){return t.i===t.j}).append("text").attr("x",a.padding).attr("y",a.padding).attr("dy",".71em").text(function(t){return i.plot.labelByTrait[t.x]})},D3ScatterPlotMatrix.prototype.update=function(){this.plot.subplots.forEach(function(t){t.update()})},D3ScatterPlotMatrix.prototype.initSvg=function(){var t=this,i=this.config,e=t.plot.width+i.margin.left+i.margin.right,a=t.plot.height+i.margin.top+i.margin.bottom;t.svg=d3.select(t.placeholderSelector).select("svg"),t.svg.empty()||t.svg.remove(),t.svg=d3.select(t.placeholderSelector).append("svg"),t.svg.attr("width",e).attr("height",a).attr("viewBox","0 0 "+e+" "+a).attr("preserveAspectRatio","xMidYMid meet").attr("class","mw-d3-scatterplot-matrix"),t.svgG=t.svg.append("g").attr("class","mw-container").attr("transform","translate("+i.margin.left+","+i.margin.top+")"),i.width&&!i.height||d3.select(window).on("resize",function(){})},D3ScatterPlotMatrix.prototype.init=function(){var t=this;t.initPlot(),t.initSvg(),t.drawPlot()},D3ScatterPlotMatrix.prototype.drawBrush=function(t){function i(t){r!==this&&(d3.select(r).call(l.clear()),o.plot.x.scale.domain(o.plot.domainByTrait[t.x]),o.plot.y.scale.domain(o.plot.domainByTrait[t.y]),r=this)}function e(t){var i=l.extent();o.svgG.selectAll("circle").classed("hidden",function(e){return i[0][0]>e[t.x]||e[t.x]>i[1][0]||i[0][1]>e[t.y]||e[t.y]>i[1][1]})}function a(){l.empty()&&o.svgG.selectAll(".hidden").classed("hidden",!1)}var o=this,l=d3.svg.brush().x(o.plot.x.scale).y(o.plot.y.scale).on("brushstart",i).on("brush",e).on("brushend",a);t.append("g").call(l);var r}; | ||
0 | \ No newline at end of file | 3 | \ No newline at end of file |
datalets/scatterplot-datalet/scatterplot-datalet.html