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

@canvas3/nuxt

v0.1.35

Published

Module for ThreeJS

Readme

Canvas3 Nuxt Module

A Nuxt module that integrates ThreeJS into your Nuxt app, providing a smooth-scroll engine, WebGL image effects, scroll-triggered animations, and a shader/animation API — all wired together through Vue directives and a global Canvas3 composable-like utility.

✨ Example use cases

Features

  • 🎬 Smooth scroll engine – Custom lerp-based scroll with speed tracking, fixed-to-parent elements, and mobile breakpoint handling.
  • 🖼 WebGL image replacement – Turn any <img> into a shader-driven ThreeJS mesh via the v-canvas3-image directive.
  • 👀 Scroll-triggered activation – Activate/deactivate elements (and their linked meshes) as they enter/leave the viewport with v-canvas3-scroll-action.
  • 🎨 Custom shader support – Bring your own vertex/fragment shaders per mesh, plus a global post-processing scroll shader pass.
  • Animation scheduler – Register callbacks that run conditionally on scroll, resize, mouse move, or custom render triggers, avoiding unnecessary renders.
  • 🖱 Mouse-reactive uniforms – Automatic uMouse / uMouseMovement uniforms updated on mouse movement for interactive shaders.
  • 📱 Responsive & reduced-motion aware – Built-in isMobile / prefersReducedMotion / disabled options to gracefully degrade.
  • 🧩 Global utility APICanvas3 import exposes scene, camera, renderer, mesh, and scroll controls anywhere in your app.
  • 🏗 Layout-based setup – Ships a ready-to-use canvas3 Nuxt layout that wraps your page content with the scroll/canvas containers.

Quick Setup

Install the module to your Nuxt application with one command:

npx nuxi module add canvas3-nuxt

That's it! You can now use the Canvas3 module in your Nuxt app ✨

1. Use the canvas3 layout

<!-- pages/index.vue -->
<script setup>
definePageMeta({ layout: 'canvas3' })
</script>

2. Enable Canvas3 in the layout

The layout exposes canvas3enabled and canvas3options props. Enable it once your options (shaders, fonts, etc.) are ready:

<!-- app.vue or a wrapping component -->
<template>
  <NuxtLayout
    :canvas3enabled="ready"
    :canvas3options="canvas3Options"
    @canvas3-ready="onReady"
  >
    <NuxtPage />
  </NuxtLayout>
</template>

<script setup>
import { ref } from 'vue'

const ready = ref(false)
const canvas3Options = {
  shaders: {
    default: { vertexShader: defaultVert, fragmentShader: defaultFrag },
    scroll: { vertexShader: scrollVert, fragmentShader: scrollFrag },
  },
  activateMeshOptions: {
    image: { uAniInImage: { value: 1, duration: 1, ease: 'power2.out' } },
  },
  canvasElement: { zIndex: -1 },
  prefersReducedMotion: false,
  isMobile: false,
  disabled: false,
}

function onReady() {
  ready.value = true
}

ready.value = true
</script>

Directives

v-canvas3-image

Converts an <img> element into a ThreeJS mesh rendered in sync with the DOM element's position, size, and scroll offset. The original image is hidden (opacity set to 0) and replaced visually by the WebGL mesh.

Requirements: must be applied to an <img> tag.

Binding value (Canvas3ImageBinding):

| Option | Type | Description | |---|---|---| | shaderName | string | Key of a custom shader registered in canvas3Options.shaders. Falls back to shaders.default. | | uniforms | MeshMaterialUniform | Extra/overriding shader uniforms merged into the material on creation and reactively on update. | | activateMeshUniforms | MeshMaterialUniform | Uniforms animated (0 → 1) when the mesh's linked scroll-action element becomes active/inactive. |

<template>
  <img
    src="/images/hero.jpg"
    alt="Hero"
    v-canvas3-image="{
      shaderName: 'wave',
      uniforms: {
        vectorVNoise: { value: [2, 2], duration: 0 },
      },
      activateMeshUniforms: {
        uAniInImage: { value: 1, duration: 1.2, ease: 'power2.out' },
      },
    }"
  >
</template>

Behavior notes:

  • Waits for the image to load (complete/load event) and for the canvas to be initiated before creating the mesh.
  • Automatically re-creates the mesh if src changes.
  • Cleans up (disposes geometry/material/texture, removes from scene) on unmount.
  • Respects canvas3options.disabled, adding a .reduced-motion class instead of creating a mesh.

v-canvas3-scroll-action

Marks an element to be tracked by the scroll engine. When the element enters/exits the configured viewport range, it toggles an active class, fires callbacks, and (optionally) activates any WebGL image meshes nested inside it (matched via data-mesh-id, set automatically by v-canvas3-image).

Binding value (scrollActionBindOptionType):

| Option | Type | Description | |---|---|---| | activateOnce | boolean | Once activated, the element is never deactivated again. | | trackOnly | boolean | Skip class toggling and mesh activation; only fires callbacks/tracking. | | activeRange | number | Fraction of viewport height used as the "active zone" (default 1, i.e. full viewport). | | activeRangeMargin | number | Extra pixel margin added to the active range for speed-tracking calculations. | | scrollSpeed | { value: number } | Applies a parallax translate based on scroll position, proportional to value. | | scrollSpeedSetTo | { value: number, duration: number } | Animates scrollSpeed.value to a new target over duration seconds via GSAP. | | fixToParent | { containerId: string, fixPosition: number, margin: number } | Pins the element's first child inside a container (by id) at a given viewport position while the container is in view. | | activateCallback | (item) => void | Called when the element becomes active. | | deactivateCallback | (item) => void | Called when the element becomes inactive (unless activateOnce). | | onScrollCallback | (item, scrollSpeed, currentPosition) => void | Called continuously while the element is in view and the page is scrolling. |

<template>
  <section
    v-canvas3-scroll-action="{
      activeRange: 0.8,
      activateCallback: onSectionActive,
      deactivateCallback: onSectionInactive,
    }"
  >
    <img src="/images/panel.jpg" alt="Panel" v-canvas3-image="{}">
  </section>
</template>

<script setup>
function onSectionActive(item) {
  console.log('Section entered view', item.elNode)
}
function onSectionInactive(item) {
  console.log('Section left view', item.elNode)
}
</script>

Parallax example:

<div v-canvas3-scroll-action="{ scrollSpeed: { value: 0.3 } }">
  <div>Moves at 0.3x scroll speed</div>
</div>

Pin-to-parent example:

<div id="stickyContainer" style="height: 200vh;">
  <div
    v-canvas3-scroll-action="{
      fixToParent: { containerId: 'stickyContainer', fixPosition: 0.5, margin: 0 },
    }"
  >
    <div>Pinned child, centered at 50% viewport while parent is in view</div>
  </div>
</div>

Global Canvas3 Utility

The module auto-imports a Canvas3 utility (via Nuxt's addImports) that exposes scene/camera/renderer access and imperative controls, independent of the directives.

| Method | Description | |---|---| | addMeshToScene(mesh) | Adds a raw ThreeJS Mesh directly to the Canvas3 scene. | | getMeshFromSceneByName(name) | Retrieves a scene object by its name. | | addImageAsMesh(imgEl, shaderName, meshId, uniforms, activateMeshUniforms) | Lower-level API used internally by v-canvas3-image; can be called manually. | | removeMesh(id) | Disposes and removes a mesh (and its material/texture) by id. | | getShaderMaterial(mesh) | Type-casts and returns a mesh's ShaderMaterial. | | addAnimationToRender(name, setup) | Registers a named animation callback (see below). | | removeAnimationFromRender(name) | Unregisters a named animation callback. | | setAnimationsToRender(state) | Globally toggles whether onAnimationsRender animations run. | | setAnimationToRender(name, state, id) | Adds/removes an animationId driving a specific animation's render state. | | setRenderDisabled(state) | Pauses/resumes the entire render loop. | | setMeshPositionsUpdate(state) | Forces continuous recalculation of image mesh positions/sizes (e.g. during layout shifts). | | resizeOnChange() | Recalculates canvas size, camera, and mesh positions — call on custom resize triggers. | | scrollTo(position, delay?) | Smoothly animates scroll to a pixel position. | | scrollToTop(delay?) | Smoothly animates scroll to the top. | | scrollToElBySelector(selector, delay?, margin?) | Scrolls to an element matched by a CSS selector. | | getScrollPosition() | Returns the current rendered scroll position. | | getScrollSpeed() | Returns the current normalized scroll speed (0–1). | | getCamera() | Returns the active THREE.PerspectiveCamera. | | getRenderer() | Returns the active THREE.WebGLRenderer. | | getScene() | Returns the active THREE.Scene. |

Animation callback example:

import { Canvas3 } from '#imports'

Canvas3.addAnimationToRender('rotateLogo', {
  onScroll: false,
  onResize: false,
  onMouseMove: true,
  onAnimationsRender: false,
  render: false,
  animationCallback: () => {
    const mesh = Canvas3.getMeshFromSceneByName('logoMesh')
    if (mesh) mesh.rotation.y += 0.01
  },
})

// later, to stop it:
Canvas3.removeAnimationFromRender('rotateLogo')

Manual scroll control example:

import { Canvas3 } from '#imports'

function goToSection() {
  Canvas3.scrollToElBySelector('#contact', 0, -80)
}

Options Reference (Canvas3OptionsType)

| Option | Type | Description | |---|---|---| | shaders | { default: Shader, scroll?: Shader, [name]: Shader } | Registry of vertex/fragment shader pairs. default is required; scroll enables the post-processing scroll-speed effect pass. | | activateMeshOptions.image | Record<string, MeshAnimation> | Default in/out uniform animations applied to image meshes on activation (e.g. uAniInImage). | | canvasElement.zIndex | number | z-index applied to the fixed WebGL canvas container. | | prefersReducedMotion | boolean | Flag to adapt behavior for reduced-motion users. | | isMobile | boolean | Flag to adapt behavior for mobile devices. | | disabled | boolean | Globally disables mesh creation; v-canvas3-image falls back to a .reduced-motion class. |

Contribution

# Install dependencies
npm install

# Generate type stubs
npm run dev:prepare

# Develop with the playground
npm run dev

# Build the playground
npm run dev:build

# Run ESLint
npm run lint

# Run Vitest
npm run test
npm run test:watch

# Release new version
npm run release