Skip to content

Hosting a spinner

Warning

Online spinner publishing is only available to PRO subscription plan users.

Overview

This page describes how to host the Maverick Excelsior Spinner component on your own website for embedding interactive 360° product views.

Self-hosting the spinner is the preferred method if you wish to:

  • Embed spinners directly in your website.
  • Have full control over the spinner's branding, appearance and behavior.
  • Avoid CORS restrictions and improve loading performance.

A perfect example of this can be found in our Jewelry Catalog Showcase:

Jewelry Catalog Showcase - Gemstones

Advantages of self-hosting

Advantage Explanation
True embedding The spinner becomes part of your page, not an external frame.
No CORS issues Hosting everything on your domain avoids cross-origin problems.
Customization Full control over styling and integration with your site.
Performance Faster loading when spinner and images are on the same domain.

Step-by-step guide

1. Include the spinner library

Add to your webpage the spinner JavaScript library from the CDN link below:

<script src="https://cdn.jsdelivr.net/gh/randomcontrol/webex-spinner@latest/webex-spinner.min.js"></script>

2. Create the HTML structure

Add a canvas element where the spinner will be rendered:

<div class="spinner-container">
    <canvas id="product-spinner" width="800" height="800"></canvas>
    <div class="spinner-loading">Loading...</div>
</div>

3. Add CSS styling

.spinner-container {
    position: relative;
    max-width: 800px;
    margin: 0 auto;
}

.spinner-container canvas {
    width: 100%;
    height: auto;
    display: block;
    cursor: grab;
}

.spinner-container canvas:active {
    cursor: grabbing;
}

.spinner-loading {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    background: rgba(0,0,0,0.7);
    color: white;
    padding: 10px 20px;
    border-radius: 5px;
}

4. Initialize the spinner

document.addEventListener('DOMContentLoaded', function() {
    const spinner = new webex_spinner_c(
        document.getElementById('product-spinner'),
        {
            images: [
                '/products/ring/atlas_0000.jpg',
                '/products/ring/atlas_0001.jpg',
                '/products/ring/atlas_0002.jpg',
                // ... add all your atlas images.
            ],
            poster: '/products/ring/poster.jpg',
            nx: 4,  // tiles per row.
            ny: 1,  // tiles per column.
            fps: 30,
            autoplay: true,
            draggable: true,
            loop: true,
            preload_amount: 15,
            on_full_preload_finished: function() {
                document.querySelector('.spinner-loading').style.display = 'none';
            }
        }
    );
});

5. Advanced configuration

Generating image arrays dynamically

Instead of listing each image manually, you can generate the array:

// Generate image array for 135 frames.
const frameCount = 135;
const imagePath = '/products/ring/';
const images = Array.from({length: frameCount}, (_, i) => {
    const frameNumber = String(i).padStart(4, '0');
    return `${imagePath}atlas_${frameNumber}.jpg`;
});

Multiple spinners on one page

const spinner_1 = new webex_spinner_c(
    document.getElementById('spinner-1'),
    {
        images: generateImageArray('/products/ring/', 135),
        poster: '/products/ring/poster.jpg',
        // ... other options.
    }
);

const spinner_2 = new webex_spinner_c(
    document.getElementById('spinner-2'),
    {
        images: generateImageArray('/products/bracelet/', 120),
        poster: '/products/bracelet/poster.jpg',
        // ... other options.
    }
);

Here's an example of how to create a gallery with multiple spinners:

<div class="product-gallery">
    <div class="product-item" data-spinner-path="/products/ring/" data-frames="135">
        <canvas id="spinner-ring" width="400" height="400"></canvas>
        <h3>Diamond Ring</h3>
    </div>

    <div class="product-item" data-spinner-path="/products/necklace/" data-frames="120">
        <canvas id="spinner-necklace" width="400" height="400"></canvas>
        <h3>Pearl Necklace</h3>
    </div>
</div>

<script>
document.querySelectorAll('.product-item').forEach(item => {
    const canvas = item.querySelector('canvas');
    const path = item.dataset.spinnerPath;
    const frames = parseInt(item.dataset.frames);

    // Generate image array.
    const images = Array.from({length: frames}, (_, i) => {
        return `${path}atlas_${String(i).padStart(4, '0')}.jpg`;
    });

    // Initialize spinner.
    new webex_spinner_c(canvas, {
        images: images,
        poster: `${path}poster.jpg`,
        nx: 4,
        ny: 1,
        autoplay: false,  // Don't autoplay in gallery.
        draggable: true
    });
});
</script>

API reference

Constructor options

Option Type Default Description
images Array required Array of atlas image URLs
poster String false URL of poster image
nx Number 4 Tiles per row in atlas
ny Number 1 Tiles per column in atlas
fps Number 30 Frames per second
autoplay Boolean true Start spinning automatically
draggable Boolean true Enable mouse/touch drag
loop Boolean true Loop the animation
preload_amount Number 0 Frames to preload before starting

Methods

// Control playback.
spinner.play();
spinner.stop();

// Set options.
spinner.set_reverse(true);  // Reverse playback direction.
spinner.set_option('fps', 60);  // Change frame rate.

// Get information.
const currentFrame = spinner.get_current_frame();
const totalFrames = spinner.get_total_frames();
const isRunning = spinner.is_running();

// Destroy spinner.
spinner.destroy();

Events

The spinner dispatches custom events you can listen to:

canvas.addEventListener('webex-spinner:loading-progress', (e) => {
    console.log(`Loading: ${e.detail.progress * 100}%`);
});

canvas.addEventListener('webex-spinner:full-preload-finished', () => {
    console.log('All frames loaded');
});

Troubleshooting

Common issues

  1. CORS errors: Ensure images are served from the same domain or have proper CORS headers.
  2. Performance issues: Reduce frame count or image quality for smoother playback.
  3. Mobile touch not working: Ensure the canvas has touch-action: none CSS property.

Tip

For production use, always test your spinners on various devices and connection speeds to ensure optimal performance for all users.