npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

react-tela

v1.0.1

Published

React renderer for Canvas

Readme

react-tela

Use React to render images, shapes and text to <canvas>

[!WARNING] This package is currently under development. Expect breaking changes.

react-tela is a React renderer that draws components to a <canvas> node.

Features

  • Low-level primitives — base components expose Canvas drawing operations directly (rects, circles, arcs, paths, images, text)
  • High-level abstractions — use the power of React to compose primitives into complex UIs
  • Flexbox layout — optional @react-tela/flex package provides a <Flex> component powered by Yoga for CSS-like layout
  • Unopinionated about runtime — works in web browsers, Node.js, and nx.js
  • No DOM dependency — never assumes anything "outside" of the provided canvas node

Installation

npm install react-tela react

Quick Start

import React from "react";
import { Group, Rect, Text, useDimensions } from "react-tela";

function Contents() {
  const dims = useDimensions();
  return (
    <>
      <Rect width={dims.width} height={dims.height} fill="purple" alpha={0.5} />
      <Text fontSize={32} fontFamily="Geist" fill="white">
        Hello world!
      </Text>
    </>
  );
}

export function App() {
  return (
    <Group x={5} y={15} width={180} height={30} rotate={0.1}>
      <Contents />
    </Group>
  );
}

Rendering

Import render from react-tela/render and pass your app component along with a canvas element:

Web Browser

import React from "react";
import { render } from "react-tela/render";
import { App } from "./App";

render(<App />, document.getElementById("canvas"));

Node.js

Uses @napi-rs/canvas for headless rendering:

import React from "react";
import { render } from "react-tela/render";
import config, { Canvas } from "@napi-rs/canvas";
import { App } from "./App";

const canvas = new Canvas(300, 150);
await render(<App />, canvas, config);

const buffer = canvas.toBuffer("image/png");
// … do something with the PNG buffer

nx.js

import React from "react";
import { render } from "react-tela/render";
import { App } from "./App";

render(<App />, screen);

Gradients

The fill and stroke props on shapes and text accept gradient descriptors in addition to CSS color strings. Use the gradient hooks inside components for optimal performance — they memoize the descriptor so the underlying CanvasGradient is cached across re-renders:

import React from 'react';
import { Rect, Text, useLinearGradient, useRadialGradient, useConicGradient } from 'react-tela';

export function App() {
  // Linear gradient (memoized)
  const linear = useLinearGradient(0, 0, 200, 0, [
    [0, 'red'],
    [0.5, 'yellow'],
    [1, 'blue'],
  ]);

  // Radial gradient (memoized)
  const radial = useRadialGradient(100, 100, 10, 100, 100, 100, [
    [0, 'white'],
    [1, 'black'],
  ]);

  // Conic gradient (memoized)
  const conic = useConicGradient(0, 100, 100, [
    [0, 'red'],
    [0.25, 'yellow'],
    [0.5, 'green'],
    [0.75, 'blue'],
    [1, 'red'],
  ]);

  // Gradient on text
  const textGradient = useLinearGradient(0, 0, 300, 0, [[0, 'red'], [1, 'blue']]);

  return (
    <>
      <Rect width={200} height={100} fill={linear} />
      <Rect y={100} width={200} height={200} fill={radial} />
      <Rect y={300} width={200} height={200} fill={conic} />
      <Text y={500} fontSize={48} fontFamily="Geist" fill={textGradient}>Gradient Text</Text>
    </>
  );
}

Gradient example

Gradient Hooks

| Hook | Parameters | Description | |------|-----------|-------------| | useLinearGradient | (x0, y0, x1, y1, stops) | Memoized linear gradient between two points | | useRadialGradient | (x0, y0, r0, x1, y1, r1, stops) | Memoized radial gradient between two circles | | useConicGradient | (startAngle, x, y, stops) | Memoized conic (sweep) gradient around a point |

Each stops parameter is an array of [offset, color] tuples where offset is between 0 and 1.

Patterns

The <Pattern> component creates a repeating pattern that can be used as a fill or stroke on shapes and text. It works like a <Group> but renders its children into an offscreen canvas and exposes a CanvasPattern via ref:

import React, { useRef } from 'react';
import { Rect, Pattern } from 'react-tela';

export function App() {
  const pattern = useRef<CanvasPattern>(null);

  return (
    <>
      <Pattern ref={pattern} width={20} height={20} repetition="repeat">
        <Rect width={10} height={10} fill="#ccc" />
        <Rect x={10} y={10} width={10} height={10} fill="#ccc" />
      </Pattern>
      <Rect width={200} height={120} fill={pattern} />
    </>
  );
}

Pattern example

Pattern Props

| Prop | Type | Default | Description | |------|------|---------|-------------| | repetition | 'repeat' \| 'repeat-x' \| 'repeat-y' \| 'no-repeat' | 'repeat' | How the pattern repeats | | width | number | — | Width of the pattern tile | | height | number | — | Height of the pattern tile |

The <Pattern> component also accepts all <Group> props. Pass the ref to fill or stroke on any shape or text component to apply the pattern.

usePattern() Hook

For image URL-based patterns, use the usePattern() hook. It loads the image asynchronously and returns a CanvasPattern (or null while loading):

import { Rect, usePattern } from 'react-tela';

function TiledBackground() {
  const pattern = usePattern('https://example.com/tile.png', 'repeat');

  return <Rect width={400} height={300} fill={pattern} />;
}

usePattern example

| Parameter | Type | Default | Description | |-----------|------|---------|-------------| | source | string | — | Image URL or path to load | | repetition | 'repeat' \| 'repeat-x' \| 'repeat-y' \| 'no-repeat' | 'repeat' | How the pattern repeats |

Returns CanvasPattern | nullnull while the image is loading.

Filters

All entities support the filter prop, which maps directly to CanvasRenderingContext2D.filter. Pass any valid CSS filter string:

import React from 'react';
import { Rect, Circle, Text } from 'react-tela';

export function App() {
  return (
    <>
      <Rect x={10} y={20} width={80} height={80} fill="red" filter="blur(3px)" />
      <Circle x={115} y={25} radius={35} fill="blue" filter="drop-shadow(4px 4px 4px rgba(0,0,0,0.5))" />
      <Text x={220} y={44} fill="green" fontSize={32} fontFamily="Geist" filter="drop-shadow(3px 3px 0 rgba(0,0,0,0.7))">Hello</Text>
    </>
  );
}

Filter example

Supported filter functions include blur(), brightness(), contrast(), drop-shadow(), grayscale(), hue-rotate(), invert(), opacity(), saturate(), and sepia(). Multiple filters can be chained in a single string.

Blend Modes

Set the blendMode prop on any entity to control how it composites with the content below it. This maps directly to the Canvas globalCompositeOperation property.

import React from 'react';
import { Rect, Circle } from 'react-tela';

export function App() {
  return (
    <>
      <Rect width={360} height={120} fill="#222" />
      <Rect x={10} y={10} width={80} height={100} fill="#e74c3c" />
      <Rect x={50} y={10} width={80} height={100} fill="#3498db" blendMode="multiply" />
      <Rect x={140} y={10} width={80} height={100} fill="#e74c3c" />
      <Rect x={180} y={10} width={80} height={100} fill="#3498db" blendMode="screen" />
      <Rect x={270} y={10} width={80} height={100} fill="#e74c3c" />
      <Circle x={290} y={30} radius={40} fill="#3498db" blendMode="overlay" />
    </>
  );
}

Blend modes example

Common values include "multiply", "screen", "overlay", "darken", "lighten", "destination-out", and more. See MDN for the full list.

Shadows

All entities support shadow props that map directly to the Canvas shadow properties:

import React from 'react';
import { Rect, Circle, Text } from 'react-tela';

export function App() {
  return (
    <>
      <Rect x={10} y={10} width={100} height={80} fill="blue"
        shadowColor="rgba(0, 0, 0, 0.5)" shadowBlur={10} shadowOffsetX={5} shadowOffsetY={5} />
      <Circle x={180} y={20} radius={40} fill="red"
        shadowColor="rgba(0, 0, 0, 0.6)" shadowBlur={15} shadowOffsetX={4} shadowOffsetY={4} />
      <Text x={270} y={40} fill="green" fontSize={32} fontFamily="Geist"
        shadowColor="rgba(0, 0, 0, 0.7)" shadowBlur={3} shadowOffsetX={2} shadowOffsetY={2}>Hello</Text>
    </>
  );
}

Shadow example

The shadowColor prop accepts any CSS color string. shadowBlur controls the blur radius, while shadowOffsetX and shadowOffsetY control the horizontal and vertical offset of the shadow.

Components

All components accept these common props:

| Prop | Type | Default | Description | |------|------|---------|-------------| | x | number | 0 | Horizontal position | | y | number | 0 | Vertical position | | width | number | 0 | Width in pixels | | height | number | 0 | Height in pixels | | alpha | number | 1 | Opacity (0 = transparent, 1 = opaque) | | rotate | number | 0 | Rotation in degrees | | scaleX | number | 1 | Horizontal scale | | scaleY | number | 1 | Vertical scale | | blendMode | GlobalCompositeOperation | — | Composite operation (see MDN) | | shadowColor | string | — | Shadow color (CSS color string) | | shadowBlur | number | 0 | Shadow blur radius | | shadowOffsetX | number | 0 | Shadow horizontal offset | | shadowOffsetY | number | 0 | Shadow vertical offset |

Mouse and touch events are supported on all components: onClick, onMouseDown, onMouseUp, onMouseMove, onMouseEnter, onMouseLeave, onTouchStart, onTouchMove, onTouchEnd.

<Rect>

Draws a filled and/or stroked rectangle.

import React from 'react';
import { Rect } from 'react-tela';

export function App() {
  return <Rect x={5} y={5} width={100} height={50} fill="red" stroke="black" lineWidth={2} />;
}

Rect example

Rounded corners

Add borderRadius to render a rectangle with rounded corners (uses ctx.roundRect() under the hood):

import React from 'react';
import { Rect } from 'react-tela';

export function App() {
  return <Rect x={5} y={5} width={100} height={50} fill="blue" borderRadius={10} />;
}

Rounded Rect example

The borderRadius prop accepts a single number, a DOMPointInit, or an array — matching the CanvasRenderingContext2D.roundRect() spec.

<Circle>

Draws a circle. Shorthand for <Arc> with startAngle={0} and endAngle={360}.

import React from 'react';
import { Circle } from 'react-tela';

export function App() {
  return <Circle x={10} y={10} radius={40} fill="green" />;
}

Circle example

<Ellipse>

Draws an ellipse with separate X and Y radii.

import React from 'react';
import { Ellipse } from 'react-tela';

export function App() {
  return <Ellipse x={10} y={10} radiusX={80} radiusY={40} fill="purple" stroke="white" lineWidth={2} />;
}

Ellipse example

| Prop | Type | Default | Description | |------|------|---------|-------------| | radiusX | number | — | Horizontal radius | | radiusY | number | — | Vertical radius | | ellipseRotation | number | 0 | Ellipse rotation in degrees | | startAngle | number | 0 | Start angle in degrees | | endAngle | number | 360 | End angle in degrees | | counterclockwise | boolean | false | Draw counterclockwise |

<Arc>

Draws an arc or partial circle.

import React from 'react';
import { Arc } from 'react-tela';

export function App() {
  return <Arc x={10} y={10} radius={50} startAngle={0} endAngle={180} fill="orange" />;
}

Arc example

| Prop | Type | Description | |------|------|-------------| | radius | number | Arc radius | | startAngle | number | Start angle in degrees | | endAngle | number | End angle in degrees | | counterclockwise | boolean | Draw counterclockwise |

<Path>

Draws an SVG path.

import React from 'react';
import { Path } from 'react-tela';

export function App() {
  return (
    <Path
      x={31} y={31}
      width={47.94} height={47.94}
      d="M26.285,2.486l5.407,10.956c0.376,0.762,1.103,1.29,1.944,1.412l12.091,1.757c2.118,0.308,2.963,2.91,1.431,4.403l-8.749,8.528c-0.608,0.593-0.886,1.448-0.742,2.285l2.065,12.042c0.362,2.109-1.852,3.717-3.746,2.722l-10.814-5.685c-0.752-0.395-1.651-0.395-2.403,0l-10.814,5.685c-1.894,0.996-4.108-0.613-3.746-2.722l2.065-12.042c0.144-0.837-0.134-1.692-0.742-2.285l-8.749-8.528c-1.532-1.494-0.687-4.096,1.431-4.403l12.091-1.757c0.841-0.122,1.568-0.65,1.944-1.412l5.407-10.956C22.602,0.567,25.338,0.567,26.285,2.486z"
      fill="#ED8A19"
      stroke="red"
      lineWidth={3}
      scaleX={2} scaleY={2}
    />
  );
}

| Prop | Type | Description | |------|------|-------------| | d | string | SVG path data string | | width | number | Required. Path viewport width | | height | number | Required. Path viewport height |

Path example

<Line>

Draws a line or polyline through a series of points.

import React from 'react';
import { Line } from 'react-tela';

export function App() {
  return <Line points={[{ x: 10, y: 80 }, { x: 70, y: 10 }, { x: 140, y: 80 }]} stroke="blue" lineWidth={3} />;
}

Line example

| Prop | Type | Description | |------|------|-------------| | points | {x: number, y: number}[] | Array of points to connect |

Width and height are computed automatically from the bounding box of the points. All shape props are supported (stroke, lineWidth, fill, etc.).

<BezierCurve>

Draws a cubic Bézier curve between two points with two control points.

BezierCurve example

import React from 'react';
import { BezierCurve } from 'react-tela';

export function App() {
  return (
    <BezierCurve
      x0={10} y0={10}
      cp1x={40} cp1y={0}
      cp2x={60} cp2y={100}
      x1={90} y1={10}
      stroke="blue"
      lineWidth={2}
    />
  );
}

| Prop | Type | Description | |------|------|-------------| | x0, y0 | number | Start point | | cp1x, cp1y | number | First control point | | cp2x, cp2y | number | Second control point | | x1, y1 | number | End point |

Width and height are computed automatically from the bounding box. All shape props are supported.

<QuadraticCurve>

Draws a quadratic Bézier curve between two points with one control point.

QuadraticCurve example

import React from 'react';
import { QuadraticCurve } from 'react-tela';

export function App() {
  return (
    <QuadraticCurve
      x0={10} y0={80}
      cpx={50} cpy={10}
      x1={90} y1={80}
      stroke="red"
      lineWidth={2}
    />
  );
}

| Prop | Type | Description | |------|------|-------------| | x0, y0 | number | Start point | | cpx, cpy | number | Control point | | x1, y1 | number | End point |

Width and height are computed automatically from the bounding box. All shape props are supported.

<Image>

Renders an image from a URL or file path. The image loads asynchronously — the component renders at the specified (or natural) dimensions once loaded.

<Image src="/path/to/image.png" x={10} y={10} width={200} height={150} />

| Prop | Type | Description | |------|------|-------------| | src | string | Image source (URL or file path) | | sx, sy, sw, sh | number | Source crop rectangle (optional) | | imageSmoothing | boolean | Enable/disable image smoothing when scaling (default: true). Set to false for pixel art. | | imageSmoothingQuality | "low" \| "medium" \| "high" | Quality of image smoothing (default: "low") |

<Text>

Renders text.

import React from 'react';
import { Text } from 'react-tela';

export function App() {
  return (
    <Text x={10} y={10} fontSize={24} fontFamily="Geist" fill="#333" stroke="rgba(0,0,0,0.1)">
      Hello world!
    </Text>
  );
}

Text example

| Prop | Type | Default | Description | |------|------|---------|-------------| | children | string \| number | — | Text content | | fontSize | number | 24 | Font size in pixels | | fontFamily | string | "sans-serif" | Font family | | fontWeight | string | "" | Font weight | | fill | string | — | Fill color | | stroke | string | — | Stroke color | | lineWidth | number | — | Stroke width | | textAlign | CanvasTextAlign | "start" | Horizontal alignment | | textBaseline | CanvasTextBaseline | "top" | Vertical baseline | | letterSpacing | number | — | Extra spacing between letters (px) | | wordSpacing | number | — | Extra spacing between words (px) | | direction | CanvasDirection | — | Text direction ("ltr", "rtl", "inherit") | | fontKerning | CanvasFontKerning | — | Font kerning ("auto", "normal", "none") | | fontStretch | CanvasFontStretch | — | Font stretch (e.g. "condensed", "expanded") | | fontVariantCaps | CanvasFontVariantCaps | — | Font variant caps (e.g. "small-caps", "all-petite-caps") | | maxWidth | number | — | Maximum width before wrapping/truncating | | lineHeight | number | 1.2 | Line height as a multiplier of fontSize | | overflow | 'wrap' \| 'ellipsis' \| 'clip' | 'wrap' | How to handle text exceeding maxWidth |

Multiline / Word Wrap

When maxWidth is set, text automatically wraps to fit. Use overflow to control behavior:

import React from 'react';
import { Rect, Text } from 'react-tela';

export function App() {
  return (
    <>
      <Rect width={500} height={120} fill="#f8f8f8" />
      <Text x={10} y={10} fontSize={14} fontFamily="Geist" fill="#333" maxWidth={150} lineHeight={1.4}>
        This is a long paragraph that will automatically wrap to fit within the maxWidth.
      </Text>
      <Text x={180} y={10} fontSize={14} fontFamily="Geist" fill="#333" maxWidth={150} overflow="ellipsis">
        This text will be truncated with an ellipsis when it overflows.
      </Text>
      <Text x={350} y={10} fontSize={14} fontFamily="Geist" fill="#333" maxWidth={150} overflow="clip">
        This text will be hard-clipped at the boundary edge.
      </Text>
      <Text x={60} y={105} fontSize={10} fontFamily="Geist" fill="#999">wrap (default)</Text>
      <Text x={235} y={105} fontSize={10} fontFamily="Geist" fill="#999">ellipsis</Text>
      <Text x={415} y={105} fontSize={10} fontFamily="Geist" fill="#999">clip</Text>
    </>
  );
}

Multiline / word wrap example

Explicit newline characters (\n) are always respected, even without maxWidth.

<Group>

Groups child components into a sub-canvas with its own coordinate system. Children render relative to the group's position.

import React from 'react';
import { Group, Rect, Text } from 'react-tela';

export function App() {
  return (
    <Group x={50} y={20} width={200} height={80} rotate={5}>
      <Rect width={200} height={80} fill="purple" alpha={0.5} />
      <Text fontSize={24} fontFamily="Geist" fill="white">Inside a group</Text>
    </Group>
  );
}

Group example

Viewport / Scrolling

A <Group> can act as a scrollable viewport into a larger content area. Set contentWidth and/or contentHeight to define the inner canvas dimensions independently from the rendered width/height, then use scrollTop/scrollLeft to control which portion of the content is visible.

| Prop | Type | Default | Description | |------|------|---------|-------------| | contentWidth | number | — | Width of the inner content canvas. When larger than width, enables horizontal scrolling. | | contentHeight | number | — | Height of the inner content canvas. When larger than height, enables vertical scrolling. | | scrollTop | number | 0 | Vertical offset into the content. Out-of-bounds values show empty space (useful for overscroll effects). | | scrollLeft | number | 0 | Horizontal offset into the content. Out-of-bounds values show empty space (useful for overscroll effects). |

import React, { useState, useEffect } from 'react';
import { Group, Rect, Text } from 'react-tela';

export function App() {
  const [scrollTop, setScrollTop] = useState(0);

  // Animate scrolling
  useEffect(() => {
    const id = setInterval(() => {
      setScrollTop((prev) => (prev + 1) % 200);
    }, 16);
    return () => clearInterval(id);
  }, []);

  return (
    <Group width={200} height={100} contentHeight={300} scrollTop={scrollTop}>
      <Rect width={200} height={100} fill="red" />
      <Rect y={100} width={200} height={100} fill="green" />
      <Rect y={200} width={200} height={100} fill="blue" />
    </Group>
  );
}

When contentWidth/contentHeight are not set, the <Group> renders its children at full size without any viewport clipping.

Key optimization: When only scrollTop/scrollLeft change (and children haven't changed), the inner canvas is not re-rendered — only the source coordinates of the drawImage call change. This makes scrolling essentially free.

borderRadius prop

When set, the Group clips its composited output to a rounded rectangle. Accepts a single number for uniform corners or an array [tl, tr, br, bl] for per-corner radii — the same API as <RoundRect>.

<Group x={50} y={20} width={200} height={80} borderRadius={10}>
  <Rect width={200} height={80} fill="purple" />
</Group>

{/* Bottom corners only */}
<Group x={50} y={120} width={200} height={80} borderRadius={[0, 0, 10, 10]}>
  <Rect width={200} height={80} fill="blue" />
</Group>

<Canvas>

Creates a sub-canvas that you can draw to imperatively via getContext('2d'). Useful for mixing imperative canvas drawing with React components.

import React from 'react';
import { Canvas, useParent } from 'react-tela';

export function App() {
  const root = useParent();
  return (
    <Canvas
      width={120}
      height={80}
      ref={(ref) => {
        if (!ref) return;
        const ctx = ref.getContext("2d");
        if (!ctx) return;
        const grad = ctx.createLinearGradient(0, 0, 120, 80);
        grad.addColorStop(0, "#3498db");
        grad.addColorStop(1, "#9b59b6");
        ctx.fillStyle = grad;
        ctx.fillRect(0, 0, 120, 80);
        ctx.fillStyle = "white";
        ctx.beginPath();
        ctx.arc(60, 40, 25, 0, Math.PI * 2);
        ctx.fill();
        root.queueRender();
      }}
    />
  );
}

Canvas example

Shape Props

<Rect>, <Circle>, <Ellipse>, <Arc>, <Path>, <Line>, <BezierCurve>, and <QuadraticCurve> all share these shape-specific props:

| Prop | Type | Description | |------|------|-------------| | fill | string | Fill color | | fillRule | CanvasFillRule | Fill rule ("nonzero" or "evenodd") | | stroke | string | Stroke color | | lineWidth | number | Stroke width (default: 1) | | lineCap | CanvasLineCap | Line cap style | | lineJoin | CanvasLineJoin | Line join style | | lineDash | number[] | Dash pattern | | lineDashOffset | number | Dash offset | | miterLimit | number | Miter limit | | clip | boolean | Clip children to this shape | | clipRule | CanvasFillRule | Clip rule |

Hooks

useDimensions()

Returns { width, height } of the parent canvas or group.

function FullSizeRect() {
  const { width, height } = useDimensions();
  return <Rect width={width} height={height} fill="black" />;
}

useLayout()

Returns { x, y, width, height } from the nearest LayoutContext. Used internally by components to support the <Flex> layout system.

useParent()

Returns the parent Root context. Useful for advanced use cases like accessing the underlying canvas context or queuing manual re-renders.

useTextMetrics(text, fontFamily?, fontSize?, fontWeight?)

Measures text and returns a TextMetrics object. Useful for positioning or sizing based on text content.

import React from 'react';
import { Group, Rect, Text, useDimensions, useTextMetrics } from 'react-tela';

function CenteredText({ children }: { children: string }) {
  const dims = useDimensions();
  const metrics = useTextMetrics(children, "Geist", 24);
  return (
    <Text
      x={dims.width / 2 - metrics.width / 2}
      y={dims.height / 2 - 12}
      fontSize={24}
      fontFamily="Geist"
      fill="white"
    >
      {children}
    </Text>
  );
}

export function App() {
  return (
    <Group x={0} y={0} width={400} height={60}>
      <Rect width={400} height={60} fill="#2c3e50" />
      <CenteredText>Centered with useTextMetrics</CenteredText>
    </Group>
  );
}

useTextMetrics example

Related Packages

Exports

| Entry Point | Exports | |------------|---------| | react-tela | Rect, Circle, Ellipse, Arc, Path, Line, Image, Text, Group, Canvas, useDimensions, useLayout, useParent, useTextMetrics, LayoutContext | | react-tela/render | render |

What is "tela"? 🇧🇷

The word "tela" is the Portuguese word for "canvas" or "screen".

tela [ˈtɛla] (feminine noun)

  1. (de pintar) canvas
  2. (cinema, telecommunications) screen

Since the name react-canvas was already taken, react-tela was a fun alternative.

Prior Art

A few other React renderers for <canvas> already exist, so why another?

react-tela is designed to make as few assumptions about the runtime environment as possible. Other renderers assume they are running in a web browser, or possibly Node.js. This module only interacts with the canvas node it is provided, and never makes any assumptions about anything "outside" of the node.

  • react-art — Appears to be an official solution (code lives in the React monorepo), but documentation and examples are basically non-existent and it does not seem to be actively maintained.
  • react-canvas — Perfect name. Nice API. Probably one of the original React <canvas> implementations. Has not been updated in years.
  • react-konva — Awesome and very mature. Relies on react-dom, which is pretty large and assumes a DOM is available.

License

MIT