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

@aivue/360-spin

v2.0.1

Published

Interactive 360-degree product image spin component for Vue.js with AI-powered generation

Readme

@aivue/360-spin

Interactive 360-degree product image spin component for Vue.js with AI-powered generation

npm version npm downloads License: MIT

✨ Features

360° Viewer

  • 🖼️ Static to Animated: Show static product image by default, animate on hover/tap
  • 🎬 Multiple Modes: Support for GIF animations or frame sequences
  • 📱 Mobile Optimized: Touch and drag to spin on mobile devices
  • 🎯 Flexible Triggers: Hover, click, or auto-play animations
  • 🛍️ E-commerce Ready: Perfect for product cards, carousels, and search results
  • Performance: Preloading and optimized frame rendering
  • 🎨 Customizable: Full control over styling and behavior
  • Accessible: Keyboard navigation and screen reader support

🤖 AI 360° Generator (NEW!)

  • 📤 Upload & Generate: Upload a single product image and AI generates 360° views
  • 🎨 OpenAI DALL-E 3: High-quality AI-generated frames at different angles
  • 🔄 Stability AI Support: Alternative AI provider for generation
  • 🎯 Customizable: Choose frame count (12/24/36/72), background color, quality
  • 📊 Real-time Progress: Track generation progress with live updates
  • 💾 Download Frames: Export all generated frames for use elsewhere
  • 🔍 Vision Analysis: GPT-4 Vision analyzes your product for better results

📦 Installation

npm install @aivue/360-spin

🚀 Quick Start

Basic Usage (GIF Mode)

<template>
  <Ai360Spin
    static-image="/images/product-static.jpg"
    animated-image="/images/product-360.gif"
    alt="Product 360 view"
    width="400px"
    height="400px"
  />
</template>

<script setup>
import { Ai360Spin } from '@aivue/360-spin';
import '@aivue/360-spin/360-spin.css';
</script>

Frame Sequence Mode

<template>
  <Ai360Spin
    static-image="/images/product-static.jpg"
    :animated-image="frameUrls"
    mode="frames"
    :frame-rate="30"
    enable-drag-spin
    alt="Product 360 view"
  />
</template>

<script setup>
import { Ai360Spin } from '@aivue/360-spin';
import '@aivue/360-spin/360-spin.css';

const frameUrls = [
  '/images/frame-001.jpg',
  '/images/frame-002.jpg',
  '/images/frame-003.jpg',
  // ... more frames
];
</script>

Product Card Integration

<template>
  <div class="product-card">
    <Ai360Spin
      :static-image="product.image"
      :animated-image="product.spin360"
      container-class="ai-360-spin--card"
      :alt="product.name"
      trigger="hover"
    />
    <h3>{{ product.name }}</h3>
    <p>{{ product.price }}</p>
  </div>
</template>

🤖 AI 360° Generator

Generate 360-degree product views from a single image using AI:

<template>
  <Ai360Generator
    provider="openai"
    api-key="your-openai-api-key"
    :auto-save-api-key="true"
    :show-frame-preview="true"
    @frames-generated="handleFramesGenerated"
    @generation-complete="handleComplete"
  />
</template>

<script setup>
import { Ai360Generator } from '@aivue/360-spin';
import '@aivue/360-spin/360-spin.css';

function handleFramesGenerated(frames) {
  console.log('Generated frames:', frames);
  // Use frames with Ai360Spin component
}

function handleComplete(frames) {
  console.log('Generation complete!', frames.length, 'frames');
}
</script>

Programmatic AI Generation

Use the AI generator utility directly:

import { AI360Generator } from '@aivue/360-spin';

const generator = new AI360Generator(
  {
    provider: 'openai',
    apiKey: 'your-api-key',
    frameCount: 36,
    backgroundColor: 'white',
    quality: 80,
    useVisionAnalysis: true
  },
  (progress) => {
    console.log(`Progress: ${progress.percentage}%`);
    console.log(`Status: ${progress.status}`);
    console.log(`Frame ${progress.currentFrame}/${progress.totalFrames}`);
  }
);

// Generate from File
const file = document.querySelector('input[type="file"]').files[0];
const result = await generator.generate(file);
console.log('Generated frames:', result.frames);
console.log('Product description:', result.productDescription);

// Or generate from base64 image
const base64Image = 'data:image/jpeg;base64,...';
const result = await generator.generate(base64Image);

📖 API Reference

Ai360Spin Component

Props

| Prop | Type | Default | Description | |------|------|---------|-------------| | staticImage | string | required | URL of the static product image | | animatedImage | string \| string[] | required | GIF URL or array of frame URLs | | mode | 'gif' \| 'frames' \| 'auto' | 'auto' | Animation mode | | trigger | 'hover' \| 'click' \| 'auto' | 'hover' | How to start animation | | width | string \| number | '100%' | Container width | | height | string \| number | 'auto' | Container height | | alt | string | 'Product 360 view' | Alt text for images | | frameRate | number | 30 | FPS for frame sequence | | loop | boolean | true | Whether to loop animation | | direction | 'clockwise' \| 'counterclockwise' | 'clockwise' | Spin direction | | preload | boolean | true | Preload images on mount | | showLoading | boolean | true | Show loading indicator | | loadingText | string | 'Loading...' | Loading text | | enableDragSpin | boolean | true | Enable drag to spin on mobile | | dragSensitivity | number | 10 | Pixels per frame for drag | | containerClass | string | '' | CSS class for container | | imageClass | string | '' | CSS class for images |

Events

| Event | Payload | Description | |-------|---------|-------------| | animation-start | void | Fired when animation starts | | animation-end | void | Fired when animation ends | | loaded | void | Fired when images are loaded | | error | Error | Fired on loading error | | frame-change | number | Fired when frame changes (frames mode) |

Ai360Generator Component

Props

| Prop | Type | Default | Description | |------|------|---------|-------------| | provider | 'openai' \| 'stability' | 'openai' | AI provider for generation | | apiKey | string | '' | API key (can be saved in localStorage) | | autoSaveApiKey | boolean | true | Auto-save API key to localStorage | | showFramePreview | boolean | true | Show preview grid of generated frames |

Events

| Event | Payload | Description | |-------|---------|-------------| | frames-generated | string[] | Emitted when user clicks "Use These Frames" | | generation-start | void | Emitted when generation starts | | generation-complete | string[] | Emitted when generation completes | | generation-error | Error | Emitted on generation error |

AI360Generator Class

Constructor Options

interface AI360GeneratorConfig {
  provider?: 'openai' | 'stability';
  apiKey: string;
  frameCount?: number; // Default: 36
  backgroundColor?: 'white' | 'transparent' | 'black' | 'custom';
  customBackgroundColor?: string;
  quality?: number; // 0-100, Default: 80
  imageSize?: '1024x1024' | '1024x1792' | '1792x1024';
  model?: string; // Default: 'dall-e-3' for OpenAI
  useVisionAnalysis?: boolean; // Default: true
  promptTemplate?: string; // Custom prompt template
}

Methods

  • generate(imageFile: File | string): Promise<AI360GenerationResult>
    • Generates 360° frames from a single image
    • Returns frames, product description, and metadata

🎨 Styling

The component comes with default styles, but you can customize them:

/* Custom container styles */
.ai-360-spin {
  border-radius: 12px;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
}

/* Custom loading spinner */
.ai-360-spin__spinner {
  border-top-color: #your-brand-color;
}

/* Custom hint badge */
.ai-360-spin__hint {
  background: rgba(your-color, 0.9);
}

Pre-built Classes

  • .ai-360-spin--card - Optimized for product cards (1:1 aspect ratio)
  • .ai-360-spin--grid - Optimized for grid layouts (4:3 aspect ratio)
  • .ai-360-spin--carousel - Optimized for carousels (full width/height)

💡 Use Cases

E-commerce Product Listings

<div class="product-grid">
  <div v-for="product in products" :key="product.id" class="product-item">
    <Ai360Spin
      :static-image="product.thumbnail"
      :animated-image="product.spin360Gif"
      container-class="ai-360-spin--grid"
      :alt="product.name"
    />
  </div>
</div>

Product Detail Page

<Ai360Spin
  :static-image="product.mainImage"
  :animated-image="product.frames"
  mode="frames"
  :frame-rate="60"
  enable-drag-spin
  width="600px"
  height="600px"
  trigger="click"
/>

Carousel Integration

<div class="carousel">
  <div v-for="item in carouselItems" :key="item.id" class="carousel-slide">
    <Ai360Spin
      :static-image="item.image"
      :animated-image="item.spin"
      container-class="ai-360-spin--carousel"
      trigger="hover"
    />
  </div>
</div>

🔧 Advanced Usage

Using the Composable

<script setup>
import { use360Spin } from '@aivue/360-spin';

const config = {
  staticImage: '/product.jpg',
  animatedImage: frameUrls,
  mode: 'frames',
  frameRate: 30
};

const {
  isAnimating,
  isLoading,
  currentFrameIndex,
  startAnimation,
  stopAnimation,
  preloadImages
} = use360Spin(config, emit);

// Manually control animation
function handleCustomTrigger() {
  if (isAnimating.value) {
    stopAnimation();
  } else {
    startAnimation();
  }
}
</script>

Programmatic Control

<template>
  <div>
    <Ai360Spin
      ref="spinRef"
      :static-image="staticImg"
      :animated-image="frames"
      trigger="click"
      @animation-start="onStart"
      @animation-end="onEnd"
      @frame-change="onFrameChange"
    />
    <button @click="toggleSpin">Toggle Spin</button>
  </div>
</template>

<script setup>
import { ref } from 'vue';
import { Ai360Spin } from '@aivue/360-spin';

const spinRef = ref(null);

function onStart() {
  console.log('Animation started');
}

function onEnd() {
  console.log('Animation ended');
}

function onFrameChange(frameIndex) {
  console.log('Current frame:', frameIndex);
}
</script>

📱 Mobile Optimization

The component automatically optimizes for mobile devices:

  • Touch Events: Drag to spin through frames
  • Performance: Optimized rendering for mobile browsers
  • Responsive: Adapts to different screen sizes
  • Touch Feedback: Visual feedback for touch interactions

🎯 Best Practices

Frame Sequence Tips

  1. Frame Count: Use 24-36 frames for smooth rotation
  2. Image Size: Optimize images (WebP format recommended)
  3. Naming: Use sequential naming (frame-001.jpg, frame-002.jpg, etc.)
  4. Preloading: Enable preloading for better UX

Performance Optimization

<Ai360Spin
  :static-image="product.thumbnail"
  :animated-image="product.frames"
  :preload="true"
  :frame-rate="24"
  loading-image="/placeholder.jpg"
/>

Accessibility

<Ai360Spin
  :static-image="product.image"
  :animated-image="product.spin"
  :alt="`360-degree view of ${product.name}`"
  role="img"
  aria-label="Interactive product view"
/>

🌐 Browser Support

  • Chrome/Edge (latest)
  • Firefox (latest)
  • Safari (latest)
  • Mobile browsers (iOS Safari, Chrome Mobile)

📄 License

MIT © reachbrt

🤝 Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

🔗 Links

📝 Changelog

See CHANGELOG.md for details.


Made with ❤️ by reachbrt