Skip to content

Commit

Permalink
Added controls
Browse files Browse the repository at this point in the history
  • Loading branch information
dkreft committed Nov 13, 2022
1 parent eed3ebb commit 20f3e24
Show file tree
Hide file tree
Showing 7 changed files with 156 additions and 29 deletions.
43 changes: 41 additions & 2 deletions src/components/App/App.jsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,54 @@
import React from 'react'
import React, {
useCallback,
useState,
} from 'react'

import PropTypes from 'prop-types'

import Controls from './Controls'
import Fractal from './Fractal'

import Styles from './styles.module.sass'

const PARAMS = new URLSearchParams(window.location.search)

const DIRECTION = 0
const LENGTH = 500
const LIMIT = Math.pow(2, 5) + 7
const RATIO = 0.5
const SHIFT_ANGLE = 60



export default function App() {
const [state, setState] = useState({
direction: Number(PARAMS.get('direction') || DIRECTION),
length: Number(PARAMS.get('length') || LENGTH),
limit: Number(PARAMS.get('limit') || LIMIT),
ratio: Number(PARAMS.get('ratio') || RATIO),
shiftAngle: Number(PARAMS.get('shiftAngle') || SHIFT_ANGLE),
})

const handleChange = useCallback(({ name, value }) => {
setState((oldState) => ({
...oldState,
[name]: Number(value),
}))
}, [setState])

return (
<div className={ Styles.root }>
<Fractal />
<Fractal
direction={ state.direction }
length={ state.length }
limit={ state.limit }
ratio={ state.ratio }
shiftAngle={ state.shiftAngle }
/>
<Controls
handleChange={ handleChange }
state={ state }
/>
</div>
)
}
71 changes: 71 additions & 0 deletions src/components/App/Controls/Controls.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import React, {
useCallback,
} from 'react'

import PropTypes from 'prop-types'

import Styles from './styles.module.sass'


export default function Controls({ handleChange, state }) {
const onChange = useCallback((e) => {
e.stopPropagation()
e.preventDefault()

handleChange({
name: e.target.name,
value: e.target.value,
})
}, [handleChange])

return (
<div className={ Styles.root }>
Angle:
<input
onChange={ onChange }
type="number"
name="shiftAngle"
defaultValue={ state.shiftAngle }
/>
<br />
Direction:
<input
onChange={ onChange }
type="number"
name="direction"
defaultValue={ state.direction }
/>
<br />
Limit:
<input
onChange={ onChange }
type="number"
name="limit"
defaultValue={ state.limit }
/>
<br />
Length:
<input
onChange={ onChange }
type="number"
name="length"
defaultValue={ state.length }
step={ 10 }
/>
<br/>
Ratio:
<input
onChange={ onChange }
type="number"
name="ratio"
defaultValue={ state.ratio }
step={ 0.01 }
max={ 0.99 }
/>
</div>
)
}

Controls.propTypes = {
handleChange: PropTypes.func.isRequired,
}
3 changes: 3 additions & 0 deletions src/components/App/Controls/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import Controls from './Controls'

export default Controls
11 changes: 11 additions & 0 deletions src/components/App/Controls/styles.module.sass
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
.root
position: absolute
padding: 1rem
border: 1px solid black
background: #ccc
top: 0
right: 0
width: 20rem
height: 10rem


24 changes: 11 additions & 13 deletions src/components/App/Fractal/Fractal.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,16 @@ import drawFractal from './lib/fractal'

import Styles from './styles.module.sass'

const DIRECTION = 0
const LENGTH = 500
const LIMIT = Math.pow(2, 5) + 7


export default function Fractal() {
export default function Fractal(props) {
const {
direction,
length,
limit,
ratio,
shiftAngle,
} = props

const ref = useRef()

const canvasSize = useSize(ref)
Expand All @@ -24,14 +28,8 @@ export default function Fractal() {
canvas.width = canvasSize[0]
canvas.height = canvasSize[1]

const params = new URLSearchParams(window.location.search)

drawFractal(canvas, {
direction: Number(params.get('direction') || DIRECTION),
length: Number(params.get('length') || LENGTH),
limit: Number(params.get('limit') || LIMIT),
})
}, [canvasSize])
drawFractal(canvas, props)
}, [canvasSize, props])

return (
<canvas
Expand Down
32 changes: 19 additions & 13 deletions src/components/App/Fractal/lib/fractal.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,18 @@ import getDirection from './getDirection'

const D2R = Math.PI / 180

const COLORS = ['#fff', '#f00', '#0f0', '#00f', 'pink', 'cyan', 'violet']
const COLORS = ['black'] //, 'red', 'orange', 'yellow', 'green', 'cyan', 'violet', 'cyan', 'violet']
const MIN_SIDE_LEGNTH = 1.5


export default function drawFractal(canvas, opts = {}) {
const colors = colorGenerator()

const ratio = Math.min(0.999, opts.ratio)

const ctx = canvas.getContext('2d')
ctx.fillStyle = '#fff' //'#242424'
ctx.fillRect(0, 0, canvas.width, canvas.height);

ctx.translate(canvas.width * 0.5,
canvas.height * 0.5)
Expand All @@ -24,7 +29,7 @@ export default function drawFractal(canvas, opts = {}) {

const lengthColorMap = new Map()

do {
while ( shapesToDraw.length ) {
const shape = shapesToDraw.shift()

const color = (function() {
Expand All @@ -44,17 +49,22 @@ export default function drawFractal(canvas, opts = {}) {
points,
} = shape

const newLength = length / 2
if ( newLength < 2 ) {
const newLength = length * ratio

if ( newLength < MIN_SIDE_LENGTH ) {
console.warn('new Length too small to render')
break
}

if ( lengthColorMap.size >= opts.limit ) {
continue
}

for ( let j = 0; j < points.length; ++j ) {
const p1 = points[j]
const p2 = points[j + 1] || points[0]

const direction = getDirection(p1, p2) - 60
const direction = getDirection(p1, p2) - opts.shiftAngle

const child = buildShape({
direction,
Expand All @@ -65,28 +75,24 @@ export default function drawFractal(canvas, opts = {}) {

shapesToDraw.push(child)
}
} while ( lengthColorMap.size < opts.limit )
}
}

function drawPolygon(ctx, { direction, length, points }) {
const [start, ...others] = points

ctx.beginPath()

ctx.fillStyle = `rgba(0, 0, 0, 0.15)`
ctx.moveTo(start.x, start.y)

// ctx.strokeText(`(${ start.x }, ${ start.y })`, start.x + 20, start.y + 10)

others.forEach(({ x, y }, i) => {
ctx.lineTo(x, y)
//ctx.strokeText(`(${ x }, ${ y })`, x + 20, y + 10)
ctx.stroke()
})

ctx.lineTo(start.x, start.y)

ctx.stroke()
ctx.closePath()
ctx.fill()
ctx.stroke()
}

function* colorGenerator() {
Expand Down
1 change: 0 additions & 1 deletion src/components/App/styles.module.sass
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
.root
height: 100%
width: 100%
border: 1px solid pink
bottom: 0
top: 0
left: 0
Expand Down

0 comments on commit 20f3e24

Please sign in to comment.