Skip to content

(WIP) 🎨 A Canvas API-wrapper for solidjs ⚑ by solid and @solid-primitives/jsx-tokenizer

License

Notifications You must be signed in to change notification settings

bigmistqke/solid-canvas

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

solid-canvas

🎨 solid-canvas

pnpm

a solid wrapper around the Canvas API

rec.mp4

source

_rec.mp4

source

_rec2.mp4

source

_rec3.mp4

source

curves.mp4

source

Simple example

import { Canvas, Text, Rectangle } from 'solid-canvas'

const App = () => (
  <Canvas fill="blue">
    <Text position={{ x: 100, y: 100 }} text="hallo" fill="white" size={20} />
    <Rectangle
      position={{ x: 100, y: 100 }}
      dimensions={{ width: 250, height: 250 }}
      fill="purple"
      stroke="transparent"
    />
  </Canvas>
)

You can also compose shapes

import { Canvas, Text, Rectangle } from 'solid-canvas'

const App = () => (
  <Canvas fill="blue">
    <Rectangle
      position={{ x: 100, y: 100 }}
      dimensions={{ width: 250, height: 250 }}
      fill="purple"
      stroke="transparent"
    >
      <Text text="hallo" fill="white" size={20} />
    </Rectangle>
  </Canvas>
)

Screenshot 2023-03-22 at 20 36 47

MouseEvents: draggable <Rectangle/>

import { Canvas, Rectangle } from 'solid-canvas'

const App: Component = () => {
  const [selected, setSelected] = createSignal(false)
  const [position, setPosition] = createSignal({ x: 100, y: 100 })

  return (
    <Canvas
      onMouseMove={event => {
        if (!selected()) return
        setPosition(position => ({
          x: position + event.delta.x,
          y: position + event.delta.y,
        }))
      }}
      onMouseUp={() => setSelected(false)}
    >
      <Rectangle
        position={position()}
        dimensions={{ width: 50, height: 50 }}
        onMouseDown={() => setSelected(true)}
      />
    </Canvas>
  )
}

Each Shape2D also has a controller-prop which accepts functions that alter the component's prop: an example of this is Drag

import { Canvas, Rectangle } from 'solid-canvas'

const App = () => (
  <Canvas>
    <Rectangle
      position={{ x: 100, y: 100 }}
      dimensions={{ width: 50, height: 50 }}
      controllers{[Drag()]}
    />
  </Canvas>
)
_rec3.mp4

<Group/> and Clip

import { Canvas, Rectangle, Group } from 'solid-canvas'

const App = () => (
  <Canvas>
    <Group
      position={{ x: 100, y: 100 }}
      clip={() => (
        <>
          <Rectangle
            position={{ x: 0, y: 0 }}
            dimensions={{ width: 100, height: 50 }}
          />
          <Rectangle
            position={{ x: 0, y: 0 }}
            dimensions={{ width: 50, height: 100 }}
          />
        </>
      )}
      fill="blue"
    >
      <Text text="hallo" size={50} />
    </Group>
  </Canvas>
)

Screenshot 2023-03-22 at 20 46 40

All Shape2Ds inherit from Group, so you can clip and add children to any Shape2D

Lines: <Line/>, <Bezier/> and <Quadratic/>

import { Bezier, Canvas, Line, Quadratic } from 'solid-canvas'

const App = () => (
  <Canvas draggable>
    <Line
      position={{ x: 100, y: 100 }}
      points={[
        { x: 0, y: 0 },
        { x: 50, y: 100 },
        { x: 100, y: 0 },
        { x: 150, y: 100 },
        { x: 200, y: 0 },
        { x: 250, y: 100 },
      ]}
    />
    <Bezier
      position={{ x: 500, y: 100 }}
      points={[
        { point: { x: 0, y: 0 }, control: { x: 50, y: 0 } },
        { point: { x: 50, y: 100 }, control: { x: -50, y: 0 } },
        { point: { x: 100, y: 0 }, control: { x: -50, y: 0 } },
        { point: { x: 150, y: 100 }, control: { x: -50, y: 0 } },
        { point: { x: 200, y: 0 }, control: { x: -50, y: 0 } },
        { point: { x: 250, y: 100 }, control: { x: -50, y: 0 } },
      ]}
    />
    <Quadratic
      position={{ x: 900, y: 150 }}
      points={[
        { point: { x: 0, y: 0 }, control: { x: 25, y: -100 } },
        { point: { x: 50, y: 0 } },
        { point: { x: 100, y: 0 } },
        { point: { x: 150, y: 0 } },
        { point: { x: 200, y: 0 } },
        { point: { x: 250, y: 0 } },
      ]}
    />
  </Canvas>
)

Screenshot 2023-03-26 at 12 00 18

Canvas API-Coverage

  • Object2D
    • <Group/>
    • Shape2D
      • <Text/>
      • <Image/>
      • Path2D
        • <Rectangle/>
        • <Line/>
        • <Arc/>
        • <Bezier/>
        • <Quadratic/>
  • Compositing
    • <Group/> (to 'properly' composite groups we should render to offscreencanvas first)
    • Shape2D
  • Clipping
    • <Group/>
    • Shape2D (Shape2D inherits from Group)
  • Color (for fill/stroke)
    • <Gradient/>
    • <Pattern/>

Additional API

  • Path component
    • accepts an svg path constructed with utility-functions from solid-canvas/d example
    • accepts a raw svg path-string
  • MouseEvents for Shape2D πŸ‘‰ Shape2D.onMouseDown, Shape2D.onMouseMove and Shape2D.onMouseUp
  • MouseEvents for Canvas πŸ‘‰ Canvas.onMouseDown, Canvas.onMouseMove and Canvas.onMouseUp
  • HoverStyles for Shape2D with "&:hover" selector πŸ‘‰ "&:hover: Shape2DStyles`
  • Transitions for Shape2D: automatic lerping between styles/transforms
  • Navigation
    • Pan (draggable-prop in Canvas)
    • Zoom
  • Controller-prop: callback which can control the props
  • Handles-controller
    • Pan (draggable-prop in Canvas)
    • Zoom
  • Controllers-prop: transform props through a series of composable controller-functions
  • CurveHandles-controller: edit points of Path2D
    • Line
    • Bezier
    • Quadratic
    • Rectangle
    • Arc
  • TransformHandles-controller: edit transform (position, rotation, scale and skew) of Object2D
  • Nestable <Canvas/> to divide scene up for optimization (p.ex static background-canvas and dynamic player-canvas)
  • OffscreenCanvas / Offscreen-prop: offload rendering to webworker
  • HTML component: easy way to implement html in Canvas coordinate system
  • Masking with destination-in see
  • Caching Object2D by rendering result to OffscreenCanvas

Overal Ambitions / Roadmap

  • Cover the whole Canvas-API
  • Provide tools to simplify common canvas operations
  • Explore render-optimizations:
    • Only render what is in viewport
    • Only render the bounds of Shape2Ds that has changed
  • Treeshakable: minimal use should result in minimal bundle

About

(WIP) 🎨 A Canvas API-wrapper for solidjs ⚑ by solid and @solid-primitives/jsx-tokenizer

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages