Created
November 14, 2022 21:47
-
-
Save thisiscarlosgomes/11745164a088542f0af32486e3b3e3cc to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* eslint-disable jsx-a11y/anchor-is-valid */ | |
import React, { useEffect, useRef, useState } from 'react'; | |
import useInterval from '@use-it/interval'; | |
// Constants | |
const VALID_CHARS = `proliferating creative collection forefront dao tokenized community digital vibe!&@#~~@#(*:"?>)`; | |
const STREAM_MUTATION_ODDS = 2; | |
const MIN_STREAM_SIZE = 5; | |
const MAX_STREAM_SIZE = 40; | |
const MIN_INTERVAL_DELAY = 100; | |
const MAX_INTERVAL_DELAY = 200; | |
const MIN_DELAY_BETWEEN_STREAMS = 0; | |
const MAX_DELAY_BETWEEN_STREAMS = 12000; | |
const getRandInRange = (min, max) => | |
Math.floor(Math.random() * (max - min)) + min; | |
const getRandChar = () => | |
VALID_CHARS.charAt(Math.floor(Math.random() * VALID_CHARS.length)); | |
const getRandStream = () => | |
new Array(getRandInRange(MIN_STREAM_SIZE, MAX_STREAM_SIZE)) | |
.fill() | |
.map(_ => getRandChar()); | |
const getMutatedStream = stream => { | |
const newStream = []; | |
for (let i = 1; i < stream.length; i++) { | |
if (Math.random() < STREAM_MUTATION_ODDS) { | |
newStream.push(getRandChar()); | |
} else { | |
newStream.push(stream[i]); | |
} | |
} | |
newStream.push(getRandChar()); | |
return newStream; | |
}; | |
const RainStream = props => { | |
const [stream, setStream] = useState(getRandStream()); | |
const [topPadding, setTopPadding] = useState(stream.length * -20); | |
const [leftPadding, setLeftPadding] = useState(stream.length * -10); | |
const [intervalDelay, setIntervalDelay] = useState(null); | |
// Initialize intervalDelay | |
useEffect(() => { | |
setTimeout(() => { | |
setIntervalDelay(getRandInRange(MIN_INTERVAL_DELAY, MAX_INTERVAL_DELAY)); | |
}, getRandInRange(MIN_DELAY_BETWEEN_STREAMS, MAX_DELAY_BETWEEN_STREAMS)); | |
}, []); | |
useInterval(() => { | |
if (!props.height) return; | |
if (!intervalDelay) return; | |
// If stream is off the screen, reset it after timeout | |
if (topPadding > props.height) { | |
setStream([]); | |
const newStream = getRandStream(); | |
setStream(newStream); | |
setTopPadding(newStream.length * -44); | |
setIntervalDelay(null); | |
setTimeout( | |
() => | |
setIntervalDelay( | |
getRandInRange(MIN_INTERVAL_DELAY, MAX_INTERVAL_DELAY), | |
), | |
getRandInRange(MIN_DELAY_BETWEEN_STREAMS, MAX_DELAY_BETWEEN_STREAMS), | |
); | |
} else { | |
setTopPadding(topPadding + 32); | |
} | |
// setStream(stream => [...stream.slice(1, stream.length), getRandChar()]); | |
setStream(getMutatedStream); | |
}, intervalDelay); | |
return ( | |
<div | |
style={{ | |
fontFamily: 'matrixFont', | |
color: '#000', | |
writingMode: 'vertical-rl', | |
textOrientation: 'upright', | |
userSelect: 'none', | |
whiteSpace: 'nowrap', | |
marginLeft: leftPadding, | |
marginLeft: -13, | |
marginRight: -12, | |
fontSize: 12, | |
}}> | |
{stream.map((char, index) => ( | |
<a | |
style={{ | |
marginTop: -2, | |
// Reduce opacity for last charslet ourSubstring = "Example";stream.includes("c") | |
opacity: index < 6 ? 0.1 + index * 0.2 : 1, | |
color: index === stream.length - 1 ? '#151BFF' : undefined, | |
}}> | |
{char} | |
</a> | |
))} | |
</div> | |
); | |
}; | |
const MatrixRain = props => { | |
const containerRef = useRef(null); | |
const [containerSize, setContainerSize] = useState(null); // ?{width, height} | |
useEffect(() => { | |
const boundingClientRect = containerRef.current.getBoundingClientRect(); | |
setContainerSize({ | |
width: boundingClientRect.width, | |
height: boundingClientRect.height, | |
}); | |
}, []); | |
const streamCount = containerSize ? Math.floor(containerSize.width / 12) : 0; | |
return ( | |
<div | |
style={{ | |
background: '#f5f5f5', | |
position: 'fixed', | |
top: 0, | |
left: 0, | |
display: 'flex', | |
flexDirection: 'row', | |
justifyContent: 'center', | |
inset:'1', | |
width:'500px', | |
height:'auto', | |
}} | |
ref={containerRef}> | |
{new Array(streamCount).fill().map(_ => ( | |
<RainStream height={containerSize?.height} /> | |
))} | |
</div> | |
); | |
}; | |
export default MatrixRain; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment