diff --git a/README.md b/README.md
index 281d7d0..080fe38 100644
--- a/README.md
+++ b/README.md
@@ -30,6 +30,7 @@
- [x] Deno KV storage
- [x] Kysley Postgres/Neon storage
- [x] Migrations
+ - [ ] Seeds
- [x] RPC (GET/POST)
- [x] Emails (Resend)
- [x] Auth
@@ -56,8 +57,10 @@
- [x] Tailwindcss
- [x] Icons (Lucide)
- [x] Fonts
-- [ ] Canvas
- - [ ] Wait for Fonts
+- [x] Canvas
+ - [x] Wait for Fonts
+ - [x] Animation
+ - [x] Screen/Dims
- [x] AssemblyScript
- [x] WebAudio
- [x] Wasm AudioWorklet
diff --git a/src/pages/About.tsx b/src/pages/About.tsx
index 1186aa8..a717fbd 100644
--- a/src/pages/About.tsx
+++ b/src/pages/About.tsx
@@ -1,5 +1,3 @@
-import { Link } from '~/src/ui/Link.tsx'
-
export function About() {
return
About Page
diff --git a/src/pages/App.tsx b/src/pages/App.tsx
index a89921b..6b41b5b 100644
--- a/src/pages/App.tsx
+++ b/src/pages/App.tsx
@@ -5,6 +5,7 @@ import { ResetPassword } from '~/src/comp/ResetPassword.tsx'
import { VerifyEmail } from '~/src/comp/VerifyEmail.tsx'
import { About } from '~/src/pages/About.tsx'
import { AssemblyScript } from '~/src/pages/AssemblyScript.tsx'
+import { Canvas } from '~/src/pages/Canvas'
import { Chat } from '~/src/pages/Chat/Chat.tsx'
import { Home } from '~/src/pages/Home.tsx'
import { OAuthRegister } from '~/src/pages/OAuthRegister.tsx'
@@ -19,6 +20,8 @@ export function App() {
const info = $({
bg: 'transparent',
+ canvasWidth: 500,
+ canvasHeight: 500,
})
return
+ case '/canvas':
+ return
+
case '/asc':
return
diff --git a/src/pages/Canvas.tsx b/src/pages/Canvas.tsx
new file mode 100644
index 0000000..e5b89b2
--- /dev/null
+++ b/src/pages/Canvas.tsx
@@ -0,0 +1,59 @@
+import { Sigui, type Signal } from 'sigui'
+import { drawText } from 'utils'
+import { screen } from '~/src/screen.ts'
+
+export function Canvas({ width, height }: {
+ width: Signal
+ height: Signal
+}) {
+ using $ = Sigui()
+
+ const canvas = as HTMLCanvasElement
+ const c = canvas.getContext('2d')!
+
+ const info = $({
+ pr: screen.$.pr,
+ width,
+ height,
+ c: $.unwrap(async () => {
+ await document.fonts.ready
+ return c
+ })
+ })
+
+ $.fx(() => {
+ const { c, width, height, pr } = $.of(info)
+ $()
+ if (c instanceof Error) return
+ canvas.width = width * pr
+ canvas.height = height * pr
+ canvas.style.width = `${width}px`
+ canvas.style.height = `${height}px`
+ c.scale(pr, pr)
+ c.textBaseline = 'top'
+ c.textRendering = 'optimizeSpeed'
+ c.miterLimit = 1.5
+ c.font = '32px "Fustat"'
+ })
+
+ let i = 0
+ let animFrame: any
+ function tick() {
+ animFrame = requestAnimationFrame(tick)
+ c.restore()
+ c.save()
+ c.rotate(0.12 * i++)
+ drawText(c, { x: 10, y: 10 }, 'Hello World', `hsl(${i % 360}, 50%, 50%)`, 4, '#000')
+ }
+
+ $.fx(() => {
+ const { c } = $.of(info)
+ $()
+ if (c instanceof Error) return
+ c.translate(info.width / 2, info.height / 2)
+ tick()
+ return () => cancelAnimationFrame(animFrame)
+ })
+
+ return canvas
+}
diff --git a/src/pages/Home.tsx b/src/pages/Home.tsx
index db009f4..0818108 100644
--- a/src/pages/Home.tsx
+++ b/src/pages/Home.tsx
@@ -23,6 +23,7 @@ export function Home() {
{state.user.isAdmin &&
Admin}
Chat
+
Canvas
AssemblyScript
About
diff --git a/src/screen.ts b/src/screen.ts
new file mode 100644
index 0000000..059499c
--- /dev/null
+++ b/src/screen.ts
@@ -0,0 +1,5 @@
+import { $ } from 'sigui'
+
+export const screen = $({
+ pr: window.devicePixelRatio,
+})