Skip to content

Commit

Permalink
feat: Render control stems with svg
Browse files Browse the repository at this point in the history
  • Loading branch information
Undistraction committed Jul 23, 2024
1 parent d308fa7 commit b0a8a29
Show file tree
Hide file tree
Showing 18 changed files with 175 additions and 104 deletions.
2 changes: 1 addition & 1 deletion .eslintrc.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ module.exports = {

plugins: ['tailwind', 'import', 'react'],

ignorePatterns: ['**/coverage/*', `/node_modules/*`, `/dist/`, `**/demo/*`],
ignorePatterns: ['**/coverage/*', `/node_modules/*`, `/dist/`, `/demo/dist`],

rules: {
'react/prop-types': 0,
Expand Down
3 changes: 0 additions & 3 deletions TODO.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,6 @@

### Should do

1. Improve saving mechanism. Better structure of saved data. Save and check version.
2. Switch drawing of control point stems to SVG

### Could do

1. Shortcuts
Expand Down
78 changes: 15 additions & 63 deletions demo/src/App/App.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,11 @@ import { useDebounce } from 'use-debounce'
import getCoonsPatch from '../../../src/'
import { INTERPOLATION_STRATEGY_ID } from '../../../src/const'
import { BOUNDS_POINT_IDS, CORNER_POINTS } from '../const'
import useObserveClientSize from '../hooks/useObserveClientSize'
import {
clampGridSquareToGridDimensions,
getRandomBoundingCurves,
} from '../utils'
import { getRandomBoundingCurves } from '../utils'
import { getBoundsApi } from '../utils/boundsApi'
import localStorageApi from '../utils/localStorageApi'
import Canvas from './Canvas'
import ControlNodes from './Canvas/ControlNodes'
import Shape from './Canvas/Shape'
import Sidebar from './Sidebar'
import WorkArea from './WorkArea'

// -----------------------------------------------------------------------------
// Const
Expand Down Expand Up @@ -48,8 +42,6 @@ const CONFIG_DEFAULT = {
},
}

const BORDER_WIDTHS = 2

// -----------------------------------------------------------------------------
// Utils
// -----------------------------------------------------------------------------
Expand Down Expand Up @@ -205,16 +197,8 @@ const App = () => {
const [savedProjects, setSavedProjects] = React.useState(
localStorageApi.getProjects()
)
const displayRef = React.useRef(null)
const [boundingCurvesDebounced] = useDebounce(boundingCurves, 5)

useObserveClientSize(displayRef, setCanvasSize, {
// left + right border widths
width: -BORDER_WIDTHS,
// top + bottom border widths
height: -BORDER_WIDTHS,
})

React.useLayoutEffect(() => {
if (!boundingCurves && canvas && canvasSize.width > 0) {
setBoundingCurves(getRandomBoundingCurves(canvas))
Expand All @@ -226,55 +210,23 @@ const App = () => {
}
}, [boundingCurvesDebounced, canvas, grid, canvasSize])

const gridSquareClamped = React.useMemo(
() =>
surface.gridSquare
? clampGridSquareToGridDimensions(surface.gridSquare, grid)
: surface.gridSquare,
[surface, grid]
)

const boundsApi = getBoundsApi(boundingCurves)

return (
<div className="relative flex h-full w-screen flex-row space-x-5 p-5">
<div
className="relative h-full flex-grow overflow-hidden"
id="patch-view"
ref={displayRef}
>
<Canvas
setCanvas={setCanvas}
width={canvasSize.width}
height={canvasSize.height}
coonsPatch={coonsPatch}
gridSquare={gridSquareClamped}
surface={surface}
config={config}
/>
{boundingCurves && (
<React.Fragment>
<Shape
boundingCurves={boundingCurves}
onDrag={handleShapeDrag(
boundingCurves,
setBoundingCurves,
config
)}
/>
{config.bounds.shouldDrawCornerPoints && (
<ControlNodes
boundingCurves={boundingCurves}
onNodePositionChange={handleNodePositionChange(
boundingCurves,
setBoundingCurves,
config
)}
/>
)}
</React.Fragment>
)}
</div>
<WorkArea
handleShapeDrag={handleShapeDrag}
boundingCurves={boundingCurves}
setCanvas={setCanvas}
canvasSize={canvasSize}
coonsPatch={coonsPatch}
surface={surface}
config={config}
setBoundingCurves={setBoundingCurves}
handleNodePositionChange={handleNodePositionChange}
setCanvasSize={setCanvasSize}
grid={grid}
/>
<div className="-my-5 w-[300px] flex-shrink-0 flex-grow-0 overflow-y-scroll">
<Sidebar
grid={grid}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React from 'react'
import { isInt } from '../../../../src/utils/types'
import getCanvasApi from '../../utils/getCanvasApi'
import { isInt } from '../../../../../src/utils/types'
import getCanvasApi from '../../../utils/getCanvasApi'

// -----------------------------------------------------------------------------
// Exports
Expand Down Expand Up @@ -32,7 +32,6 @@ const Canvas = ({
canvasApi.drawCoonsPatch(coonsPatch, {
shouldDrawBounds: config.bounds.shouldDrawBounds,
shouldDrawIntersections: config.grid.shouldDrawIntersections,
shouldDrawCornerPoints: config.bounds.shouldDrawCornerPoints,
})

if (gridSquare && isInt(gridSquare.x) && isInt(gridSquare.y)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
// -----------------------------------------------------------------------------

import React from 'react'
import { BOUNDS_POINT_IDS } from '../../../const'
import { BOUNDS_POINT_IDS } from '../../../../const'
import ControlPointNode from './ControlPointNode'
import CornerNode from './CornerNode'

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ const ControlPointNode = ({ position, onDrag, id }) => {
<Draggable
nodeRef={nodeRef}
position={position}
bounds="#patch-view"
bounds="#work-area"
onDrag={onDrag(id)}
handle=".control-point-handle"
>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ const CornerNode = ({ id, position, onDrag }) => {
<Draggable
nodeRef={nodeRef}
position={position}
bounds="#patch-view"
bounds="#work-area"
onDrag={onDrag(id)}
handle=".corner-handle"
>
Expand Down
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import React from 'react'

// -----------------------------------------------------------------------------
// Utils
// -----------------------------------------------------------------------------

const renderStems = (points) =>
points.map(([point1, point2], idx) => {
return (
<line
key={idx}
x1={point1.x}
y1={point1.y}
x2={point2.x}
y2={point2.y}
stroke="#BBB"
/>
)
})

// -----------------------------------------------------------------------------
// Exports
// -----------------------------------------------------------------------------

const ControlPointStems = ({ boundingCurves, width, height }) => {
const points = [
[boundingCurves.top.startPoint, boundingCurves.top.controlPoint1],
[boundingCurves.top.endPoint, boundingCurves.top.controlPoint2],
[boundingCurves.bottom.startPoint, boundingCurves.bottom.controlPoint1],
[boundingCurves.bottom.endPoint, boundingCurves.bottom.controlPoint2],
[boundingCurves.left.startPoint, boundingCurves.left.controlPoint1],
[boundingCurves.left.endPoint, boundingCurves.left.controlPoint2],
[boundingCurves.right.startPoint, boundingCurves.right.controlPoint1],
[boundingCurves.right.endPoint, boundingCurves.right.controlPoint2],
]

return (
<div className={`absolute inset-0`}>
<svg
xmlns="http://www.w3.org/2000/svg"
overflow="visible"
viewBox={`0 0 ${width} ${height}`}
width={width}
height={height}
>
{renderStems(points)}
</svg>
</div>
)
}

export default ControlPointStems
3 changes: 3 additions & 0 deletions demo/src/App/WorkArea/Canvas/ControlPointStems/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import ControlPointStems from './ControlPointStems.jsx'

export default ControlPointStems
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React from 'react'
import Draggable from 'react-draggable'
import { getBoundsApi } from '../../../utils/boundsApi'
import { getBoundsApi } from '../../../../utils/boundsApi'

// -----------------------------------------------------------------------------
// Const
Expand Down Expand Up @@ -119,7 +119,7 @@ const Shape = ({ boundingCurves, onDrag }) => {
<Draggable
nodeRef={nodeRef}
position={boundingCurves.top.startPoint}
bounds="#patch-view"
bounds="#work-area"
onDrag={(event, dragElement) => {
const newPosition = {
x: dragElement.x,
Expand Down
File renamed without changes.
File renamed without changes.
93 changes: 93 additions & 0 deletions demo/src/App/WorkArea/WorkArea.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
import React from 'react'
import useObserveClientSize from '../../hooks/useObserveClientSize'
import { clampGridSquareToGridDimensions } from '../../utils'
import Canvas from './Canvas'
import ControlNodes from './Canvas/ControlNodes'
import ControlPointStems from './Canvas/ControlPointStems'
import Shape from './Canvas/Shape'

// -----------------------------------------------------------------------------
// Const
// -----------------------------------------------------------------------------

const BORDER_WIDTHS = 2

// -----------------------------------------------------------------------------
// Exports
// -----------------------------------------------------------------------------

const WorkArea = ({
setCanvas,
canvasSize,
coonsPatch,
surface,
config,
boundingCurves,
setBoundingCurves,
handleNodePositionChange,
handleShapeDrag,
setCanvasSize,
grid,
}) => {
const displayRef = React.useRef(null)

const gridSquareClamped = React.useMemo(
() =>
surface.gridSquare
? clampGridSquareToGridDimensions(surface.gridSquare, grid)
: surface.gridSquare,
[surface, grid]
)

useObserveClientSize(displayRef, setCanvasSize, {
// left + right border widths
width: -BORDER_WIDTHS,
// top + bottom border widths
height: -BORDER_WIDTHS,
})

return (
<div
className="relative h-full flex-grow overflow-hidden"
id="work-area"
ref={displayRef}
>
<Canvas
setCanvas={setCanvas}
width={canvasSize.width}
height={canvasSize.height}
coonsPatch={coonsPatch}
gridSquare={gridSquareClamped}
surface={surface}
config={config}
/>
{boundingCurves && (
<React.Fragment>
<Shape
boundingCurves={boundingCurves}
onDrag={handleShapeDrag(boundingCurves, setBoundingCurves, config)}
/>
{config.bounds.shouldDrawCornerPoints && (
<React.Fragment>
<ControlPointStems
boundingCurves={boundingCurves}
width={canvasSize.width}
height={canvasSize.height}
/>
<ControlNodes
boundingCurves={boundingCurves}
onNodePositionChange={handleNodePositionChange(
boundingCurves,
setBoundingCurves,
config
)}
/>
</React.Fragment>
)}
</React.Fragment>
)}
</div>
)
}

export default WorkArea
3 changes: 3 additions & 0 deletions demo/src/App/WorkArea/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import WorkArea from './WorkArea.jsx'

export default WorkArea
30 changes: 1 addition & 29 deletions demo/src/utils/getCanvasApi.js
Original file line number Diff line number Diff line change
Expand Up @@ -111,30 +111,6 @@ const getCanvasApi = (context) => {
drawQuad(boundingCurves, { color: lineColor, lineWidth })
}

const drawControlPoints = (boundingCurves) => {
// Draw control point stems
const edges = [
boundingCurves.top,
boundingCurves.bottom,
boundingCurves.left,
boundingCurves.right,
]

edges.map(({ startPoint, endPoint, controlPoint1, controlPoint2 }) => {
drawLine(startPoint, controlPoint1)
drawLine(endPoint, controlPoint2)
})
}

const drawLine = (startPoint, endPoint, { color = 'grey' } = {}) => {
context.beginPath()
context.moveTo(startPoint.x, startPoint.y)
context.lineTo(endPoint.x, endPoint.y)
context.strokeStyle = color
context.lineWidth = 1
context.stroke()
}

const clearCanvas = (canvas) => {
context.clearRect(0, 0, canvas.width, canvas.height)
}
Expand All @@ -158,16 +134,12 @@ const getCanvasApi = (context) => {

const drawCoonsPatch = (
coonsPatch,
{ shouldDrawIntersections, shouldDrawBounds, shouldDrawCornerPoints }
{ shouldDrawIntersections, shouldDrawBounds }
) => {
if (shouldDrawBounds) {
drawBounds(coonsPatch.config.boundingCurves)
}

if (shouldDrawCornerPoints) {
drawControlPoints(coonsPatch.config.boundingCurves)
}

const curves = coonsPatch.api.getCurves()

// Draw curves along x axis
Expand Down

0 comments on commit b0a8a29

Please sign in to comment.