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

js-cloudimage-3d-view

v1.1.0

Published

Interactive 3D model viewer with orbit controls, lighting, and accessibility

Readme


Why js-cloudimage-3d-view?

Embedding 3D models on the web shouldn't require writing Three.js boilerplate. This library handles all the heavy lifting:

  • Drop-in viewer — one line of JS or a single HTML element to display any 3D model
  • Multi-format — GLTF/GLB, OBJ+MTL, STL, FBX, 3DS, and AMF out of the box
  • Accessible by default — WCAG 2.1 AA compliant with keyboard navigation and screen reader support
  • Framework-agnostic — works with vanilla JS, React, or any framework
  • Full camera controls — orbit, zoom, pan, auto-rotate with damping
  • Animations — play, pause, stop, speed control for embedded animations
  • Lighting & environment — 3-point lighting, HDR/EXR environment maps, tone mapping
  • Lightweight — ~14 KB gzipped (Three.js as peer dependency)

Features

  • Orbit controls — mouse/touch rotation, zoom, and pan with configurable damping
  • Auto-rotate — configurable speed with pause-on-interact and resume delay
  • Animation playback — play/pause/stop/speed control with toolbar buttons
  • 3-point lighting — ambient + key/fill/rim lights, fully configurable
  • Environment maps — HDR/EXR support with PMREM, optional background display
  • Tone mapping — ACES filmic, Reinhard, Cineon, Linear, or None
  • Shadows — soft shadow ground plane with configurable opacity
  • Screenshot — capture and download the current view as PNG
  • Fullscreen — one-click fullscreen toggle
  • Themes — light and dark themes
  • Progress bar — loading progress with accessible ARIA attributes
  • Ctrl+scroll zoom — optional scroll interception with tooltip hint
  • DRACO compression — automatic DRACO decoder for compressed GLTF/GLB
  • 40+ data attributes — fully declarative HTML configuration
  • WCAG 2.1 AA — keyboard navigation, ARIA attributes, focus management, reduced motion
  • React wrapper — component, hook, and ref API with SSR safety
  • TypeScript — full type definitions with strict mode

Installation

npm install js-cloudimage-3d-view three

CDN

<script src="https://unpkg.com/three/build/three.min.js"></script>
<script src="https://scaleflex.cloudimg.io/v7/plugins/js-cloudimage-3d-view/1.1.0/js-cloudimage-3d-view.min.js?vh=114f86&func=proxy"></script>

Quick Start

JavaScript API

import CI3DView from 'js-cloudimage-3d-view';

const viewer = new CI3DView('#my-container', {
  src: 'https://example.com/model.glb',
  autoRotate: true,
  shadows: true,
  theme: 'dark',
  onLoad(instance) {
    console.log('Model loaded!', instance.getAnimations());
  },
});

HTML Data-Attributes

<div
  data-ci-3d-src="https://example.com/model.glb"
  data-ci-3d-auto-rotate
  data-ci-3d-shadows
  data-ci-3d-theme="dark"
  style="width: 100%; height: 500px;"
></div>

<script>
  CI3DView.autoInit();
</script>

Supported Formats

| Format | Extensions | Notes | |--------|-----------|-------| | glTF / GLB | .gltf, .glb | Recommended. Supports DRACO compression, animations, PBR materials | | OBJ | .obj | Optional .mtl material file via mtlSrc config | | STL | .stl | Mesh-only, auto-assigned standard material | | FBX | .fbx | Supports skeletal animations | | 3DS | .3ds | Legacy Autodesk format | | AMF | .amf | Additive manufacturing format |

API Reference

Constructor

new CI3DView(element: HTMLElement | string, config: CI3DViewConfig)

Config

| Option | Type | Default | Description | |--------|------|---------|-------------| | src | string | — | Model URL (required) | | mtlSrc | string | — | MTL material URL (for OBJ models) | | alt | string | '' | Accessible description | | controls | boolean | true | Enable orbit controls | | zoom | boolean | true | Enable zoom | | pan | boolean | true | Enable pan | | scrollToZoom | boolean | false | Allow direct scroll-to-zoom (default: Ctrl+scroll) | | autoRotate | boolean | false | Enable auto-rotation | | autoRotateSpeed | number | 0.5 | Auto-rotate speed | | autoRotateDelay | number | 3000 | Delay (ms) before auto-rotate resumes after interaction | | damping | boolean | true | Enable inertia damping | | dampingFactor | number | 0.1 | Damping strength (0-1) | | zoomMin | number | — | Minimum zoom distance | | zoomMax | number | — | Maximum zoom distance | | polarAngleMin | number | 0 | Min vertical angle in degrees (0 = top) | | polarAngleMax | number | 180 | Max vertical angle in degrees (180 = bottom) | | theme | 'light' \| 'dark' | 'light' | Theme | | background | string | 'transparent' | Background color | | showProgress | boolean | true | Show loading progress bar | | fullscreenButton | boolean | true | Show fullscreen button | | screenshotButton | boolean | false | Show screenshot button | | screenshotFilename | string | 'screenshot' | Screenshot download filename | | screenshotScale | number | 2 | Screenshot resolution multiplier | | resetCameraButton | boolean | true | Show reset camera button | | autoRotateButton | boolean | true | Show auto-rotate toggle button | | animationButtons | boolean | true | Show animation play/pause/stop buttons | | toolbarPosition | string | 'bottom-center' | 'bottom-left', 'bottom-center', or 'bottom-right' | | shadows | boolean | true | Enable shadow ground plane | | shadowOpacity | number | 0.3 | Shadow opacity (0-1) | | shadowBlur | number | 2 | Shadow blur amount | | environmentMap | string | — | HDR/EXR environment map URL | | environmentBackground | boolean | false | Show environment map as scene background | | toneMapping | string | 'aces' | 'none', 'linear', 'reinhard', 'aces', or 'filmic' | | toneMappingExposure | number | 1.0 | Tone mapping exposure | | draco | boolean | true | Enable DRACO decoder for GLTF | | dracoDecoderPath | string | — | Custom DRACO decoder path | | animation | number \| string | — | Animation index or name to play on load | | autoPlayAnimation | boolean | false | Auto-play first animation on load | | animationSpeed | number | 1.0 | Animation playback speed | | cameraPosition | [x, y, z] | — | Custom initial camera position | | cameraFov | number | 45 | Camera field of view (degrees) | | cameraTarget | [x, y, z] | — | Custom camera look-at target | | pixelRatio | number | 2 | Max device pixel ratio | | antialias | boolean | true | Enable antialiasing | | lighting | LightingConfig | — | Custom lighting configuration |

Callbacks

| Callback | Type | Description | |----------|------|-------------| | onLoadStart | () => void | Fired when model loading begins | | onProgress | (progress: number) => void | Loading progress (0-1) | | onLoad | (instance) => void | Fired when model is loaded and ready | | onError | (error: Error) => void | Fired on load error | | onCameraChange | (position, target) => void | Fired when camera moves | | onFullscreenChange | (isFullscreen: boolean) => void | Fired on fullscreen toggle |

Instance Methods

// Model
instance.loadModel(src: string, mtlSrc?: string): Promise<void>
instance.update(config: Partial<CI3DViewConfig>): void
instance.destroy(): void

// Camera
instance.setCameraPosition(x: number, y: number, z: number): void
instance.setCameraTarget(x: number, y: number, z: number): void
instance.resetCamera(): void

// Auto-rotate
instance.setAutoRotate(enabled: boolean): void

// Animation
instance.playAnimation(indexOrName?: number | string): void
instance.pauseAnimation(): void
instance.stopAnimation(): void
instance.setAnimationSpeed(speed: number): void
instance.getAnimations(): string[]

// Screenshot
instance.screenshot(scale?: number): string       // Returns data URL
instance.downloadScreenshot(filename?: string, scale?: number): void

// Fullscreen
instance.enterFullscreen(): void
instance.exitFullscreen(): void
instance.isFullscreen(): boolean

// Three.js access
instance.getThreeObjects(): { scene, camera, renderer, controls, model }
instance.getElements(): { container, canvas }

Static Methods

CI3DView.autoInit(root?: HTMLElement): CI3DViewInstance[]

React Usage

import { CI3DViewer, useCI3DView } from 'js-cloudimage-3d-view/react';

// Component
function ModelViewer() {
  return (
    <CI3DViewer
      src="/model.glb"
      autoRotate
      shadows
      theme="dark"
      style={{ width: '100%', height: 500 }}
      onLoad={(instance) => console.log('Loaded!', instance.getAnimations())}
    />
  );
}

// Ref API
function ModelViewer() {
  const ref = useRef<CI3DViewerRef>(null);
  return (
    <>
      <CI3DViewer ref={ref} src="/model.glb" shadows />
      <button onClick={() => ref.current?.resetCamera()}>Reset</button>
      <button onClick={() => ref.current?.downloadScreenshot()}>Screenshot</button>
    </>
  );
}

// Hook
function ModelViewer() {
  const { containerRef, instance, ready } = useCI3DView({
    src: '/model.glb',
    autoRotate: true,
    shadows: true,
  });

  return (
    <>
      <div ref={containerRef} style={{ width: '100%', height: 500 }} />
      {ready && <button onClick={() => instance.current?.resetCamera()}>Reset</button>}
    </>
  );
}

Lighting Configuration

Customize the 3-point lighting system:

new CI3DView('#el', {
  src: '/model.glb',
  lighting: {
    ambientIntensity: 0.4,
    ambientColor: '#ffffff',
    keyLight: {
      intensity: 1.0,
      color: '#ffffff',
      position: [5, 10, 7],
      castShadow: true,
    },
    fillLight: {
      intensity: 0.5,
      position: [-5, 5, 5],
    },
    rimLight: {
      intensity: 0.3,
      position: [0, 5, -10],
    },
  },
});

Environment Maps

Use HDR or EXR environment maps for realistic reflections:

new CI3DView('#el', {
  src: '/model.glb',
  environmentMap: '/studio.hdr',
  environmentBackground: true,
  toneMapping: 'aces',
  toneMappingExposure: 1.2,
});

Data Attributes

All config options can be set via HTML data attributes with the data-ci-3d- prefix:

<div
  data-ci-3d-src="/model.glb"
  data-ci-3d-auto-rotate
  data-ci-3d-auto-rotate-speed="1.0"
  data-ci-3d-shadows
  data-ci-3d-shadow-opacity="0.5"
  data-ci-3d-theme="dark"
  data-ci-3d-background="#1a1a1a"
  data-ci-3d-environment-map="/studio.hdr"
  data-ci-3d-tone-mapping="aces"
  data-ci-3d-camera-position="[0, 2, 5]"
  data-ci-3d-auto-play-animation
  data-ci-3d-animation-speed="0.5"
  data-ci-3d-scroll-to-zoom
  style="width: 100%; height: 500px;"
></div>

Boolean attributes are true when present (empty value), or accept "true", "1", "yes".

Accessibility

  • All interactive elements are keyboard-navigable
  • Arrow keys rotate the model
  • + / - zoom in/out
  • 0 resets camera
  • R toggles auto-rotate
  • F toggles fullscreen
  • Space toggles animation playback
  • Escape exits fullscreen
  • Tab / Shift+Tab navigates toolbar buttons
  • role="application" with aria-describedby keyboard instructions
  • aria-label on all buttons, aria-pressed on toggles
  • Progress bar with role="progressbar" and aria-valuenow
  • prefers-reduced-motion disables auto-rotate and uses instant transitions

Browser Support

| Browser | Version | |---------|---------| | Chrome | 80+ | | Firefox | 80+ | | Safari | 14+ | | Edge | 80+ |

Requires WebGL 2.0 support.

License

MIT


Support

If this library helped your project, consider buying me a coffee!