1 | var domready = require('domready')
|
2 | , pretty = require('prettysize')
|
3 | , schemes = require('./schemes')
|
4 | , d3 = require('d3')
|
5 |
|
6 | var arc = d3.svg.arc()
|
7 | .startAngle(function(d) { return angle(d.x) })
|
8 | .endAngle(function(d) { return angle(d.x + Math.max(d.dx - 0.025, 0.0125)) })
|
9 | .innerRadius(function(d) { return Math.sqrt(d.y) })
|
10 | .outerRadius(function(d) { return Math.sqrt(d.y + d.dy * 0.65) })
|
11 |
|
12 | var initArc = d3.svg.arc()
|
13 | .startAngle(function(d) { return angle(d.x) })
|
14 | .endAngle(function(d) { return angle(d.x + d.dx) })
|
15 | .innerRadius(function(d) { return Math.sqrt(d.y) })
|
16 | .outerRadius(function(d) { return Math.sqrt(d.y) })
|
17 |
|
18 | domready(function() {
|
19 | var root = window.disc
|
20 | , width = window.innerWidth
|
21 | , height = Math.max(window.innerHeight - 100, 100)
|
22 | , radius = Math.min(width, height) * 0.45
|
23 | , deg = 120
|
24 |
|
25 | var svg = d3.select('.chart').append('svg')
|
26 | .attr('width', width)
|
27 | .attr('height', height)
|
28 | .append('g')
|
29 | .attr('transform', 'translate(' + width / 2 + ',' + height * .52 + ')')
|
30 |
|
31 | var palettes = d3.select('.palette-wrap')
|
32 | .style('top', String(window.innerHeight - (schemes.length - 1) * 56 - 16) + 'px')
|
33 | .selectAll('.palette')
|
34 | .data(schemes)
|
35 | .enter()
|
36 | .append('svg')
|
37 | .style('display', 'inline-block')
|
38 | .classed('palette', true)
|
39 | .on('click', function(d, i) {
|
40 | useScheme(i, path.transition()
|
41 | .duration(600)
|
42 | .ease(bounce_high, 1000)
|
43 | .delay(function(d, i) {
|
44 | return d.x * 100 + d.y / maxdepth * 0.06125
|
45 | })
|
46 | )
|
47 | })
|
48 |
|
49 | palettes.append('rect')
|
50 | .attr('width', 23)
|
51 | .attr('height', 48)
|
52 | .style('fill', function(d) {
|
53 | return d.background
|
54 | })
|
55 |
|
56 | palettes.selectAll('.color')
|
57 | .data(function(d) { return d.all })
|
58 | .enter()
|
59 | .append('rect')
|
60 | .style('fill', function(d) { return d })
|
61 | .attr('x', 25)
|
62 | .attr('y', function(d, i, j) {
|
63 | return 48 * i / schemes[j].all.length - 1
|
64 | })
|
65 | .attr('width', 22)
|
66 | .attr('height', function(d, i, j) {
|
67 | return 48 / schemes[j].all.length - 1
|
68 | })
|
69 |
|
70 | var partition = d3.layout.partition()
|
71 | .sort(null)
|
72 | .size([2 * Math.PI, radius * radius])
|
73 | .value(function(d) { return 1 })
|
74 |
|
75 |
|
76 |
|
77 |
|
78 |
|
79 | var title = svg.append('text')
|
80 | .text(root.name)
|
81 | .attr('x', 0)
|
82 | .attr('y', -5)
|
83 | .style('font-size', '12px')
|
84 | .style('fill', 'white')
|
85 | .style('font-weight', 500)
|
86 | .style('alignment-baseline', 'middle')
|
87 | .style('text-anchor', 'middle')
|
88 |
|
89 |
|
90 |
|
91 |
|
92 |
|
93 | var size = svg.append('text')
|
94 | .text(pretty(root.size))
|
95 | .attr('x', 0)
|
96 | .attr('y', 15)
|
97 | .style('fill', 'white')
|
98 | .style('font-size', '10px')
|
99 | .style('alignment-baseline', 'middle')
|
100 | .style('text-anchor', 'middle')
|
101 |
|
102 |
|
103 |
|
104 |
|
105 |
|
106 |
|
107 | var groups = svg.datum(root).selectAll('g')
|
108 | .data(partition.nodes)
|
109 | .enter()
|
110 | .append('g')
|
111 | .attr('transform', 'rotate(' + deg + ')')
|
112 |
|
113 | var maxdepth = groups[0].reduce(function(max, el) {
|
114 | return Math.max(max, el.__data__.depth)
|
115 | }, 0)
|
116 |
|
117 |
|
118 |
|
119 |
|
120 |
|
121 | var path = groups.append('path')
|
122 | .attr('d', initArc)
|
123 | .attr('display', function(d) {
|
124 | return d.depth ? null : 'none'
|
125 | })
|
126 | .style('stroke', '#2B2B2B')
|
127 | .style('stroke-width', '0')
|
128 | .style('fill-rule', 'evenodd')
|
129 | .each(function(d) {
|
130 | d.x0 = d.x
|
131 | d.dx0 = d.dx
|
132 | d.el = this
|
133 | })
|
134 |
|
135 |
|
136 |
|
137 |
|
138 |
|
139 |
|
140 |
|
141 | var background
|
142 | , scheme = 0
|
143 | , specials
|
144 | , color
|
145 |
|
146 | useScheme(scheme, path)
|
147 | function useScheme(n, path) {
|
148 | background = schemes[n].background
|
149 | specials = schemes[n].specials
|
150 |
|
151 | palettes
|
152 | .transition()
|
153 | .ease('bounce')
|
154 | .duration(500)
|
155 | .attr('height', function(d, i) {
|
156 | return i === n ? 0 : 48
|
157 | })
|
158 |
|
159 | ;[d3.select('body')
|
160 | , d3.select('html')].forEach(function(el) {
|
161 | el.transition()
|
162 | .ease('sin-in-out')
|
163 | .duration(600)
|
164 | .style('background', background)
|
165 | })
|
166 |
|
167 | var colors = schemes[n].main
|
168 | Object.keys(specials).forEach(function(key) {
|
169 | var idx = colors.indexOf(specials[key].toLowerCase())
|
170 | if (idx === -1) return
|
171 | colors.splice(idx, 1)
|
172 | })
|
173 |
|
174 | color = d3.scale
|
175 | .ordinal()
|
176 | .range(colors)
|
177 |
|
178 | path.style('fill', function(d) {
|
179 | var name = d.children ? d.name : d.parent.name
|
180 | return d.c = schemes[n].modifier.call(d, specials[name] || color(name), root)
|
181 | })
|
182 | }
|
183 |
|
184 | path.transition()
|
185 | .duration(1000)
|
186 | .ease('elastic', 2, 1)
|
187 | .delay(function(d, i) {
|
188 | return d.x * 100 + (i % 4) * 250 + d.y / maxdepth * 0.25
|
189 | })
|
190 | .attr('d', arc)
|
191 |
|
192 |
|
193 |
|
194 |
|
195 |
|
196 |
|
197 | groups.transition()
|
198 | .duration(3250)
|
199 | .delay(function(d, i) {
|
200 | return d.x * 100 + (i % 4) * 250 + d.y / maxdepth * 0.25 + 250
|
201 | })
|
202 | .attrTween('transform', rotateTween(deg))
|
203 |
|
204 | groups.on('mouseover', function(d) {
|
205 | highlight(d)
|
206 | title.text(d.name)
|
207 | size.text(pretty(d.size))
|
208 | }).on('mouseout', function(d) {
|
209 | unhighlight(d)
|
210 | title.text(root.name)
|
211 | size.text(pretty(root.size))
|
212 | })
|
213 |
|
214 | highlight.tween = hoverTween(1)
|
215 | function highlight(d) {
|
216 | if (d.el) d3.select(d.el)
|
217 | .transition()
|
218 | .delay(function(d) { return (d.depth - 1) * 300 / maxdepth })
|
219 | .ease('back-out', 10)
|
220 | .duration(500)
|
221 | .attrTween('d', highlight.tween)
|
222 | .style('fill', function(d) { return d.c })
|
223 |
|
224 | if (d.children) {
|
225 | var i = d.children.length
|
226 | while (i--) highlight(d.children[i])
|
227 | }
|
228 | }
|
229 |
|
230 | unhighlight.tween = hoverTween(0)
|
231 | function unhighlight(d) {
|
232 | if (d.el) d3.select(d.el)
|
233 | .transition()
|
234 | .delay(function(d) { return (d.depth - 1) * 300 / maxdepth })
|
235 | .ease('back-out', 4)
|
236 | .duration(500)
|
237 | .attrTween('d', unhighlight.tween)
|
238 | .style('fill', function(d) { return d.c })
|
239 |
|
240 | if (d.children) {
|
241 | var i = d.children.length
|
242 | while (i--) unhighlight(d.children[i])
|
243 | }
|
244 | }
|
245 |
|
246 | var modes = d3.selectAll('[data-mode]')
|
247 | modes.on('click', function change() {
|
248 | var value
|
249 | switch (this.getAttribute('data-mode')) {
|
250 | case 'count':
|
251 | default:
|
252 | value = function() { return 1 }
|
253 | break
|
254 | case 'size':
|
255 | value = function(d) { return d.size }
|
256 | break
|
257 | }
|
258 |
|
259 | modes.style('opacity', null)
|
260 | d3.select(this).style('opacity', 1)
|
261 |
|
262 | groups
|
263 | .data(partition.value(value).nodes)
|
264 | .select('path')
|
265 | .transition()
|
266 | .duration(1500)
|
267 | .attrTween('d', arcTween)
|
268 | })
|
269 | })
|
270 |
|
271 | function angle(x) {
|
272 | return x
|
273 | }
|
274 |
|
275 |
|
276 |
|
277 | function bounce_high(t) {
|
278 | return t < 1 / 2.75 ? 7.5625 * t * t
|
279 | : t < 2 / 2.75 ? 7.5625 * (t -= 1.5 / 2.75) * t + .65
|
280 | : t < 2.5 / 2.75 ? 7.5625 * (t -= 2.25 / 2.75) * t + .85
|
281 | : 7.5625 * (t -= 2.625 / 2.75) * t + .975
|
282 | }
|
283 |
|
284 | function arcTween(a) {
|
285 | var i = d3.interpolate({x: a.x0, dx: a.dx0}, a)
|
286 | return function(t) {
|
287 | var b = i(t)
|
288 | a.x0 = b.x
|
289 | a.dx0 = b.dx
|
290 | return arc(b)
|
291 | }
|
292 | }
|
293 |
|
294 |
|
295 |
|
296 |
|
297 |
|
298 |
|
299 |
|
300 | function hoverTween(z) {
|
301 | var ht = 0
|
302 | var harc = d3.svg.arc()
|
303 | .startAngle(function(d) {
|
304 | return angle(d.x)
|
305 | })
|
306 | .endAngle(function(d) {
|
307 | return angle(d.x
|
308 | + (1 - ht) * Math.max(d.dx - 0.025, 0.0125)
|
309 | + ht * (d.dx + 0.00005)
|
310 | )
|
311 | })
|
312 | .innerRadius(function(d) {
|
313 | return Math.sqrt(d.y)
|
314 | })
|
315 | .outerRadius(function(d) {
|
316 | return Math.sqrt(d.y + d.dy * (ht * 0.35 + 0.65)) + ht
|
317 | })
|
318 |
|
319 | return function(a) {
|
320 | a.t0 = a.t3 = a.t0 || 0
|
321 | a.t1 = z
|
322 | a.t2 = a.t1 - a.t0
|
323 | return function(_t) {
|
324 | ht = a.t2 * _t + a.t3
|
325 | a.t0 = ht
|
326 | return harc(a)
|
327 | }
|
328 | }
|
329 | }
|
330 |
|
331 |
|
332 |
|
333 |
|
334 |
|
335 | function rotateTween(deg) {
|
336 | return function(d) {
|
337 | return function(t) {
|
338 | return 'rotate(' + (1-t) * deg + ')'
|
339 | }
|
340 | }
|
341 | }
|