背景
以下の参考サイト
https://themecut.jp/24/final/
このサイトの中の、ウィッグ作品をマウスの横スクロールでぐるりと360°回転して確認できる動きがあったので、どうにかできないかなあと思いつつ、ちょっとやってみました。
※画像は、そのまま参考サイトのものを使用させて頂きました。
実際のコード
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>360° 回転ビューア</title>
<style>
#viewer {
width: 500px;
height: 500px;
background: url('3d.jpg') no-repeat;
background-size: 100% auto;
cursor: grab;
border: 2px solid #ccc;
margin: 20px;
}
.info {
margin: 20px;
}
</style>
</head>
<body>
<!-- マネキンを表示するエリア -->
<div id="viewer"></div>
<div class="info">
<p>現在のフレーム: <span id="frameNumber">0</span> / 46</p>
<p>マウスホイールまたは横ドラッグで回転</p>
</div>
<script>
const viewer = document.getElementById("viewer");
const frameNumberDisplay = document.getElementById("frameNumber");
const frameCount = 46; // フレーム数(画像内のコマ数)
let currentFrame = 0; // 現在表示中のフレーム番号
let isDragging = false; // マウスドラッグ中かどうかの判定
let startX = 0; // ドラッグ開始時のX座標
// フレームを更新する関数
function updateFrame(frame) {
const frameHeight = viewer.clientHeight; // ビューアの高さ(画像の高さ)を取得
// 無限回転を可能にする正規化
// フレーム番号を0からframeCount-1の範囲に正規化
const normalizedFrame = ((frame % frameCount) + frameCount) % frameCount;
console.log(`Normalized Frame: ${normalizedFrame}`);
// 背景位置を更新(縦方向にずらして別のフレームを表示)
viewer.style.backgroundPosition = `0px -${normalizedFrame * frameHeight}px`
// 現在のフレーム番号を表示
frameNumberDisplay.textContent = normalizedFrame;
}
// マウスドラッグで回転(横ドラッグ対応)
// ドラッグ開始
viewer.addEventListener("mousedown", (e) => {
isDragging = true; // ドラッグ開始フラグ
startX = e.clientX; // 開始位置のX座標を記録
viewer.style.cursor = "grabbing"; // カーソルを「つかんでいる」形に
});
// ドラッグ中
document.addEventListener("mousemove", (e) => {
if (isDragging) {
const deltaX = e.clientX - startX; // 移動距離を計算
const sensitivity = 2; // 感度調整
if (Math.abs(deltaX) > sensitivity) {
const direction = deltaX > 0 ? 1 : -1; // 右ドラッグで進む、左ドラッグで戻る
currentFrame += direction;
updateFrame(currentFrame);
startX = e.clientX; // 開始位置を更新
}
}
});
// ドラッグ終了
document.addEventListener("mouseup", () => {
isDragging = false; // ドラッグ終了
viewer.style.cursor = "grab"; // カーソルを元に戻す
});
// 初期表示
updateFrame(0);
</script>
</body>
</html>
苦労点
360°以上回転させると、表示されなくなって真っ白になる現象が起こってたのですが、AIのclaudeを利用し、以下の理論でなんとか切り抜けました。
無限ループ正規化の仕組み
frameが47になったら → 0に戻る
frameが-1になったら → 45に戻る
結果:0〜45の範囲で無限ループ
通常の範囲内(最大値の46フレーム内)
frame = 10の場合
((10 % 46) + 46) % 46
= (10 + 46) % 46
= 56 % 46
= 10
frame = 45の場合
((45 % 46) + 46) % 46
= (45 + 46) % 46
= 91 % 46
= 45
範囲(最大値の46フレーム)を超えた場合
frame = 46の場合(1周目)
((46 % 46) + 46) % 46
= (0 + 46) % 46
= 46 % 46
= 0 ← 0に戻る!
frame = 47の場合
((47 % 46) + 46) % 46
= (1 + 46) % 46
= 47 % 46
= 1
frame = 92の場合(2周目)
((92 % 46) + 46) % 46
= (0 + 46) % 46
= 46 % 46
= 0 ← また0に戻る!
負の数(逆回転)
frame = -1の場合
((-1 % 46) + 46) % 46
= (-1 + 46) % 46
= 45 % 46
= 45 ← 45に戻る!
frame = -2の場合
((-2 % 46) + 46) % 46
= (-2 + 46) % 46
= 44 % 46
= 44
frame = -47の場合
((-47 % 46) + 46) % 46
= (-1 + 46) % 46
= 45 % 46
= 45
メモ程度ですので、さらに追記等すると思います!