cloud.min.js 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452
  1. function flatten(t, e) {
  2. if ("string" == typeof t) return t;
  3. var n = [];
  4. for (e in t) {
  5. var a = flatten(t[e], e);
  6. a && n.push(a)
  7. }
  8. return n.join(" ")
  9. }
  10. function parseText(t) {
  11. tags = {};
  12. var e = {},
  13. n = undefined;
  14. t.split(n ? /\n/g : wordSeparators).forEach(function (t) {
  15. ((t = t.substr(0, maxLength), e[t.toLowerCase()] = t, tags[t = t.toLowerCase()] = (tags[t] || 0) + 1))
  16. }), tags = d3.entries(tags).sort(function (t, e) {
  17. return e.value - t.value
  18. }), tags.forEach(function (t) {
  19. t.key = e[t.key]
  20. }), generate()
  21. }
  22. function generate() {
  23. //d3.selectAll("#angle-count, #angle-from, #angle-to").on("change", t).on("mouseup", t), t(), parseText(d3.select("#text").property("value"))
  24. layout.font(d3.select("#font").property("value")).spiral(d3.select("#spiral").property("value")), fontSize = d3.scale[d3.select("#scale").property("value")]().range([10, 100]), tags.length && fontSize.domain([+tags[tags.length - 1].value || 1, +tags[0].value]), complete = 0, statusText.style("display", null), words = [], layout.stop().words(tags.slice(0, max = Math.min(tags.length, 261))).start()
  25. }
  26. function inChange() {
  27. function n(t, e) {
  28. return t[0] * e[1] - t[1] * e[0]
  29. }
  30. function a(t, e) {
  31. return t[0] * e[0] + t[1] * e[1]
  32. }
  33. var r = 40.5,
  34. o = 35,
  35. s = 20,
  36. l = d3.select("#angles").append("svg").attr("width", 2 * (r + o)).attr("height", r + 1.5 * s).append("g").attr("transform", "translate(" + [r + o, r + s] + ")");
  37. l.append("path").style("fill", "none").attr("d", ["M", -r, 0, "A", r, r, 0, 0, 1, r, 0].join(" ")), l.append("line").attr("x1", -r - 7).attr("x2", r + 7), l.append("line").attr("y2", -r - 7), l.selectAll("text").data([-90, 0, 90]).enter().append("text").attr("dy", function (t, e) {
  38. return 1 === e ? null : ".3em"
  39. }).attr("text-anchor", function (t, e) {
  40. return ["end", "middle", "start"][e]
  41. }).attr("transform", function (t) {
  42. return t += 90, "rotate(" + t + ")translate(" + -(r + 10) + ")rotate(" + -t + ")translate(2)"
  43. }).text(function (t) {
  44. return t + "\xb0"
  45. });
  46. var u, i, c, d = Math.PI / 180,
  47. h = d3.scale.linear(),
  48. f = d3.svg.arc().innerRadius(0).outerRadius(r);
  49. c = +d3.select("#angle-count").property("value"), u = Math.max(-90, Math.min(90, +d3.select("#angle-from").property("value"))), i = Math.max(-90, Math.min(90, +d3.select("#angle-to").property("value")));
  50. parseText(d3.select("#text").property("value"))
  51. h.domain([0, c - 1]).range([u, i]);
  52. var t = l.selectAll("path.angle").data([{
  53. startAngle: u * d,
  54. endAngle: i * d
  55. }]);
  56. t.enter().insert("path", "circle").attr("class", "angle").style("fill", "#fc0"), t.attr("d", f);
  57. var o = l.selectAll("line.angle").data(d3.range(c).map(h));
  58. o.enter().append("line").attr("class", "angle"), o.exit().remove(), o.attr("transform", function (t) {
  59. return "rotate(" + (90 + t) + ")"
  60. }).attr("x2", function (t, e) {
  61. return e && e !== c - 1 ? -r : -r - 5
  62. });
  63. var s = l.selectAll("path.drag").data([u, i]);
  64. s.enter().append("path").attr("class", "drag").attr("d", "M-9.5,0L-3,3.5L-3,-3.5Z").call(d3.behavior.drag().on("drag", function (t, o) {
  65. t = (o ? i : u) + 90;
  66. var s = [-r * Math.cos(t * d), -r * Math.sin(t * d)],
  67. l = [d3.event.x, d3.event.y],
  68. c = ~~(Math.atan2(n(s, l), a(s, l)) / d);
  69. t = Math.max(-90, Math.min(90, t + c - 90)), c = i - u, o ? (i = t, c > 360 ? u += c - 360 : 0 > c && (u = i)) : (u = t, c > 360 ? i += 360 - c : 0 > c && (i = u)), e()
  70. }).on("dragend", generate)), s.attr("transform", function (t) {
  71. return "rotate(" + (t + 90) + ")translate(-" + r + ")"
  72. }), layout.rotate(function () {
  73. return h(~~(Math.random() * c))
  74. })//d3.select("#angle-count").property("value", c), d3.select("#angle-from").property("value", u), d3.select("#angle-to").property("value", i)
  75. }
  76. function progress(t) {
  77. statusText.text(++complete + "/" + max)
  78. }
  79. function draw(t, e) {
  80. statusText.style("display", "none"), scale = e ? Math.min(w / Math.abs(e[1].x - w / 2), w / Math.abs(e[0].x - w / 2), h / Math.abs(e[1].y - h / 2), h / Math.abs(e[0].y - h / 2)) / 2 : 1, words = t;
  81. var n = vis.selectAll("text").data(words, function (t) {
  82. return t.text.toLowerCase()
  83. });
  84. n.transition().duration(1e3).attr("transform", function (t) {
  85. return "translate(" + [t.x, t.y] + ")rotate(" + t.rotate + ")"
  86. }).style("font-size", function (t) {
  87. return t.size + "px"
  88. }), n.enter().append("text").attr("text-anchor", "middle").attr("transform", function (t) {
  89. return "translate(" + [t.x, t.y] + ")rotate(" + t.rotate + ")"
  90. }).style("font-size", "1px").transition().duration(1e3).style("font-size", function (t) {
  91. return t.size + "px"
  92. }), n.style("font-family", function (t) {
  93. return t.font
  94. }).style("fill", function (t) {
  95. return fill(t.text.toLowerCase())
  96. }).text(function (t) {
  97. return t.text
  98. });
  99. var a = background.append("g").attr("transform", vis.attr("transform")),
  100. r = a.node();
  101. n.exit().each(function () {
  102. r.appendChild(this)
  103. }), a.transition().duration(1e3).style("opacity", 1e-6).remove(), vis.transition().delay(1e3).duration(750).attr("transform", "translate(" + [w >> 1, h >> 1] + ")scale(" + scale + ")")
  104. }
  105. function downloadPNG() {
  106. d3.event.preventDefault();
  107. var t = document.createElement("canvas"),
  108. e = t.getContext("2d");
  109. t.width = w, t.height = h, e.translate(w >> 1, h >> 1),
  110. e.scale(scale, scale), words.forEach(function (t, n) {
  111. e.save(), e.translate(t.x, t.y), e.rotate(t.rotate * Math.PI / 180),
  112. e.textAlign = "center",
  113. e.fillStyle = fill(t.text.toLowerCase()),
  114. e.font = t.size + "px " + t.font,
  115. e.fillText(t.text, 0, 0), e.restore()
  116. }),
  117. echoContentType.attr("value", "image/png"),
  118. echoInput.attr("value", t.toDataURL("image/png")),
  119. echoForm.node().submit()
  120. }
  121. function downloadSVG() {
  122. d3.event.preventDefault(), echoContentType.attr("value", "image/svg+xml;charset=utf-8"),
  123. echoInput.attr("value", svg.attr("version", "1.1").attr("xmlns", "http://www.w3.org/2000/svg").node().parentNode.innerHTML),
  124. echoForm.node().submit()
  125. } !
  126. function (t) {
  127. function e() {
  128. function t(t, n, a) {
  129. for (var r, o, s, l = ([{
  130. x: 0,
  131. y: 0
  132. }, {
  133. x: e[0],
  134. y: e[1]
  135. }], n.x), i = n.y, d = Math.sqrt(e[0] * e[0] + e[1] * e[1]), h = m(e), f = Math.random() < .5 ? 1 : -1, p = -f;
  136. (r = h(p += f)) && (o = ~~r[0], s = ~~r[1], !(Math.min(o, s) > d));) if (n.x = l + o, n.y = i + s, !(n.x + n.x0 < 0 || n.y + n.y0 < 0 || n.x + n.x1 > e[0] || n.y + n.y1 > e[1]) && (!a || !u(n, t, e[0])) && (!a || c(n, a))) {
  137. for (var y, g = n.sprite, v = n.width >> 5, x = e[0] >> 5, w = n.x - (v << 4), M = 127 & w, b = 32 - M, z = n.y1 - n.y0, k = (n.y + n.y0) * x + (w >> 5), T = 0; z > T; T++) {
  138. y = 0;
  139. for (var A = 0; v >= A; A++) t[k + A] |= y << b | (v > A ? (y = g[T * v + A]) >>> M : 0);
  140. k += x
  141. }
  142. return delete n.sprite, !0
  143. }
  144. return !1
  145. }
  146. var e = [256, 256],
  147. h = n,
  148. p = a,
  149. y = r,
  150. g = o,
  151. v = s,
  152. m = d,
  153. x = [],
  154. w = 1 / 0,
  155. b = d3.dispatch("word", "end"),
  156. z = null,
  157. k = {};
  158. return k.start = function () {
  159. function n() {
  160. for (var n, s = +new Date; + new Date - s < w && ++u < o && z;) n = d[u], n.x = e[0] * (Math.random() + .5) >> 1, n.y = e[1] * (Math.random() + .5) >> 1, l(n, d, u), t(a, n, r) && (c.push(n), b.word(n), r ? i(r, n) : r = [{
  161. x: n.x + n.x0,
  162. y: n.y + n.y0
  163. }, {
  164. x: n.x + n.x1,
  165. y: n.y + n.y1
  166. }], n.x -= e[0] >> 1, n.y -= e[1] >> 1);
  167. u >= o && (k.stop(), b.end(c, r))
  168. }
  169. var a = f((e[0] >> 5) * e[1]),
  170. r = null,
  171. o = x.length,
  172. u = -1,
  173. c = [],
  174. d = x.map(function (t, e) {
  175. return {
  176. text: h.call(this, t, e),
  177. font: p.call(this, t, e),
  178. rotate: g.call(this, t, e),
  179. size: ~~y.call(this, t, e),
  180. padding: s.call(this, t, e)
  181. }
  182. }).sort(function (t, e) {
  183. return e.size - t.size
  184. });
  185. return z && clearInterval(z), z = setInterval(n, 0), n(), k
  186. }, k.stop = function () {
  187. return z && (clearInterval(z), z = null), k
  188. }, k.timeInterval = function (t) {
  189. return arguments.length ? (w = null == t ? 1 / 0 : t, k) : w
  190. }, k.words = function (t) {
  191. return arguments.length ? (x = t, k) : x
  192. }, k.size = function (t) {
  193. return arguments.length ? (e = [+t[0], +t[1]], k) : e
  194. }, k.font = function (t) {
  195. return arguments.length ? (p = d3.functor(t), k) : p
  196. }, k.rotate = function (t) {
  197. return arguments.length ? (g = d3.functor(t), k) : g
  198. }, k.text = function (t) {
  199. return arguments.length ? (h = d3.functor(t), k) : h
  200. }, k.spiral = function (t) {
  201. return arguments.length ? (m = M[t + ""] || t, k) : m
  202. }, k.fontSize = function (t) {
  203. return arguments.length ? (y = d3.functor(t), k) : y
  204. }, k.padding = function (t) {
  205. return arguments.length ? (v = d3.functor(t), k) : v
  206. }, d3.rebind(k, b, "on")
  207. }
  208. function n(t) {
  209. return t.text
  210. }
  211. function a() {
  212. return "serif"
  213. }
  214. function r(t) {
  215. return Math.sqrt(t.value)
  216. }
  217. function o() {
  218. return 30 * (~~(6 * Math.random()) - 3)
  219. }
  220. function s() {
  221. return 1
  222. }
  223. function l(t, e, n) {
  224. if (!t.sprite) {
  225. w.clearRect(0, 0, (g << 5) / m, v / m);
  226. var a = 0,
  227. r = 0,
  228. o = 0,
  229. s = e.length;
  230. for (n--; ++n < s;) {
  231. t = e[n], w.save(), w.font = ~~((t.size + 1) / m) + "px " + t.font;
  232. var l = w.measureText(t.text + "m").width * m,
  233. u = t.size << 1;
  234. if (t.rotate) {
  235. var i = Math.sin(t.rotate * y),
  236. c = Math.cos(t.rotate * y),
  237. d = l * c,
  238. h = l * i,
  239. f = u * c,
  240. p = u * i;
  241. l = Math.max(Math.abs(d + p), Math.abs(d - p)) + 31 >> 5 << 5, u = ~~Math.max(Math.abs(h + f), Math.abs(h - f))
  242. } else l = l + 31 >> 5 << 5;
  243. if (u > o && (o = u), a + l >= g << 5 && (a = 0, r += o, o = 0), r + u >= v) break;
  244. w.translate((a + (l >> 1)) / m, (r + (u >> 1)) / m), t.rotate && w.rotate(t.rotate * y), w.fillText(t.text, 0, 0), w.restore(), t.width = l, t.height = u, t.xoff = a, t.yoff = r, t.x1 = l >> 1, t.y1 = u >> 1, t.x0 = -t.x1, t.y0 = -t.y1, a += l
  245. }
  246. for (var x = w.getImageData(0, 0, (g << 5) / m, v / m).data, M = []; --n >= 0;) {
  247. t = e[n];
  248. for (var l = t.width, b = l >> 5, u = t.y1 - t.y0, z = t.padding, k = 0; u * b > k; k++) M[k] = 0;
  249. if (a = t.xoff, null == a) return;
  250. r = t.yoff;
  251. for (var T = 0, A = -1, C = 0; u > C; C++) {
  252. for (var k = 0; l > k; k++) {
  253. var S = b * C + (k >> 5),
  254. I = x[(r + C) * (g << 5) + (a + k) << 2] ? 1 << 31 - k % 32 : 0;
  255. z && (C && (M[S - b] |= I), l - 1 > C && (M[S + b] |= I), I |= I << 1 | I >> 1), M[S] |= I, T |= I
  256. }
  257. T ? A = C : (t.y0++, u--, C--, r++)
  258. }
  259. t.y1 = t.y0 + A, t.sprite = M.slice(0, (t.y1 - t.y0) * b)
  260. }
  261. }
  262. }
  263. function u(t, e, n) {
  264. n >>= 5;
  265. for (var a, r = t.sprite, o = t.width >> 5, s = t.x - (o << 4), l = 127 & s, u = 32 - l, i = t.y1 - t.y0, c = (t.y + t.y0) * n + (s >> 5), d = 0; i > d; d++) {
  266. a = 0;
  267. for (var h = 0; o >= h; h++) if ((a << u | (o > h ? (a = r[d * o + h]) >>> l : 0)) & e[c + h]) return !0;
  268. c += n
  269. }
  270. return !1
  271. }
  272. function i(t, e) {
  273. var n = t[0],
  274. a = t[1];
  275. e.x + e.x0 < n.x && (n.x = e.x + e.x0), e.y + e.y0 < n.y && (n.y = e.y + e.y0), e.x + e.x1 > a.x && (a.x = e.x + e.x1), e.y + e.y1 > a.y && (a.y = e.y + e.y1)
  276. }
  277. function c(t, e) {
  278. return t.x + t.x1 > e[0].x && t.x + t.x0 < e[1].x && t.y + t.y1 > e[0].y && t.y + t.y0 < e[1].y
  279. }
  280. function d(t) {
  281. var e = t[0] / t[1];
  282. return function (t) {
  283. return [e * (t *= .1) * Math.cos(t), t * Math.sin(t)]
  284. }
  285. }
  286. function h(t) {
  287. var e = 4,
  288. n = e * t[0] / t[1],
  289. a = 0,
  290. r = 0;
  291. return function (t) {
  292. var o = 0 > t ? -1 : 1;
  293. switch (Math.sqrt(1 + 4 * o * t) - o & 3) {
  294. case 0:
  295. a += n;
  296. break;
  297. case 1:
  298. r += e;
  299. break;
  300. case 2:
  301. a -= n;
  302. break;
  303. default:
  304. r -= e
  305. }
  306. return [a, r]
  307. }
  308. }
  309. function f(t) {
  310. for (var e = [], n = -1; ++n < t;) e[n] = 0;
  311. return e
  312. }
  313. var p, y = Math.PI / 180,
  314. g = 64,
  315. v = 2048,
  316. m = 1;
  317. if ("undefined" != typeof document) p = document.createElement("canvas"), p.width = 1, p.height = 1, m = Math.sqrt(p.getContext("2d").getImageData(0, 0, 1, 1).data.length >> 2), p.width = (g << 5) / m, p.height = v / m;
  318. else {
  319. var x = require("canvas");
  320. p = new x(g << 5, v)
  321. }
  322. var w = p.getContext("2d"),
  323. M = {
  324. archimedean: d,
  325. rectangular: h
  326. };
  327. w.fillStyle = "red", w.textAlign = "center", t.cloud = e
  328. }("undefined" == typeof exports ? d3.layout || (d3.layout = {}) : exports);
  329. var unicodePunctuationRe = "!-#%-*,-/:;?@\\[-\\]_{}\xa1\xa7\xab\xb6\xb7\xbb\xbf\u037e\u0387\u055a-\u055f\u0589\u058a\u05be\u05c0\u05c3\u05c6\u05f3\u05f4\u0609\u060a\u060c\u060d\u061b\u061e\u061f\u066a-\u066d\u06d4\u0700-\u070d\u07f7-\u07f9\u0830-\u083e\u085e\u0964\u0965\u0970\u0af0\u0df4\u0e4f\u0e5a\u0e5b\u0f04-\u0f12\u0f14\u0f3a-\u0f3d\u0f85\u0fd0-\u0fd4\u0fd9\u0fda\u104a-\u104f\u10fb\u1360-\u1368\u1400\u166d\u166e\u169b\u169c\u16eb-\u16ed\u1735\u1736\u17d4-\u17d6\u17d8-\u17da\u1800-\u180a\u1944\u1945\u1a1e\u1a1f\u1aa0-\u1aa6\u1aa8-\u1aad\u1b5a-\u1b60\u1bfc-\u1bff\u1c3b-\u1c3f\u1c7e\u1c7f\u1cc0-\u1cc7\u1cd3\u2010-\u2027\u2030-\u2043\u2045-\u2051\u2053-\u205e\u207d\u207e\u208d\u208e\u2329\u232a\u2768-\u2775\u27c5\u27c6\u27e6-\u27ef\u2983-\u2998\u29d8-\u29db\u29fc\u29fd\u2cf9-\u2cfc\u2cfe\u2cff\u2d70\u2e00-\u2e2e\u2e30-\u2e3b\u3001-\u3003\u3008-\u3011\u3014-\u301f\u3030\u303d\u30a0\u30fb\ua4fe\ua4ff\ua60d-\ua60f\ua673\ua67e\ua6f2-\ua6f7\ua874-\ua877\ua8ce\ua8cf\ua8f8-\ua8fa\ua92e\ua92f\ua95f\ua9c1-\ua9cd\ua9de\ua9df\uaa5c-\uaa5f\uaade\uaadf\uaaf0\uaaf1\uabeb\ufd3e\ufd3f\ufe10-\ufe19\ufe30-\ufe52\ufe54-\ufe61\ufe63\ufe68\ufe6a\ufe6b\uff01-\uff03\uff05-\uff0a\uff0c-\uff0f\uff1a\uff1b\uff1f\uff20\uff3b-\uff3d\uff3f\uff5b\uff5d\uff5f-\uff65",
  330. fill = d3.scale.category20b(),
  331. w = 960,
  332. h = 600,
  333. words = [],
  334. max, scale = 1,
  335. complete = 0,
  336. keyword = "",
  337. tags, fontSize, maxLength = 30,
  338. fetcher, statusText = d3.select("#status"),
  339. layout = d3.layout.cloud().timeInterval(10).size([w, h]).fontSize(function (t) {
  340. return fontSize(+t.value)
  341. }).text(function (t) {
  342. return t.key
  343. }).on("word", progress).on("end", draw),
  344. echoForm = d3.select("body").append("form").attr("action", "https://www.jasondavies.com/echo").attr("target", "_blank").attr("method", "POST"),
  345. echoContentType = echoForm.append("input").attr("type", "hidden").attr("name", "content-type"),
  346. echoInput = echoForm.append("input").attr("type", "hidden").attr("name", "echo"),
  347. svg = d3.select("#cloudDiv").append("svg").attr("width", w).attr("height", h),
  348. background = svg.append("g"),
  349. vis = svg.append("g").attr("transform", "translate(" + [w >> 1, h >> 1] + ")");
  350. d3.select("#download-svg").on("click", downloadSVG);
  351. var form = d3.select("#form").on("submit", function () {
  352. parseText(d3.select("#text").property("value")), d3.event.preventDefault()
  353. });
  354. form.selectAll("input[type=number]").on("click.refresh", function () {
  355. this.value !== this.defaultValue && (generate(), this.defaultValue = this.value)
  356. }), form.selectAll("input[type=text]").on("onchange", generate);
  357. var stopWords = /^(i|me|my|myself|we|us|our|ours|ourselves|you|your|yours|yourself|yourselves|he|him|his|himself|she|her|hers|herself|it|its|itself|they|them|their|theirs|themselves|what|which|who|whom|whose|this|that|these|those|am|is|are|was|were|be|been|being|have|has|had|having|do|does|did|doing|will|would|should|can|could|ought|i'm|you're|he's|she's|it's|we're|they're|i've|you've|we've|they've|i'd|you'd|he'd|she'd|we'd|they'd|i'll|you'll|he'll|she'll|we'll|they'll|isn't|aren't|wasn't|weren't|hasn't|haven't|hadn't|doesn't|don't|didn't|won't|wouldn't|shan't|shouldn't|can't|cannot|couldn't|mustn't|let's|that's|who's|what's|here's|there's|when's|where's|why's|how's|a|an|the|and|but|if|or|because|as|until|while|of|at|by|for|with|about|against|between|into|through|during|before|after|above|below|to|from|up|upon|down|in|out|on|off|over|under|again|further|then|once|here|there|when|where|why|how|all|any|both|each|few|more|most|other|some|such|no|nor|not|only|own|same|so|than|too|very|say|says|said|shall)$/,
  358. punctuation = new RegExp("[" + unicodePunctuationRe + "]", "g"),
  359. wordSeparators = /[ \f\n\r\t\v\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u2028\u2029\u202f\u205f\u3000\u3031-\u3035\u309b\u309c\u30a0\u30fc\uff70]+/g,
  360. discard = /^(@|https?:|\/\/)/,
  361. htmlTags = /(<[^>]*?>|<script.*?<\/script>|<style.*?<\/style>|<head.*?><\/head>)/g,
  362. matchTwitter = /^https?:\/\/([^\.]*\.)?twitter\.com/;
  363. d3.select("#random-palette").on("click", function () {
  364. paletteJSON("http://www.colourlovers.com/api/palettes/random", {}, function (t) {
  365. fill.range(t[0].colors), vis.selectAll("text").style("fill", function (t) {
  366. return fill(t.text.toLowerCase())
  367. })
  368. }), d3.event.preventDefault()
  369. }), function () {
  370. function t() {
  371. c = +d3.select("#angle-count").property("value"), u = Math.max(-90, Math.min(90, +d3.select("#angle-from").property("value"))), i = Math.max(-90, Math.min(90, +d3.select("#angle-to").property("value"))), e()
  372. }
  373. function e() {
  374. h.domain([0, c - 1]).range([u, i]);
  375. var t = l.selectAll("path.angle").data([{
  376. startAngle: u * d,
  377. endAngle: i * d
  378. }]);
  379. t.enter().insert("path", "circle").attr("class", "angle").style("fill", "#fc0"), t.attr("d", f);
  380. var o = l.selectAll("line.angle").data(d3.range(c).map(h));
  381. o.enter().append("line").attr("class", "angle"), o.exit().remove(), o.attr("transform", function (t) {
  382. return "rotate(" + (90 + t) + ")"
  383. }).attr("x2", function (t, e) {
  384. return e && e !== c - 1 ? -r : -r - 5
  385. });
  386. var s = l.selectAll("path.drag").data([u, i]);
  387. s.enter().append("path").attr("class", "drag").attr("d", "M-9.5,0L-3,3.5L-3,-3.5Z").call(d3.behavior.drag().on("drag", function (t, o) {
  388. t = (o ? i : u) + 90;
  389. var s = [-r * Math.cos(t * d), -r * Math.sin(t * d)],
  390. l = [d3.event.x, d3.event.y],
  391. c = ~~(Math.atan2(n(s, l), a(s, l)) / d);
  392. t = Math.max(-90, Math.min(90, t + c - 90)), c = i - u, o ? (i = t, c > 360 ? u += c - 360 : 0 > c && (u = i)) : (u = t, c > 360 ? i += 360 - c : 0 > c && (i = u)), e()
  393. }).on("dragend", generate)), s.attr("transform", function (t) {
  394. return "rotate(" + (t + 90) + ")translate(-" + r + ")"
  395. }), layout.rotate(function () {
  396. return h(~~(Math.random() * c))
  397. }), d3.select("#angle-count").property("value", c), d3.select("#angle-from").property("value", u), d3.select("#angle-to").property("value", i)
  398. }
  399. function n(t, e) {
  400. return t[0] * e[1] - t[1] * e[0]
  401. }
  402. function a(t, e) {
  403. return t[0] * e[0] + t[1] * e[1]
  404. }
  405. var r = 40.5,
  406. o = 35,
  407. s = 20,
  408. l = d3.select("#angles").append("svg").attr("width", 2 * (r + o)).attr("height", r + 1.5 * s).append("g").attr("transform", "translate(" + [r + o, r + s] + ")");
  409. l.append("path").style("fill", "none").attr("d", ["M", -r, 0, "A", r, r, 0, 0, 1, r, 0].join(" ")), l.append("line").attr("x1", -r - 7).attr("x2", r + 7), l.append("line").attr("y2", -r - 7), l.selectAll("text").data([-90, 0, 90]).enter().append("text").attr("dy", function (t, e) {
  410. return 1 === e ? null : ".3em"
  411. }).attr("text-anchor", function (t, e) {
  412. return ["end", "middle", "start"][e]
  413. }).attr("transform", function (t) {
  414. return t += 90, "rotate(" + t + ")translate(" + -(r + 10) + ")rotate(" + -t + ")translate(2)"
  415. }).text(function (t) {
  416. return t + "\xb0"
  417. });
  418. var u, i, c, d = Math.PI / 180,
  419. h = d3.scale.linear(),
  420. f = d3.svg.arc().innerRadius(0).outerRadius(r);
  421. d3.selectAll("#angle-count, #angle-from, #angle-to").on("change", t).on("mouseup", t),
  422. t(),
  423. parseText(d3.select("#text").property("value"))
  424. }();