From 3618b25735977c7dda126bba61c571fa94151650 Mon Sep 17 00:00:00 2001 From: mbclr3 Date: Sun, 24 May 2020 16:19:49 -0400 Subject: [PATCH 1/4] Added some dots --- package-lock.json | 10 +++ package.json | 2 + src/components/DarkModeSwitch.js | 4 +- src/components/Dots.js | 146 +++++++++++++++++++++++++++++++ src/pages/index.js | 4 +- 5 files changed, 164 insertions(+), 2 deletions(-) create mode 100644 src/components/Dots.js diff --git a/package-lock.json b/package-lock.json index f1a8c46..b028d9c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2966,6 +2966,11 @@ } } }, + "delaunator": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/delaunator/-/delaunator-4.0.1.tgz", + "integrity": "sha512-WNPWi1IRKZfCt/qIDMfERkDp93+iZEmOxN2yy4Jg+Xhv8SLk2UTqqbe1sfiipn0and9QrE914/ihdx82Y/Giag==" + }, "des.js": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.1.tgz", @@ -4218,6 +4223,11 @@ } } }, + "js-graph-algorithms": { + "version": "1.0.18", + "resolved": "https://registry.npmjs.org/js-graph-algorithms/-/js-graph-algorithms-1.0.18.tgz", + "integrity": "sha1-+W7Ie/GU9cCjE2X6Dh0Ht7li2JE=" + }, "js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", diff --git a/package.json b/package.json index f870f0e..04fd35c 100644 --- a/package.json +++ b/package.json @@ -11,7 +11,9 @@ "@chakra-ui/core": "^0.5.2", "@emotion/core": "^10.0.27", "@emotion/styled": "^10.0.27", + "delaunator": "^4.0.1", "emotion-theming": "^10.0.27", + "js-graph-algorithms": "^1.0.18", "next": "^9.1.7", "next-fonts": "^1.1.0", "react": "^16.12.0", diff --git a/src/components/DarkModeSwitch.js b/src/components/DarkModeSwitch.js index 22e773a..f944f4a 100644 --- a/src/components/DarkModeSwitch.js +++ b/src/components/DarkModeSwitch.js @@ -1,6 +1,6 @@ import { useColorMode, Switch } from '@chakra-ui/core'; -export const DarkModeSwitch = () => { +const DarkModeSwitch = () => { const { colorMode, toggleColorMode } = useColorMode(); const isDark = colorMode === 'dark'; return ( @@ -14,3 +14,5 @@ export const DarkModeSwitch = () => { /> ); }; + +export default DarkModeSwitch; diff --git a/src/components/Dots.js b/src/components/Dots.js new file mode 100644 index 0000000..b7acb39 --- /dev/null +++ b/src/components/Dots.js @@ -0,0 +1,146 @@ +import React, { useRef, useEffect } from 'react'; +import Delaunator from 'delaunator'; +import { WeightedGraph, Edge, KruskalMST } from 'js-graph-algorithms'; + +function pointInDonut(center, inRadius, outRadius) { + const r = Math.random() * (outRadius - inRadius) + inRadius; + const theta = Math.random() * Math.PI * 2; + return [center.x + r * Math.cos(theta), center.y + r * Math.sin(theta)]; +} + +function distance(p1, p2) { + return Math.hypot(p2[0] - p1[0], p2[1] - p1[1]); +} + +function pointsEqual(a, b) { + return a[0] === b[0] && a[1] === b[1]; +} + +function edgeSetContains(s, e) { + for (let i = 0; i < s.length; i++) { + const o = s[i]; + if ( + (o[0] === e[0] && o[1] === e[1]) || + (o[0] === e[1] && o[1] === e[0]) + ) { + return true; + } + } + return false; +} + +function drawCircle(ctx, location) { + const [x, y] = location; + ctx.fillStyle = 'black'; + ctx.beginPath(); + ctx.arc(x, y, 2, 0, 2 * Math.PI, true); + + ctx.fill(); +} + +function drawLine(ctx, from, to) { + ctx.beginPath(); + ctx.moveTo(from[0], from[1]); + ctx.lineTo(to[0], to[1]); + ctx.stroke(); +} + +function getMST(points, edges) { + const g = new WeightedGraph(points.length); + for (let i = 0; i < edges.length; i++) { + // console.log(edges[i][0]); + g.addEdge( + new Edge( + edges[i][0], + edges[i][1], + distance(points[edges[i][0]], points[edges[i][1]]), + ), + ); + } + console.log(g); + + const kruskal = new KruskalMST(g); + console.log(kruskal); + + return kruskal.mst; +} + +function maybe(e, p) { + if (Math.random() < p) e(); +} + +const Dots = () => { + const canvasRef = useRef(null); + let canvas, ctx; + useEffect(() => { + canvas = canvasRef.current; + ctx = canvas.getContext('2d'); + const { width, height } = canvas.getBoundingClientRect(); + ctx.clearRect(0, 0, width, height); + const points = []; + const NUM_POINTS = 500; + for (let i = 0; i < NUM_POINTS; i++) { + const point = pointInDonut( + { x: width / 2, y: height / 2 }, + 125, + 200, + ); + drawCircle(ctx, point); + points.push(point); + } + console.log(points); + const delaunay = Delaunator.from(points); + console.log(delaunay.triangles); + const triangles = delaunay.triangles; + const edgeSet = []; + const p = 0; + for (let i = 0; i < triangles.length; i += 3) { + for (let j = 0; j < 3; j++) { + const l = i; + const r = i + (j % 3); + if (!edgeSetContains(edgeSet, [triangles[l], triangles[r]])) { + if ( + distance(points[triangles[l]], points[triangles[r]]) < + 50 + ) { + maybe( + () => + drawLine( + ctx, + points[triangles[l]], + points[triangles[r]], + ), + p, + ); + } + edgeSet.push([triangles[l], triangles[r]]); + } + } + } + + console.log(edgeSet); + const mst = getMST(points, edgeSet); + for (let i = 0; i < mst.length; i++) { + const e = mst[i]; + // if (!edgeSetContains(edgeSet, [e.from(), e.to()])) + drawLine(ctx, points[e.from()], points[e.to()]); + } + }, [canvasRef.current]); + // ctx.fillStyle = 'blue'; + // ctx.fillRect(0, 0, canvas.width, canvas.height); + + return ( + { + const rect = canvas.getBoundingClientRect(); + drawCircle(ctx, [e.clientX - rect.x, e.clientY - rect.y]); + }} + /> + ); +}; + +export default Dots; diff --git a/src/pages/index.js b/src/pages/index.js index f9dc531..5c1dd3e 100644 --- a/src/pages/index.js +++ b/src/pages/index.js @@ -2,8 +2,9 @@ import Head from 'next/head'; import { withTheme } from 'emotion-theming'; import { Text, Stack, Image, Heading } from '@chakra-ui/core'; -import { DarkModeSwitch } from '../components/DarkModeSwitch'; +import DarkModeSwitch from '../components/DarkModeSwitch'; import SocialGrid from '../components/SocialGrid'; +import Dots from '../components/Dots'; const Index = () => ( <> @@ -28,6 +29,7 @@ const Index = () => ( Hey everyone, Miguel here! + ); From ffffef2ea30f76a7c63aa27331b1d68761a09bf2 Mon Sep 17 00:00:00 2001 From: mbclr3 Date: Sun, 24 May 2020 17:33:31 -0400 Subject: [PATCH 2/4] SVG is better than canvas --- package-lock.json | 282 ++++++++++++++++++++++++++++++++++++++++ package.json | 1 + src/components/Dots.js | 158 ++++++++++++---------- src/components/NoSSR.js | 8 ++ src/pages/index.js | 27 ++-- 5 files changed, 402 insertions(+), 74 deletions(-) create mode 100644 src/components/NoSSR.js diff --git a/package-lock.json b/package-lock.json index b028d9c..2967ff7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2900,6 +2900,270 @@ "type": "^1.0.1" } }, + "d3": { + "version": "5.16.0", + "resolved": "https://registry.npmjs.org/d3/-/d3-5.16.0.tgz", + "integrity": "sha512-4PL5hHaHwX4m7Zr1UapXW23apo6pexCgdetdJ5kTmADpG/7T9Gkxw0M0tf/pjoB63ezCCm0u5UaFYy2aMt0Mcw==", + "requires": { + "d3-array": "1", + "d3-axis": "1", + "d3-brush": "1", + "d3-chord": "1", + "d3-collection": "1", + "d3-color": "1", + "d3-contour": "1", + "d3-dispatch": "1", + "d3-drag": "1", + "d3-dsv": "1", + "d3-ease": "1", + "d3-fetch": "1", + "d3-force": "1", + "d3-format": "1", + "d3-geo": "1", + "d3-hierarchy": "1", + "d3-interpolate": "1", + "d3-path": "1", + "d3-polygon": "1", + "d3-quadtree": "1", + "d3-random": "1", + "d3-scale": "2", + "d3-scale-chromatic": "1", + "d3-selection": "1", + "d3-shape": "1", + "d3-time": "1", + "d3-time-format": "2", + "d3-timer": "1", + "d3-transition": "1", + "d3-voronoi": "1", + "d3-zoom": "1" + } + }, + "d3-array": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-1.2.4.tgz", + "integrity": "sha512-KHW6M86R+FUPYGb3R5XiYjXPq7VzwxZ22buHhAEVG5ztoEcZZMLov530mmccaqA1GghZArjQV46fuc8kUqhhHw==" + }, + "d3-axis": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/d3-axis/-/d3-axis-1.0.12.tgz", + "integrity": "sha512-ejINPfPSNdGFKEOAtnBtdkpr24c4d4jsei6Lg98mxf424ivoDP2956/5HDpIAtmHo85lqT4pruy+zEgvRUBqaQ==" + }, + "d3-brush": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/d3-brush/-/d3-brush-1.1.5.tgz", + "integrity": "sha512-rEaJ5gHlgLxXugWjIkolTA0OyMvw8UWU1imYXy1v642XyyswmI1ybKOv05Ft+ewq+TFmdliD3VuK0pRp1VT/5A==", + "requires": { + "d3-dispatch": "1", + "d3-drag": "1", + "d3-interpolate": "1", + "d3-selection": "1", + "d3-transition": "1" + } + }, + "d3-chord": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/d3-chord/-/d3-chord-1.0.6.tgz", + "integrity": "sha512-JXA2Dro1Fxw9rJe33Uv+Ckr5IrAa74TlfDEhE/jfLOaXegMQFQTAgAw9WnZL8+HxVBRXaRGCkrNU7pJeylRIuA==", + "requires": { + "d3-array": "1", + "d3-path": "1" + } + }, + "d3-collection": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/d3-collection/-/d3-collection-1.0.7.tgz", + "integrity": "sha512-ii0/r5f4sjKNTfh84Di+DpztYwqKhEyUlKoPrzUFfeSkWxjW49xU2QzO9qrPrNkpdI0XJkfzvmTu8V2Zylln6A==" + }, + "d3-color": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/d3-color/-/d3-color-1.4.1.tgz", + "integrity": "sha512-p2sTHSLCJI2QKunbGb7ocOh7DgTAn8IrLx21QRc/BSnodXM4sv6aLQlnfpvehFMLZEfBc6g9pH9SWQccFYfJ9Q==" + }, + "d3-contour": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/d3-contour/-/d3-contour-1.3.2.tgz", + "integrity": "sha512-hoPp4K/rJCu0ladiH6zmJUEz6+u3lgR+GSm/QdM2BBvDraU39Vr7YdDCicJcxP1z8i9B/2dJLgDC1NcvlF8WCg==", + "requires": { + "d3-array": "^1.1.1" + } + }, + "d3-dispatch": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/d3-dispatch/-/d3-dispatch-1.0.6.tgz", + "integrity": "sha512-fVjoElzjhCEy+Hbn8KygnmMS7Or0a9sI2UzGwoB7cCtvI1XpVN9GpoYlnb3xt2YV66oXYb1fLJ8GMvP4hdU1RA==" + }, + "d3-drag": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/d3-drag/-/d3-drag-1.2.5.tgz", + "integrity": "sha512-rD1ohlkKQwMZYkQlYVCrSFxsWPzI97+W+PaEIBNTMxRuxz9RF0Hi5nJWHGVJ3Om9d2fRTe1yOBINJyy/ahV95w==", + "requires": { + "d3-dispatch": "1", + "d3-selection": "1" + } + }, + "d3-dsv": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/d3-dsv/-/d3-dsv-1.2.0.tgz", + "integrity": "sha512-9yVlqvZcSOMhCYzniHE7EVUws7Fa1zgw+/EAV2BxJoG3ME19V6BQFBwI855XQDsxyOuG7NibqRMTtiF/Qup46g==", + "requires": { + "commander": "2", + "iconv-lite": "0.4", + "rw": "1" + } + }, + "d3-ease": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/d3-ease/-/d3-ease-1.0.6.tgz", + "integrity": "sha512-SZ/lVU7LRXafqp7XtIcBdxnWl8yyLpgOmzAk0mWBI9gXNzLDx5ybZgnRbH9dN/yY5tzVBqCQ9avltSnqVwessQ==" + }, + "d3-fetch": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/d3-fetch/-/d3-fetch-1.1.2.tgz", + "integrity": "sha512-S2loaQCV/ZeyTyIF2oP8D1K9Z4QizUzW7cWeAOAS4U88qOt3Ucf6GsmgthuYSdyB2HyEm4CeGvkQxWsmInsIVA==", + "requires": { + "d3-dsv": "1" + } + }, + "d3-force": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/d3-force/-/d3-force-1.2.1.tgz", + "integrity": "sha512-HHvehyaiUlVo5CxBJ0yF/xny4xoaxFxDnBXNvNcfW9adORGZfyNF1dj6DGLKyk4Yh3brP/1h3rnDzdIAwL08zg==", + "requires": { + "d3-collection": "1", + "d3-dispatch": "1", + "d3-quadtree": "1", + "d3-timer": "1" + } + }, + "d3-format": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/d3-format/-/d3-format-1.4.4.tgz", + "integrity": "sha512-TWks25e7t8/cqctxCmxpUuzZN11QxIA7YrMbram94zMQ0PXjE4LVIMe/f6a4+xxL8HQ3OsAFULOINQi1pE62Aw==" + }, + "d3-geo": { + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/d3-geo/-/d3-geo-1.12.0.tgz", + "integrity": "sha512-NalZVW+6/SpbKcnl+BCO67m8gX+nGeJdo6oGL9H6BRUGUL1e+AtPcP4vE4TwCQ/gl8y5KE7QvBzrLn+HsKIl+w==", + "requires": { + "d3-array": "1" + } + }, + "d3-hierarchy": { + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/d3-hierarchy/-/d3-hierarchy-1.1.9.tgz", + "integrity": "sha512-j8tPxlqh1srJHAtxfvOUwKNYJkQuBFdM1+JAUfq6xqH5eAqf93L7oG1NVqDa4CpFZNvnNKtCYEUC8KY9yEn9lQ==" + }, + "d3-interpolate": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-1.4.0.tgz", + "integrity": "sha512-V9znK0zc3jOPV4VD2zZn0sDhZU3WAE2bmlxdIwwQPPzPjvyLkd8B3JUVdS1IDUFDkWZ72c9qnv1GK2ZagTZ8EA==", + "requires": { + "d3-color": "1" + } + }, + "d3-path": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/d3-path/-/d3-path-1.0.9.tgz", + "integrity": "sha512-VLaYcn81dtHVTjEHd8B+pbe9yHWpXKZUC87PzoFmsFrJqgFwDe/qxfp5MlfsfM1V5E/iVt0MmEbWQ7FVIXh/bg==" + }, + "d3-polygon": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/d3-polygon/-/d3-polygon-1.0.6.tgz", + "integrity": "sha512-k+RF7WvI08PC8reEoXa/w2nSg5AUMTi+peBD9cmFc+0ixHfbs4QmxxkarVal1IkVkgxVuk9JSHhJURHiyHKAuQ==" + }, + "d3-quadtree": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/d3-quadtree/-/d3-quadtree-1.0.7.tgz", + "integrity": "sha512-RKPAeXnkC59IDGD0Wu5mANy0Q2V28L+fNe65pOCXVdVuTJS3WPKaJlFHer32Rbh9gIo9qMuJXio8ra4+YmIymA==" + }, + "d3-random": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/d3-random/-/d3-random-1.1.2.tgz", + "integrity": "sha512-6AK5BNpIFqP+cx/sreKzNjWbwZQCSUatxq+pPRmFIQaWuoD+NrbVWw7YWpHiXpCQ/NanKdtGDuB+VQcZDaEmYQ==" + }, + "d3-scale": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/d3-scale/-/d3-scale-2.2.2.tgz", + "integrity": "sha512-LbeEvGgIb8UMcAa0EATLNX0lelKWGYDQiPdHj+gLblGVhGLyNbaCn3EvrJf0A3Y/uOOU5aD6MTh5ZFCdEwGiCw==", + "requires": { + "d3-array": "^1.2.0", + "d3-collection": "1", + "d3-format": "1", + "d3-interpolate": "1", + "d3-time": "1", + "d3-time-format": "2" + } + }, + "d3-scale-chromatic": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/d3-scale-chromatic/-/d3-scale-chromatic-1.5.0.tgz", + "integrity": "sha512-ACcL46DYImpRFMBcpk9HhtIyC7bTBR4fNOPxwVSl0LfulDAwyiHyPOTqcDG1+t5d4P9W7t/2NAuWu59aKko/cg==", + "requires": { + "d3-color": "1", + "d3-interpolate": "1" + } + }, + "d3-selection": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/d3-selection/-/d3-selection-1.4.1.tgz", + "integrity": "sha512-BTIbRjv/m5rcVTfBs4AMBLKs4x8XaaLkwm28KWu9S2vKNqXkXt2AH2Qf0sdPZHjFxcWg/YL53zcqAz+3g4/7PA==" + }, + "d3-shape": { + "version": "1.3.7", + "resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-1.3.7.tgz", + "integrity": "sha512-EUkvKjqPFUAZyOlhY5gzCxCeI0Aep04LwIRpsZ/mLFelJiUfnK56jo5JMDSE7yyP2kLSb6LtF+S5chMk7uqPqw==", + "requires": { + "d3-path": "1" + } + }, + "d3-time": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/d3-time/-/d3-time-1.1.0.tgz", + "integrity": "sha512-Xh0isrZ5rPYYdqhAVk8VLnMEidhz5aP7htAADH6MfzgmmicPkTo8LhkLxci61/lCB7n7UmE3bN0leRt+qvkLxA==" + }, + "d3-time-format": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/d3-time-format/-/d3-time-format-2.2.3.tgz", + "integrity": "sha512-RAHNnD8+XvC4Zc4d2A56Uw0yJoM7bsvOlJR33bclxq399Rak/b9bhvu/InjxdWhPtkgU53JJcleJTGkNRnN6IA==", + "requires": { + "d3-time": "1" + } + }, + "d3-timer": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/d3-timer/-/d3-timer-1.0.10.tgz", + "integrity": "sha512-B1JDm0XDaQC+uvo4DT79H0XmBskgS3l6Ve+1SBCfxgmtIb1AVrPIoqd+nPSv+loMX8szQ0sVUhGngL7D5QPiXw==" + }, + "d3-transition": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/d3-transition/-/d3-transition-1.3.2.tgz", + "integrity": "sha512-sc0gRU4PFqZ47lPVHloMn9tlPcv8jxgOQg+0zjhfZXMQuvppjG6YuwdMBE0TuqCZjeJkLecku/l9R0JPcRhaDA==", + "requires": { + "d3-color": "1", + "d3-dispatch": "1", + "d3-ease": "1", + "d3-interpolate": "1", + "d3-selection": "^1.1.0", + "d3-timer": "1" + } + }, + "d3-voronoi": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/d3-voronoi/-/d3-voronoi-1.1.4.tgz", + "integrity": "sha512-dArJ32hchFsrQ8uMiTBLq256MpnZjeuBtdHpaDlYuQyjU0CVzCJl/BVW+SkszaAeH95D/8gxqAhgx0ouAWAfRg==" + }, + "d3-zoom": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/d3-zoom/-/d3-zoom-1.8.3.tgz", + "integrity": "sha512-VoLXTK4wvy1a0JpH2Il+F2CiOhVu7VRXWF5M/LroMIh3/zBAC3WAt7QoIvPibOavVo20hN6/37vwAsdBejLyKQ==", + "requires": { + "d3-dispatch": "1", + "d3-drag": "1", + "d3-interpolate": "1", + "d3-selection": "1", + "d3-transition": "1" + } + }, "data-uri-to-buffer": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-3.0.0.tgz", @@ -3928,6 +4192,14 @@ "resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-1.0.0.tgz", "integrity": "sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM=" }, + "iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, "icss-utils": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-4.1.1.tgz", @@ -6141,6 +6413,11 @@ "aproba": "^1.1.1" } }, + "rw": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/rw/-/rw-1.3.3.tgz", + "integrity": "sha1-P4Yt+pGrdmsUiF700BEkv9oHT7Q=" + }, "safe-buffer": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", @@ -6154,6 +6431,11 @@ "ret": "~0.1.10" } }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, "sass-loader": { "version": "8.0.2", "resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-8.0.2.tgz", diff --git a/package.json b/package.json index 04fd35c..d5465ab 100644 --- a/package.json +++ b/package.json @@ -11,6 +11,7 @@ "@chakra-ui/core": "^0.5.2", "@emotion/core": "^10.0.27", "@emotion/styled": "^10.0.27", + "d3": "^5.16.0", "delaunator": "^4.0.1", "emotion-theming": "^10.0.27", "js-graph-algorithms": "^1.0.18", diff --git a/src/components/Dots.js b/src/components/Dots.js index b7acb39..ea11122 100644 --- a/src/components/Dots.js +++ b/src/components/Dots.js @@ -1,6 +1,8 @@ -import React, { useRef, useEffect } from 'react'; +import React, { useRef, useState, useEffect } from 'react'; import Delaunator from 'delaunator'; import { WeightedGraph, Edge, KruskalMST } from 'js-graph-algorithms'; +import * as d3 from 'd3'; +import { Box, useTheme } from '@chakra-ui/core'; function pointInDonut(center, inRadius, outRadius) { const r = Math.random() * (outRadius - inRadius) + inRadius; @@ -68,78 +70,102 @@ function getMST(points, edges) { function maybe(e, p) { if (Math.random() < p) e(); } +function getPoints(n, inRadius, outRadius) { + const points = []; + for (let i = 0; i < n; i++) { + const point = pointInDonut({ x: 0, y: 0 }, inRadius, outRadius); + // drawCircle(ctx, point); + points.push(point); + } + console.log(points); + return points; +} -const Dots = () => { - const canvasRef = useRef(null); - let canvas, ctx; - useEffect(() => { - canvas = canvasRef.current; - ctx = canvas.getContext('2d'); - const { width, height } = canvas.getBoundingClientRect(); - ctx.clearRect(0, 0, width, height); - const points = []; - const NUM_POINTS = 500; - for (let i = 0; i < NUM_POINTS; i++) { - const point = pointInDonut( - { x: width / 2, y: height / 2 }, - 125, - 200, - ); - drawCircle(ctx, point); - points.push(point); - } - console.log(points); - const delaunay = Delaunator.from(points); - console.log(delaunay.triangles); - const triangles = delaunay.triangles; - const edgeSet = []; - const p = 0; - for (let i = 0; i < triangles.length; i += 3) { - for (let j = 0; j < 3; j++) { - const l = i; - const r = i + (j % 3); - if (!edgeSetContains(edgeSet, [triangles[l], triangles[r]])) { - if ( - distance(points[triangles[l]], points[triangles[r]]) < - 50 - ) { - maybe( - () => - drawLine( - ctx, - points[triangles[l]], - points[triangles[r]], - ), - p, - ); - } - edgeSet.push([triangles[l], triangles[r]]); - } +function getLines(points) { + const delaunay = Delaunator.from(points); + const triangles = delaunay.triangles; + const edgeSet = []; + const lines = []; + for (let i = 0; i < triangles.length; i += 3) { + for (let j = 0; j < 3; j++) { + const l = i; + const r = i + (j % 3); + if (!edgeSetContains(edgeSet, [triangles[l], triangles[r]])) { + // if (distance(points[triangles[l]], points[triangles[r]]) < 50) { + // maybe( + // () => + // drawLine( + // ctx, + // points[triangles[l]], + // points[triangles[r]], + // ), + // p, + // ); + // } + edgeSet.push([triangles[l], triangles[r]]); } } + } + console.log(edgeSet); + const mst = getMST(points, edgeSet); + for (let i = 0; i < mst.length; i++) { + const e = mst[i]; + // if (!edgeSetContains(edgeSet, [e.from(), e.to()])) + // drawLine(ctx, points[e.from()], points[e.to()]); + lines.push({ from: points[e.from()], to: points[e.to()] }); + } + return lines; +} - console.log(edgeSet); - const mst = getMST(points, edgeSet); - for (let i = 0; i < mst.length; i++) { - const e = mst[i]; - // if (!edgeSetContains(edgeSet, [e.from(), e.to()])) - drawLine(ctx, points[e.from()], points[e.to()]); - } - }, [canvasRef.current]); - // ctx.fillStyle = 'blue'; - // ctx.fillRect(0, 0, canvas.width, canvas.height); +function convertRemToPixels(rem) { + return ( + rem * parseFloat(getComputedStyle(document.documentElement).fontSize) + ); +} + +const Dots = () => { + const theme = useTheme(); + const svgRef = useRef(); + const NUM_POINTS = 300; + const [elem] = useState( + (() => { + const points = getPoints(NUM_POINTS, 132, 200); + const lines = getLines(points); + console.log(lines); + return { points, lines }; + })(), + ); + + const size = convertRemToPixels(theme.sizes['sm'].replace('rem', '')); return ( - { - const rect = canvas.getBoundingClientRect(); - drawCircle(ctx, [e.clientX - rect.x, e.clientY - rect.y]); - }} - /> + ref={svgRef} + height={size} + width={size} + viewBox={`${-size / 2} ${-size / 2} ${size} ${size}`} + overflow="visible"> + {elem.lines.map((line, i) => ( + + ))} + {elem.points.map(([x, y], i) => ( + + ))} + ); }; diff --git a/src/components/NoSSR.js b/src/components/NoSSR.js new file mode 100644 index 0000000..f0a3c86 --- /dev/null +++ b/src/components/NoSSR.js @@ -0,0 +1,8 @@ +import dynamic from 'next/dynamic'; +import React from 'react'; + +const NoSSR = (props) => <>{props.children}; + +export default dynamic(() => Promise.resolve(NoSSR), { + ssr: false, +}); diff --git a/src/pages/index.js b/src/pages/index.js index 5c1dd3e..89deb65 100644 --- a/src/pages/index.js +++ b/src/pages/index.js @@ -1,10 +1,11 @@ import Head from 'next/head'; import { withTheme } from 'emotion-theming'; -import { Text, Stack, Image, Heading } from '@chakra-ui/core'; +import { Text, Stack, Image, Heading, Box } from '@chakra-ui/core'; import DarkModeSwitch from '../components/DarkModeSwitch'; import SocialGrid from '../components/SocialGrid'; import Dots from '../components/Dots'; +import NoSSR from '../components/NoSSR'; const Index = () => ( <> @@ -19,17 +20,27 @@ const Index = () => ( alignItems="center" justifyContent="center"> Miguel de los Reyes - Miguel de los Reyes + + + + + Miguel de los Reyes + Hey everyone, Miguel here! - ); From 60a9f7618e18cfb468323511d21da635e2508cf0 Mon Sep 17 00:00:00 2001 From: mbclr3 Date: Sun, 24 May 2020 18:11:28 -0400 Subject: [PATCH 3/4] Fix theming --- src/components/Dots.js | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/components/Dots.js b/src/components/Dots.js index ea11122..2afd8bd 100644 --- a/src/components/Dots.js +++ b/src/components/Dots.js @@ -2,7 +2,7 @@ import React, { useRef, useState, useEffect } from 'react'; import Delaunator from 'delaunator'; import { WeightedGraph, Edge, KruskalMST } from 'js-graph-algorithms'; import * as d3 from 'd3'; -import { Box, useTheme } from '@chakra-ui/core'; +import { Box, useTheme, useColorMode } from '@chakra-ui/core'; function pointInDonut(center, inRadius, outRadius) { const r = Math.random() * (outRadius - inRadius) + inRadius; @@ -125,6 +125,12 @@ function convertRemToPixels(rem) { const Dots = () => { const theme = useTheme(); + const { colorMode } = useColorMode(); + const lineColor = { + light: theme.colors.green[200], + dark: theme.colors.green[900], + }; + const dotColor = { light: theme.colors.green[900], dark: 'white' }; const svgRef = useRef(); const NUM_POINTS = 300; const [elem] = useState( @@ -144,6 +150,7 @@ const Dots = () => { ref={svgRef} height={size} width={size} + style={{ zIndex: -1 }} viewBox={`${-size / 2} ${-size / 2} ${size} ${size}`} overflow="visible"> {elem.lines.map((line, i) => ( @@ -153,7 +160,7 @@ const Dots = () => { x2={line.to[0]} y2={line.to[1]} key={i} - style={{ stroke: theme.colors.green[200], strokeWidth: 1 }} + style={{ stroke: lineColor[colorMode], strokeWidth: 1 }} /> ))} {elem.points.map(([x, y], i) => ( @@ -161,7 +168,7 @@ const Dots = () => { cx={x} cy={y} r={1} - fill={theme.colors.green[900]} + fill={dotColor[colorMode]} key={i} /> ))} From 552ecf5bbc3dde938dd85694203e691e39683990 Mon Sep 17 00:00:00 2001 From: mbclr3 Date: Sun, 24 May 2020 18:35:41 -0400 Subject: [PATCH 4/4] Maybe lines are better --- src/components/Dots.js | 46 +++++++++++++++++++++++------------------- src/pages/index.js | 2 +- 2 files changed, 26 insertions(+), 22 deletions(-) diff --git a/src/components/Dots.js b/src/components/Dots.js index 2afd8bd..49c4a25 100644 --- a/src/components/Dots.js +++ b/src/components/Dots.js @@ -91,17 +91,14 @@ function getLines(points) { const l = i; const r = i + (j % 3); if (!edgeSetContains(edgeSet, [triangles[l], triangles[r]])) { - // if (distance(points[triangles[l]], points[triangles[r]]) < 50) { - // maybe( - // () => - // drawLine( - // ctx, - // points[triangles[l]], - // points[triangles[r]], - // ), - // p, - // ); - // } + if ( + distance(points[triangles[l]], points[triangles[r]]) < 150 + ) { + lines.push({ + from: points[triangles[l]], + to: points[triangles[r]], + }); + } edgeSet.push([triangles[l], triangles[r]]); } } @@ -112,7 +109,7 @@ function getLines(points) { const e = mst[i]; // if (!edgeSetContains(edgeSet, [e.from(), e.to()])) // drawLine(ctx, points[e.from()], points[e.to()]); - lines.push({ from: points[e.from()], to: points[e.to()] }); + // lines.push({ from: points[e.from()], to: points[e.to()] }); } return lines; } @@ -127,23 +124,26 @@ const Dots = () => { const theme = useTheme(); const { colorMode } = useColorMode(); const lineColor = { - light: theme.colors.green[200], + light: theme.colors.green[100], dark: theme.colors.green[900], }; const dotColor = { light: theme.colors.green[900], dark: 'white' }; const svgRef = useRef(); - const NUM_POINTS = 300; + + const size = convertRemToPixels(theme.sizes['2xs'].replace('rem', '')); + const NUM_POINTS = 1000; + const IN_RADIUS = size / 2 + 7; + console.log(IN_RADIUS); + const OUT_RADIUS = 700; const [elem] = useState( (() => { - const points = getPoints(NUM_POINTS, 132, 200); + const points = getPoints(NUM_POINTS, IN_RADIUS, OUT_RADIUS); const lines = getLines(points); console.log(lines); return { points, lines }; })(), ); - const size = convertRemToPixels(theme.sizes['sm'].replace('rem', '')); - return ( { x2={line.to[0]} y2={line.to[1]} key={i} - style={{ stroke: lineColor[colorMode], strokeWidth: 1 }} + style={{ + stroke: lineColor[colorMode], + strokeWidth: 2, + strokeLinecap: 'round', + }} /> ))} - {elem.points.map(([x, y], i) => ( + {/* {elem.points.map(([x, y], i) => ( - ))} + ))} */} ); }; diff --git a/src/pages/index.js b/src/pages/index.js index 89deb65..b166e1c 100644 --- a/src/pages/index.js +++ b/src/pages/index.js @@ -22,7 +22,7 @@ const Index = () => ( Miguel de los Reyes