image-zoom-360 について
ECサイトの商品ページに、ズーム、360度回転、動画などのメディア機能を導入するスキルです。店舗運営者や開発者向けに、各プラットフォームの設定と独自ギャラリーの実装方法を案内します。
主な機能
- 01高解像度画像のズーム
- 02モバイルのピンチズーム指針
- 03360度回転ビューアー
- 04ギャラリー内の商品動画
- 05メディア読み込みの最適化
活用シーン
- 01ファッションや電子機器の商品詳細表示
- 02写真シーケンスによる商品回転表示
- 03商品ギャラリーでの動画表示
- 04商品ページのメディア読み込み改善
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ finsilabs/ awesome-ecommerce-skills --skill image-zoom-360インストール後、Claude Code で/image-zoom-360を入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
tile.jsonevals/360-degree-spin-viewer/criteria.jsontask.mdevals/css-lens-zoom-component/criteria.jsontask.mdevals/video-integration-and-cdn-image-optimiza/criteria.jsontask.md詳細
画像のズームと360度ビュー
概要
ホバー時の高解像度ズーム、モバイルでタッチ操作に対応したピンチズーム、画像シーケンスによる360度スピンビュー、インライン動画再生を備えた、充実した商品メディア体験を実装します。充実したメディアは、ファッション、ジュエリー、電子機器など、細部が重要なカテゴリにおいて、返品率の低下とコンバージョン率の向上につながります。
このスキルを使用する場面
- 商品の返品率が高く、視覚的な詳細情報を増やすことで返品を減らせる可能性がある場合
- ファッション、ジュエリー、電子機器など、細部が重要なカテゴリの商品詳細ページを実装する場合
- 静止画1枚から、メディアギャラリー全体へアップグレードする場合
- 360度スピン用の素材を含む商品撮影ワークフローと連携する場合
- 商品動画があり、PDP内でインライン再生できるようにする場合
基本的な手順
ステップ1:マーチャントのプラットフォームを確認し、適切な方法を選択する
| プラットフォーム | 推奨される方法 | 理由 |
|---|---|---|
| Shopify | OS2.0テーマ(Dawn、Sense)の組み込みメディア機能に加え、360度表示にはMagic Zoom PlusアプリまたはSwiper Galleryを使用します | Dawnはメディアギャラリーで商品画像、動画、3Dモデルを標準でサポートします。Magic Zoom Plus(買い切り69ドル)を追加すれば、テーマを編集せずにホバーズームと360度スピンを利用できます |
| WooCommerce | WooCommerce Product Gallery SliderまたはYITH WooCommerce Zoom Magnifier(無料版/有料版)をインストールします | WooCommerceには基本的なギャラリーが含まれています。YITH Zoom Magnifierはホバーズームとライトボックスを追加し、Product Gallery Sliderはスワイプ、サムネイル、動画のサポートを追加します |
| BigCommerce | Cornerstoneテーマに組み込まれたズーム(ホバーズームはデフォルトで有効)を使用し、スピンビュー用にMagic 360またはSirvアプリをインストールします | Cornerstoneには標準のズーム機能があります。Sirv(月額20ドル以上)は、Stencilウィジェットを備えたホスト型の360度スピンおよびズーム用CDNを提供します |
| カスタム/ヘッドレス | CSS transformによるズーム、ピンチズーム用のPointer Events API、フレームベースのスピンビューアーを備えたカスタムギャラリーコンポーネントを構築します | パフォーマンスとUXを完全に制御できます。以下の実装を参照してください |
ステップ2:商品ギャラリーを設定する
Shopify
組み込みメディアギャラリー(アプリ不要):
- 商品管理画面(Products → [product] → Media)で、画像をアップロードし、YouTube/Vimeo動画のURLを追加し、3Dモデル用の
.glbファイルをアップロードします - Shopify OS2.0テーマ(Dawn、Sense、Craft)では、すべてのメディア形式(画像、動画、3D)がギャラリーに自動表示されます
- Online Store → Themes → Customizeで商品ページのテンプレートに移動し、Product mediaセクションを見つけます:
- Image zoom(ホバー時の拡大鏡)を有効にします
- ズームの画質を高めるため、Media sizeをLargeまたはExtra Largeに設定します
- 商品動画のVideo loopingを有効にします
- バリエーションごとの画像を設定するには、Products → [product] → Variants → [variant] → Imageで画像をバリエーションに割り当てます。購入者がそのバリエーションを選択すると、ギャラリーは自動的に対応する画像に切り替わります
360度スピンビューの場合 — Magic Zoom Plus(買い切り69ドル):
- Shopify App Storeからインストールします
- スピンシーケンスの画像を、番号付きファイルとしてアップロードします(例:
product-001.jpgからproduct-036.jpgまで) - アプリが、テーマコードを変更せずに商品ページへ埋め込めるスピンビューアーウィジェットを作成します
WooCommerce
組み込みズーム(プラグイン不要):
WooCommerce には、商品ページで Zoom.js を使用した基本的な画像ズーム機能がデフォルトで含まれています。設定方法は次のとおりです。
- WooCommerce → Settings → Products → Display に移動します
- Product Images で、Zoom の動作を「有効」「無効」「内側」から設定します
- 高解像度の画像(少なくとも 1000×1000px)をアップロードします。ズームにはアップロードされた画像全体が使用されます
YITH WooCommerce Zoom Magnifier(無料+プレミアム):
- WordPress.org からインストールします
- YITH → Zoom Magnifier → Settings に移動します
- ズームの種類を設定します。Inner(画像コンテナー内で拡大)、Outer(画像の横に拡大パネルを表示)、または Lens(円形の拡大鏡がカーソルに追従)
- クリック時に全画面ズームできるよう、ライトボックスを有効にします
Product Gallery Slider(無料 — WooCommerce.com):
- インストールして有効化します
- 組み込みの WooCommerce ギャラリーに、スワイプ対応、サムネイルストリップ、全画面ライトボックスを追加します
- ギャラリー内の動画サムネイル(YouTube/Vimeo)に対応しています
360 度ビューの場合: WooCommerce 360° Image プラグイン(無料、wordpress.org)を使用します。連番のスピンフレームを、ファイル名の先頭に 360_ を付けて商品画像としてアップロードすると、プラグインがドラッグ操作で回転するビューアーを作成します。
BigCommerce
組み込みズーム(Cornerstone テーマ):
- Storefront → My Themes → Customize に移動します
- Product Page → Image で、Image zoom を有効にします(ホバーズームはデフォルトで有効です)
- ズーム品質を高めるため、Image size を「Large」に設定します。BigCommerce は画像を自動的に複数のサイズで配信します
Sirv(ホスト型 360 度スピン+ズーム CDN):
- BigCommerce App Marketplace から Sirv をインストールします
- スピンシーケンスの画像を Sirv の CDN にアップロードします。連番の画像は自動的に検出されます
- Sirv の埋め込みコードを商品説明に貼り付けるか、Sirv BigCommerce ウィジェットを使用します
- Sirv は、自動 WebP 変換を行い、すべての商品画像を CDN 経由で配信します
商品動画:
- BigCommerce の商品管理画面で、メディアセクションの Add Video をクリックし、YouTube または Vimeo の URL を貼り付けます
- 動画は商品ギャラリーにサムネイル項目として自動的に表示されます
カスタム/ヘッドレス
CSS ホバーズーム(JavaScript による画像読み込み不要):
// ZoomImage.jsx
import { useState, useRef } from 'react';
export function ZoomImage({ src, alt }) {
const [zoom, setZoom] = useState(null);
const containerRef = useRef(null);
function handleMouseMove(e) {
const rect = containerRef.current.getBoundingClientRect();
const x = ((e.clientX - rect.left) / rect.width) * 100;
const y = ((e.clientY - rect.top) / rect.height) * 100;
setZoom({ x, y });
}
return (
<div
ref={containerRef}
className="zoom-container"
onMouseMove={handleMouseMove}
onMouseLeave={() => setZoom(null)}
>
<img
src={src}
alt={alt}
className="zoom-image"
style={zoom ? {
transformOrigin: `${zoom.x}% ${zoom.y}%`,
transform: 'scale(2.5)',
} : {}}
draggable={false}
/>
</div>
);
}
.zoom-container { overflow: hidden; cursor: crosshair; aspect-ratio: 1/1; }
.zoom-image { width: 100%; height: 100%; object-fit: cover; transition: transform 0.05s linear; will-change: transform; }
360 度スピンビューアー:
// SpinViewer.jsx — preloads all frames, switches on drag
export function SpinViewer({ frames, productName = 'Product' }) {
const [frameIndex, setFrameIndex] = useState(0);
const [loaded, setLoaded] = useState(false);
const dragStart = useRef(null);
useEffect(() => {
let count = 0;
frames.forEach(src => {
const img = new Image();
img.src = src;
img.onload = () => { if (++count === frames.length) setLoaded(true); };
});
}, [frames]);
function handleDragStart(e) { dragStart.current = e.clientX ?? e.touches?.[0]?.clientX; }
function handleDragMove(e) {
if (dragStart.current === null) return;
const clientX = e.clientX ?? e.touches?.[0]?.clientX;
const delta = Math.round((clientX - dragStart.current) / 8);
if (delta !== 0) {
setFrameIndex(i => ((i + delta) % frames.length + frames.length) % frames.length);
dragStart.current = clientX;
}
}
function handleDragEnd() { dragStart.current = null; }
if (!loaded) return <div aria-label="Loading 360 view">Loading...</div>;
return (
<div
onMouseDown={handleDragStart} onMouseMove={handleDragMove}
onMouseUp={handleDragEnd} onMouseLeave={handleDragEnd}
onTouchStart={handleDragStart} onTouchMove={handleDragMove} onTouchEnd={handleDragEnd}
aria-label="360 degree product view — drag to rotate"
role="img" style={{ cursor: 'ew-resize' }}
>
<img src={frames[frameIndex]} alt={`${productName}, frame ${frameIndex + 1} of ${frames.length}`} draggable={false} />
<span aria-hidden="true" style={{ fontSize: '0.75rem', color: '#666' }}>Drag to rotate</span>
</div>
);
}
ステップ 3:パフォーマンスのためにメディアを最適化する
プラットフォームにかかわらず、次のメディアガイドラインに従ってください。
- メイン画像:ズーム品質を確保するため、長辺が最低 2000px の画像をアップロードします。プラットフォームがサムネイル用に自動的に縮小します
- 形式:プラットフォームが対応している場合は WebP 画像をアップロードします。Shopify、BigCommerce、Sirv は自動変換します。WooCommerce では Imagify または ShortPixel プラグインを使用します
- 360 度スピンフレーム:最適なフレーム数は 24~36 枚です。最適化した JPEG が 1 枚あたり 30 KB の場合、シーケンス全体で 1 MB 未満になります
- 動画:MP4 を Shopify/BigCommerce に直接アップロードするか、ホスティング費用を抑えるため YouTube/Vimeo を埋め込みます。必ずポスター画像を含めてください
- LCP(Largest Contentful Paint):メインの商品画像はほぼ常に LCP 要素になります。優先度を高くして読み込まれるようにしてください
ベストプラクティス
- Retina 画面向けには表示サイズの 2 倍で画像を配信します。それ以上大きくしないでください。幅 400px のコンテナーには 2000px ではなく 800px の画像が必要です
- WebP または AVIF 形式を使用します。同等の品質で JPEG より 30~50%小さくなります
- メイン画像を先読みします。最初の商品画像に
fetchpriority="high"とloading="eager"を追加します - メイン画像以外のメディアは遅延読み込みします。サムネイル、360 度フレームの 2 枚目以降、動画は、最初の操作後に読み込むようにします
- 360 度ビューの読み込み状態を表示します。36 フレームの事前読み込みには、モバイルで数秒かかる場合があります。進行状況インジケーターを表示してください
- ドラッグ操作にキーボードで代替できる方法を用意します。360 度スピンでは、マウスドラッグに加えて左右の矢印キーにも対応させます
- 音声付きの自動再生は避けます。ミュートでの自動再生は問題ありませんが、ほとんどのブラウザーでは音声の自動再生がブロックされます
よくある問題
| 問題 | 解決策 |
|---|---|
| Zoom の CSS transform によってレイアウトがずれます | 拡大した画像によって兄弟要素が再配置されないように、コンテナに will-change: transform と overflow: hidden を設定します |
| モバイルで 360 度回転がカクつきます | フレームの更新を requestAnimationFrame ごとに 1 回に抑えます。touchmove イベントごとに setState を呼び出さないでください |
| iOS で動画が自動再生されません | playsInline と muted 属性を追加します。iOS ではユーザー操作なしで自動再生するために両方が必要です |
| ヒーロー画像が大きいため LCP スコアが低くなります | メインの商品画像に fetchpriority="high" と loading="eager" を追加し、Lighthouse で確認します |
| 360 度表示用のアセットが大きすぎます(36 × 500 KB) | CDN を通じて、幅 800px、JPEG 品質 75 で、各フレームのサイズを 20~40 KB に抑えます |
関連スキル
- @product-page-design
- @responsive-storefront
- @accessibility-commerce
- @image-optimization-cdn