fCanvas Library
website·Indexed 30 days ago
https://fcanvas.js.orgA powerful 2D canvas library designed for minimal rendering and diverse shapes. It features a hierarchical structure using Stage, Layer, Group, and Shape classes, and incorporates a reactivity system with computed properties and watchers similar to Vue. The library includes a variety of built-in shapes such as Arc, Circle, Line, and Text, as well as plugins for animations (@fcanvas/animate), WebWorker support (@fcanvas/worker), and Node.js integration (@fcanvas/node).
What's inside fCanvas
- fCanvas is a 2D canvas library optimized for high-performance animations, transitions, and event handling for desktop and mobile applications. It supports layering, filtering, caching, and independent transformation (moving, scaling, rotating) of shapes. Unlike Konva.js and Fabric.js, fCanvas automatically stops redrawing when no changes are detected to increase performance and reduces the API surface to minimize package size (approximately 80kB, or 60kB when used with Vue).
Overview of fCanvas 2D Canvas Library
fCanvas is a high-performance 2D canvas library designed for minimal rendering and diverse shape support. It is a rewrite of KonvaJS aimed at reducing redundant APIs and improving redrawing performance. Key capabilities include high-performance animations, transitions, button nesting, layering, filtering, caching, and event handling for both desktop and mobile applications. It supports independent moving, scaling, and rotating of shapes, maintaining performance even with thousands of objects on stage. A primary performance optimization is that it automatically stops redrawing when no changes have occurred.Overview of the fcanvas 2D library
fcanvas is a powerful 2D canvas JavaScript library designed for minimal rendering and providing a diverse set of shapes. It is built to be approachable by using options that closely align with CSS standards. To optimize performance and minimize redraws, it leverages the reactive capabilities of@vue/reactivity.Use watch to monitor specific reactive sources
watch()is lazy by default and only invokes the callback when the specified source changes. UnlikewatchEffect, it allows you to be specific about which state triggers the effect and provides access to both the new and old values.Supported sources:
- A ref
- A getter function returning a value
- A reactive object (automatically enables
deep: true) - An array of the above
The callback receives:
(newValue, oldValue, onCleanup). If watching multiple sources,newValueandoldValueare arrays corresponding to the source array.const state = reactive({ count: 0 }) const countRef = ref(0) // 1. Watching a getter watch(() => state.count, (newVal, oldVal) => { console.log(`Count changed from ${oldVal} to ${newVal}`) }) // 2. Watching a ref watch(countRef, (newVal, oldVal) => { /* ... */ }) // 3. Watching multiple sources watch([countRef, () => state.count], ([newCount, newStateCount], [oldCount, oldStateCount]) => { /* ... */ })Group shapes for simultaneous display and caching
TheGroupclass allows you to group multipleShapeobjects together. It shares a similar API toShapebut includes.add(node: Shape)and.delete(node: Shape)methods, similar to those found inLayer. Grouping static elements is recommended to improve performance by avoiding continuous redrawing of elements that do not change.import { Stage, Layer, Group, Circle } from "fcanvas" const stage = new Stage().mount("#app") const layer = new Layer().addTo(stage) const group = new Group().addTo(layer) const circle = new Circle({ x: 20, y: 20, radius: 20, fill: "red" }).addTo( group )Understand the Shape base class
TheShapeclass serves as the base for all display elements in fcanvas, includingArcandRect. All child elements inherit the methods and properties defined in theShapeclass.Understand the fcanvas node hierarchy
fcanvas uses a virtual node hierarchy similar to the DOM. The root is the
Stage, which contains one or moreLayerobjects. EachLayercan contain shapes, groups of shapes, or nested groups.Every
Layermanages two<canvas>renderers: a scene renderer (visible to the user) and a hit graph renderer (a hidden canvas used for high-performance event detection).Handle high-resolution (HiDPI) displays to prevent blurriness
To prevent canvas items from appearing blurry on high-resolution displays, scale the canvas internal dimensions by the device pixel ratio (DPR) while maintaining the CSS display size.// Get the DPR and size of the canvas const dpr = window.devicePixelRatio; const rect = canvas.getBoundingClientRect(); // Set the "actual" size of the canvas canvas.width = rect.width * dpr; canvas.height = rect.height * dpr; // Scale the context to ensure correct drawing operations ctx.scale(dpr, dpr); // Set the "drawn" size of the canvas canvas.style.width = `${rect.width}px`; canvas.style.height = `${rect.height}px`;Install and initialize @fcanvas/animate
The@fcanvas/animateplugin provides animation capabilities for fcanvas by integrating GSAP. To use it, install the plugin along withfcanvasandgsap, then callinstallAnimate(Stage)to enable theAnimateclass and its.to()method.pnpm add fcanvas @fcanvas/animate gsapimport { Stage } from "fcanvas" import { installAnimate } from "@fcanvas/animate" installAnimate(Stage)Use reactive state to control fcanvas shapes
fcanvas components such asStage,Layer, andShape(e.g.,Circle) accept values as either standard primitives or reactive wrappers from the fcanvas API, such asref,reactive, andcomputed. When a reactive value is updated, the corresponding property on the canvas object updates automatically.import { ref, computed, Circle } from "fcanvas" // Define reactive state const x = ref(0) // Define a computed value based on state const y = computed(() => x.value * 2) // Pass reactive refs/computed values to the Shape constructor const circle = new Circle({ x, y }) // Updating the ref value automatically updates the circle's position x.value = 50Optimize static backgrounds using CSS
For static background images, avoid rendering them on the canvas every tick. Instead, use a plain<div>element with the CSSbackgroundproperty and position it behind the canvas element.Use reactive and computed values in fcanvas components
fcanvas components (such asStage,Layer, andShape) accept property values as either primitives or reactive return values from APIs likeref,reactive, andcomputed. When a reactive dependency changes, the component property updates automatically.import { ref, computed, Circle } from "fcanvas" const x = ref(0) const y = computed(() => x.value * 2) // The Circle component accepts reactive refs and computed values const circle = new Circle({ x, y }) // Updating x.value will automatically update the circle's x and y positions x.value = 50