11import * as React from 'react'
22import styled from 'styled-components'
3+ import Shapes from './Shapes'
4+ import { backgroundColor } from '..'
5+ import { seededRandom } from '../../../utils'
36
4- const Container = styled . div `
7+ const Container = styled . div < { color : string } > `
58 height: 100vh;
69 width: 100vw;
710 overflow: hidden;
11+ background-color: ${ ( { color } ) => color } ;
812`
913const Row = styled . div `
1014 white-space: nowrap;
@@ -13,77 +17,44 @@ const SvgWrapper = styled.div`
1317 & svg {
1418 margin-bottom: -4px;
1519 margin-top: 1px;
16-
1720 }
1821`
1922
20- function lines (
21- backgroundSize : number ,
22- fill : string ,
23- rotation : number ,
24- rotationCenter : number
25- ) : string [ ] {
26- return [
27- `<svg xmlns="http://www.w3.org/2000/svg" version="1.1" viewBox="0 0 400 400" height="${ backgroundSize } " width="${ backgroundSize } ">
28- <g transform="rotate(${ rotation } , ${ rotationCenter } , ${ rotationCenter } )">
29- <path d="M12 5 H395 V388 Z" fill="${ fill } "/>
30- <path d="M5 12 V395 H388 Z" fill="${ fill } "/>
31- </g>
32- </svg>` ,
33- `<svg xmlns="http://www.w3.org/2000/svg" version="1.1" viewBox="0 0 400 400" height="${ backgroundSize } " width="${ backgroundSize } ">
34- <g transform="rotate(${ rotation } , ${ rotationCenter } , ${ rotationCenter } )">
35- <path d="M5 188 V5 H388 Z" fill="${ fill } "/>
36- <path d="M8.5 200 L395 12 V388 Z" fill="${ fill } "/>
37- <path d="M5 212 V395 H388 Z" fill="${ fill } "/>
38- </g></svg>` ,
39- `<svg xmlns="http://www.w3.org/2000/svg" version="1.1" viewBox="0 0 400 400" height="${ backgroundSize } " width="${ backgroundSize } "><g transform="rotate(${ rotation } , ${ rotationCenter } , ${ rotationCenter } )"> <path d="M5 188 V5 H388 Z" fill="${ fill } "/>
40- <path d="M12 195 H395 V12 Z" fill="${ fill } "/>
41- <path d="M12 205 H395 V388 Z" fill="${ fill } "/>
42- <path d="M5 212 V395 H388 Z" fill="${ fill } "/>
43- </g></svg>` ,
44- `<svg xmlns="http://www.w3.org/2000/svg" version="1.1" viewBox="0 0 400 400" height="${ backgroundSize } " width="${ backgroundSize } "><g transform="rotate(${ rotation } , ${ rotationCenter } , ${ rotationCenter } )"> <path d="M12 5 H395 V188 Z" fill="${ fill } "/>
45- <path d="M5 12 V195 H388 Z" fill="${ fill } "/>
46- <path d="M12 205 H395 V388 Z" fill="${ fill } "/>
47- <path d="M5 212 V395 H388 Z" fill="${ fill } "/>
48- </g></svg>` ,
49- `<svg xmlns="http://www.w3.org/2000/svg" version="1.1" viewBox="0 0 400 400" height="${ backgroundSize } " width="${ backgroundSize } "><g transform="rotate(${ rotation } , ${ rotationCenter } , ${ rotationCenter } )"> <path d="M5 5 V395 h90 V5 Z" fill="${ fill } "/>
50- <path d="M105 5 V395 h90 V5 Z" fill="${ fill } "/>
51- <path d="M205 5 V395 h90 V5 Z" fill="${ fill } "/>
52- <path d="M305 5 V395 h90 V5 Z" fill="${ fill } "/>
53- </g></svg>` ,
54- `<svg xmlns="http://www.w3.org/2000/svg" version="1.1" viewBox="0 0 400 400" height="${ backgroundSize } " width="${ backgroundSize } "><g transform="rotate(${ rotation } , ${ rotationCenter } , ${ rotationCenter } )"> <path d="M5 5 V395 h123.3 V5 Z" fill="${ fill } "/>
55- <path d="M138.3 5 V395 h123.3 V5 Z" fill="${ fill } "/>
56- <path d="M271.6 5 V395 h123.3 V5 Z" fill="${ fill } "/>
57- </g></svg>` ,
58- `<svg xmlns="http://www.w3.org/2000/svg" version="1.1" viewBox="0 0 400 400" height="${ backgroundSize } " width="${ backgroundSize } "><g transform="rotate(${ rotation } , ${ rotationCenter } , ${ rotationCenter } )"> <path d="M5 5 V395 h190 V5 Z" fill="${ fill } "/>
59- <path d="M205 5 V395 h190 V5 Z" fill="${ fill } "/>
60- </g></svg>` ,
61- ]
62- }
63-
6423interface Props {
6524 rotationCenter : number
6625 rotationGranularity : number
6726 color : string
6827}
6928
29+ interface Indices {
30+ shape : number
31+ rotation : number
32+ }
33+
7034const TILE_SIZE = 70
7135
72- function getGridSize ( width : number , height : number ) {
36+ const getGridSize = ( width : number , height : number ) => {
7337 return {
7438 rows : Math . ceil ( height / TILE_SIZE ) ,
7539 cols : Math . ceil ( width / TILE_SIZE ) ,
7640 }
7741}
7842
79- function seededRandom ( seed : number ) {
80- // Mulberry32 PRNG
81- return function ( ) {
82- let t = ( seed += 0x6d2b79f5 )
83- t = Math . imul ( t ^ ( t >>> 15 ) , t | 1 )
84- t ^= t + Math . imul ( t ^ ( t >>> 7 ) , t | 61 )
85- return ( ( t ^ ( t >>> 14 ) ) >>> 0 ) / 4294967296
86- }
43+ const getIndices = ( rows : number , cols : number , rotationGranularity : number ) => {
44+ const indices : Indices [ ] [ ] = [ ]
45+ for ( let i = 0 ; i < rows ; i ++ ) {
46+ indices [ i ] = [ ]
47+ const rand = seededRandom ( 41 * i + 1 )
48+ for ( let j = 0 ; j < cols ; j ++ ) {
49+ indices [ i ] [ j ] = {
50+ shape : Math . floor ( rand ( ) * Shapes . length ) ,
51+ rotation :
52+ Math . floor ( rand ( ) * rotationGranularity ) *
53+ ( 360 / rotationGranularity ) ,
54+ }
55+ }
56+ }
57+ return indices ;
8758}
8859
8960const Tiler : React . FC < Props > = ( {
@@ -92,12 +63,10 @@ const Tiler: React.FC<Props> = ({
9263 color,
9364} ) => {
9465 const [ dimensions , setDimensions ] = React . useState ( {
95- width : 100 ,
96- height : 100 ,
66+ width : 1000 ,
67+ height : 1000 ,
9768 } )
98-
99- // Store the shape/rotation indices for each tile
100- const [ tileIndices , setTileIndices ] = React . useState < number [ ] [ ] | null > ( null )
69+ const [ tileIndices , setTileIndices ] = React . useState < Indices [ ] [ ] | null > ( null )
10170
10271 React . useEffect ( ( ) => {
10372 function updateDimensions ( ) {
@@ -112,52 +81,36 @@ const Tiler: React.FC<Props> = ({
11281 } , [ ] )
11382
11483 React . useEffect ( ( ) => {
115- // Precompute indices for shapes and rotations
11684 const { rows, cols } = getGridSize ( dimensions . width , dimensions . height )
117- // Use a seed based on dimensions to keep it stable between renders
118- const seed = dimensions . width * 100000 + dimensions . height
119- const rand = seededRandom ( seed )
120- const shapeIndices : number [ ] [ ] = [ ]
121- for ( let i = 0 ; i < rows ; i ++ ) {
122- shapeIndices [ i ] = [ ]
123- for ( let j = 0 ; j < cols ; j ++ ) {
124- shapeIndices [ i ] [ j ] = Math . floor ( rand ( ) * lines ( 0 , '' , 0 , 0 ) . length )
125- }
126- }
127- setTileIndices ( shapeIndices )
128- } , [ dimensions . width , dimensions . height ] )
129-
130- const { rows, cols } = getGridSize ( dimensions . width , dimensions . height )
85+ setTileIndices ( getIndices ( rows , cols , rotationGranularity ) )
86+ } , [ dimensions . width , dimensions . height , rotationGranularity ] )
13187
132- // Ensure tileIndices and rotationIndices are initialized and match the current grid size
133- if (
134- ! tileIndices ||
135- tileIndices . length !== rows ||
136- tileIndices . some ( rowArr => rowArr . length !== cols )
137- ) {
138- return null
139- }
140-
141- const lineArray : JSX . Element [ ] = [ ]
142- for ( let i = 0 ; i < rows ; i ++ ) {
143- let row = ''
144- for ( let j = 0 ; j < cols ; j ++ ) {
145- const rotation = Math . floor ( Math . random ( ) * rotationGranularity ) * ( 360 / rotationGranularity )
146- const shapes = lines ( TILE_SIZE , '#1a1a2e' , rotation , rotationCenter )
147- row += shapes [ tileIndices [ i ] [ j ] ]
148- }
149- lineArray . push (
150- < Row
151- key = { i }
152- style = { { backgroundColor : color } }
153- dangerouslySetInnerHTML = { { __html : row } }
154- />
155- )
88+ if ( ! tileIndices ) {
89+ return < Container color = { backgroundColor } />
15690 }
15791
15892 return (
159- < Container >
160- < SvgWrapper > { lineArray } </ SvgWrapper >
93+ < Container color = { color } >
94+ < SvgWrapper >
95+ { tileIndices . map ( ( row , i ) => {
96+ return (
97+ < Row key = { i } >
98+ { row . map ( ( tile , j ) => {
99+ const Shape = Shapes [ tile . shape ]
100+ return (
101+ < Shape
102+ key = { `${ i } -${ j } ` }
103+ backgroundSize = { TILE_SIZE }
104+ fill = { backgroundColor }
105+ rotation = { tile . rotation }
106+ rotationCenter = { rotationCenter }
107+ />
108+ )
109+ } ) }
110+ </ Row >
111+ )
112+ } ) }
113+ </ SvgWrapper >
161114 </ Container >
162115 )
163116}
0 commit comments