{"id":"4ea5a8baf16be8b9","slug":"eyes","first_public_version":498,"paused_version":null,"likes":24,"publish_level":"live","forks":4,"fork_of":{"id":"29d10840f83e2527","slug":"cheery-logo","title":"Cheery Logo","owner":{"id":"f35c755083683fe5","avatar_url":"https://avatars.observableusercontent.com/avatar/5a51c3b908225a581d20577e488e2aba8cbc9541c52982c638638c370c3e5e8e","login":"observablehq","name":"Observable","bio":"The end-to-end solution for building and hosting better data apps, dashboards, and reports.","home_url":"https://observablehq.com","type":"team","tier":"enterprise_2024"},"version":370},"has_importers":true,"thumbnail":"91c51f33d056927871cd6dfe5a1d790487704f55fcc9517e39826209e6275b5e","default_thumbnail":"91c51f33d056927871cd6dfe5a1d790487704f55fcc9517e39826209e6275b5e","update_time":"2018-07-31T15:28:24.516Z","publish_time":"2023-01-08T18:19:47.893Z","publish_version":506,"latest_version":506,"roles":[],"sharing":null,"owner":{"id":"8c2e47252fd4995c","avatar_url":"https://avatars.observableusercontent.com/avatar/82811927da99f8938001b2ef1f552ad2c47083e46ebc55a3a146a5a5848c4519","login":"mbostock","name":"Mike Bostock","bio":"Visualization toolmaker. Founder @observablehq. Creator @d3. Former @nytgraphics. Pronounced BOSS-tock.","home_url":"https://bost.ocks.org/mike/","type":"team","tier":"starter_2024"},"creator":{"id":"074c414ad1d825f5","avatar_url":"https://avatars.observableusercontent.com/avatar/82811927da99f8938001b2ef1f552ad2c47083e46ebc55a3a146a5a5848c4519","login":"mbostock","name":"Mike Bostock","bio":"Visualization toolmaker. Founder @observablehq. Creator @d3. Former @nytgraphics. Pronounced BOSS-tock.","home_url":"https://bost.ocks.org/mike/","tier":"pro"},"authors":[{"id":"074c414ad1d825f5","avatar_url":"https://avatars.observableusercontent.com/avatar/82811927da99f8938001b2ef1f552ad2c47083e46ebc55a3a146a5a5848c4519","name":"Mike Bostock","login":"mbostock","bio":"Visualization toolmaker. Founder @observablehq. Creator @d3. Former @nytgraphics. Pronounced BOSS-tock.","home_url":"https://bost.ocks.org/mike/","tier":"pro","approved":true,"description":""}],"files":[],"comments":[],"commenting_lock":null,"suggestions_to":[],"suggestion_from":null,"collections":[{"id":"4eb71736476d8aab","type":"public","slug":"generative-art","title":"Generative art","description":"Brand new and recreated vintage art, made with code and imagination.","update_time":"2018-09-13T19:54:26.018Z","pinned":false,"ordered":false,"custom_thumbnail":"7b32d6824dc1128f6b83353df993cde146633d12a60fcd046b16eda600f92679","default_thumbnail":"39cb24c6f01580f928304736d2de4a18772b22bec0ac026c1967144f3575144c","thumbnail":"7b32d6824dc1128f6b83353df993cde146633d12a60fcd046b16eda600f92679","listing_count":40,"parent_collection_count":0,"owner":{"id":"f35c755083683fe5","avatar_url":"https://avatars.observableusercontent.com/avatar/5a51c3b908225a581d20577e488e2aba8cbc9541c52982c638638c370c3e5e8e","login":"observablehq","name":"Observable","bio":"The end-to-end solution for building and hosting better data apps, dashboards, and reports.","home_url":"https://observablehq.com","type":"team","tier":"enterprise_2024"}}],"version":489,"title":"Eyes","license":null,"copyright":"","nodes":[{"id":0,"value":"md`# Eyes\n\nA colorful take on Processing’s [Arctangent example](https://processing.org/examples/arctangent.html).`","pinned":false,"mode":"js","data":null,"name":null},{"id":2,"value":"canvas = {\n  const context = DOM.context2d(width, height);\n  context.canvas.style.width = \"100%\";\n  context.canvas.style.height = \"auto\";\n  context.canvas.update = mouse => {\n    let {left: cx, top: cy} = context.canvas.getBoundingClientRect();\n    let {x: mx, y: my} = mouse;\n    mx -= cx;\n    my -= cy;\n    context.clearRect(0, 0, width, height);\n    for (let i = 0, n = circles.length; i < n; ++i) {\n      const {x, y, r} = circles[i];\n      context.save();\n      context.translate(x, y);\n      context.beginPath();\n      context.arc(0, 0, r, 0, 2 * Math.PI);\n      context.fillStyle = d3.schemePastel2[i % 8];\n      context.fill();\n      const dx = mx - x, dy = my - y, l = Math.sqrt(dx ** 2 + dy ** 2);\n      context.beginPath();\n      if (l < r * 2 / 3) context.arc(dx, dy, r / 3, 0, 2 * Math.PI);\n      else context.arc(dx / l * r * 2 / 3, dy / l * r * 2 / 3, r / 3, 0, 2 * Math.PI);\n      context.fillStyle = \"#333\";\n      context.fill();\n      context.restore();\n    }\n  };\n  return context.canvas;\n}","pinned":false,"mode":"js","data":null,"name":null},{"id":429,"value":"mouse = Generators.observe(notify => {\n  const update = mouse => (canvas.update(mouse), notify(mouse));\n  const moved = event => update({x: event.clientX, y: event.clientY});\n  window.addEventListener(\"mousemove\", moved);\n  update({x: window.innerWidth / 2, y: window.innerHeight / 2});\n  return () => window.removeEventListener(\"mousemove\", moved);\n})","pinned":false,"mode":"js","data":null,"name":null},{"id":402,"value":"height = 600","pinned":false,"mode":"js","data":null,"name":null},{"id":131,"value":"padding = 3","pinned":false,"mode":"js","data":null,"name":null},{"id":354,"value":"random = d3.randomUniform(padding + 5, padding + 100)","pinned":false,"mode":"js","data":null,"name":null},{"id":80,"value":"circles = {\n  const radii = d3.range(100).map(random);\n  const circles = d3.packSiblings(radii.map(r => ({r})));\n  for (const circle of circles) {\n    circle.x += width / 2;\n    circle.y += height / 2;\n    circle.r -= padding;\n  }\n  return circles;\n}","pinned":false,"mode":"js","data":null,"name":null},{"id":6,"value":"d3 = require(\"d3@5\")","pinned":false,"mode":"js","data":null,"name":null}],"resolutions":[],"schedule":null,"last_view_time":null}