diff options
| author | Yasutake Yohei <61961825+yasutakeyohei@users.noreply.github.com> | 2026-10-07 23:09:40 +0900 |
|---|---|---|
| committer | Yasutake Yohei <61961825+yasutakeyohei@users.noreply.github.com> | 2026-10-07 23:09:40 +0900 |
| commit | bc2821adb11a30244fc4663f4fafb756877d9508 (patch) | |
| tree | fea8d30d2eb1e67f895097dbf7ec4d152361243e /public/bluebey-studio/index.html | |
| parent | 0d50c5ede0812ba7b67b775c9cd0bf52d7b65e02 (diff) | |
bluebey-studio: public/ の外へ移動し非公開化
Diffstat (limited to 'public/bluebey-studio/index.html')
| -rw-r--r-- | public/bluebey-studio/index.html | 241 |
1 files changed, 0 insertions, 241 deletions
diff --git a/public/bluebey-studio/index.html b/public/bluebey-studio/index.html deleted file mode 100644 index 7111b9b..0000000 --- a/public/bluebey-studio/index.html +++ /dev/null @@ -1,241 +0,0 @@ -<!doctype html> -<html lang="ja"> -<head> -<meta charset="utf-8"> -<meta name="viewport" content="width=device-width, initial-scale=1"> -<title>ぶるべー スタジオ</title> -<meta name="description" content="小平市のマスコットキャラクタ「ぶるべー」の3Dモデルをブラウザで自由に動かせる無料のスタジオです。ポーズや表情を変えて、3Dのまま・PNG画像・線画として書き出せます。インストール不要です。"> -<!-- An inline empty icon stops the browser from requesting /favicon.ico, which would otherwise show up as a confusing 404 in the console. --> -<link rel="icon" href="data:,"> -<link rel="stylesheet" href="src/style.css"> -<script> -/* - * Boot watchdog. Runs as a plain (non-module) script so it is always executed, - * even when the module entry point cannot be loaded at all. It turns a silent - * "loading forever" screen into an explanation of what went wrong. - */ -(function () { - var failures = []; - var started = Date.now(); - window.addEventListener('error', function (event) { - var target = event.target; - if (target && (target.src || target.href)) { - failures.push((target.tagName === 'SCRIPT' ? 'JS: ' : 'ファイル: ') + (target.src || target.href)); - } - }, true); - window.__bluebeyFailures = failures; - - var timer = setInterval(function () { - if (window.__bluebeyReady) { - clearInterval(timer); - var done = document.getElementById('loading-error'); - if (done && done.dataset.watchdog) done.textContent = ''; - return; - } - if (Date.now() - started < 9000) return; - clearInterval(timer); - - var text = document.getElementById('loading-text'); - var box = document.getElementById('loading-error'); - if (text) text.textContent = '読み込みが止まっています。'; - if (!box) return; - box.dataset.watchdog = '1'; - - var lines = []; - if (location.protocol === 'file:') { - lines.push('このページはファイルとして直接開かれています(' + location.protocol + ')。'); - lines.push('ブラウザの制限により、この開き方ではJavaScriptモジュールを読み込めません。'); - lines.push(''); - lines.push('次のどちらかで開いてください。'); - lines.push('1) bluebey-studio フォルダで python serve.py を実行し、'); - lines.push(' 表示された http://127.0.0.1:8000/ を開く(推奨)'); - lines.push('2) bluebey-studio-standalone.html をダブルクリックする(1ファイル版)'); - } else { - lines.push('必要なファイルを読み込めませんでした。ページの場所とフォルダの中身を確認してください。'); - lines.push('(配布するときは bluebey-studio フォルダの中身をすべてコピーしてください)'); - } - if (failures.length) { - lines.push(''); - lines.push('読み込めなかったもの:'); - for (var i = 0; i < failures.length && i < 8; i++) lines.push('・' + failures[i]); - } - box.textContent = lines.join('\n'); - }, 1000); -})(); -</script> -<script type="importmap"> -{ - "imports": { - "three": "./vendor/three/build/three.module.js", - "three/addons/": "./vendor/three/examples/jsm/", - "opentype.js": "./vendor/lib/opentype.module.js" - } -} -</script> -</head> -<body> - -<script> -/* - * On a small screen the control panel is a bottom sheet (see the small-screen - * rules in src/style.css): the 3D view fills the screen until the user opens it, - * so it starts folded away there. Setting the class before the panel is parsed - * keeps the closed sheet from flashing on the first paint. - */ -if (window.matchMedia('(max-width: 768px), (max-height: 500px) and (pointer: coarse)').matches) { - document.body.classList.add('panel-hidden'); -} -</script> - -<div id="stage"> - <canvas id="view" aria-label="3D viewport"></canvas> -</div> - -<header id="topbar"> - <h1>ぶるべー スタジオ</h1> - <div class="topbar-actions"> - <button type="button" id="btn-shot" title="今の見た目をPNGで保存 (S)">PNG保存</button> - <button type="button" id="btn-copy" title="画像をクリップボードにコピー (C)">コピー</button> - <button type="button" id="btn-help" title="ヘルプ (?)">?</button> - <button type="button" id="btn-panel" title="パネルの表示/非表示 (Tab)">≡</button> - </div> -</header> - -<aside id="panel" aria-label="コントロールパネル"></aside> - -<p id="viewport-hint" class="viewport-hint"> - ドラッグ:回転 / ホイール:ズーム / 右ドラッグ:移動 / ぶるべーをドラッグ:移動 -</p> -<p id="viewport-hint-touch" class="viewport-hint"> - 2本指でドラッグ:カメラ移動(ぶるべーは動きません)/ 2本指をつまむ:ズーム<br> - ぶるべーの上で1本指:ぶるべーを移動(上下で高さも)/ 何もない所で1本指:回転 -</p> - -<div id="toast" role="status" aria-live="polite"></div> - -<div id="loading"> - <div class="loading-box"> - <div class="loading-spinner"></div> - <p id="loading-text">ぶるべーを読み込んでいます…</p> - <p id="loading-error"></p> - </div> -</div> - -<div id="help" hidden> - <div class="help-sheet"> - <button type="button" class="help-close" id="help-close" aria-label="閉じる">×</button> - <h2>ぶるべー スタジオの使い方</h2> - - <h3>これは何?</h3> - <p> - <code>bluebey.glb</code>(ぶるべーの3Dモデル)をブラウザで読み込み、自由にポーズをとらせ、 - 顔の表情を自由に作って、2Dの画像(PNG)として書き出せるスタジオです。 - 元の手描きパーツ(GIMPで作った目と口の画像)もそのまま使えます。 - </p> - - <h3>ポーズ</h3> - <ul> - <li>右パネルの「ポーズ」でボーンを選び、X/Y/Zのスライダーを動かします。</li> - <li>モデルをクリックすると、その場所にいちばん近いボーンが選ばれます。</li> - <li>ギズモ(回転の輪)を直接ドラッグしても回せます。</li> - <li>スライダーの値は「休めの姿勢(レストポーズ)」からの差分です。<code>0,0,0</code> で元の姿勢。</li> - <li>気に入ったポーズは「ポーズを保存」でファイルに残せます。</li> - </ul> - - <h3>スマホでの操作</h3> - <ul> - <li><b>2本指でぐりぐり</b>:カメラ(見ている基準点)を動かします。ぶるべーは基準点から動きません。</li> - <li><b>2本指をつまむ(ピンチ)</b>:ズーム(寄る/引く)。</li> - <li><b>ぶるべーの上で1本指でぐりぐり</b>:ぶるべーを基準点から動かします。上下に動かすと高さも変わります。</li> - <li><b>何もない所で1本指でぐりぐり</b>:カメラが回ります。</li> - <li>パネル(下のシート)は、上の横線(ハンドル)をドラッグすると上下に動かせます。</li> - </ul> - - <h3>表情</h3> - <ul> - <li>目:開き具合(まばたき・ウインク)、目線(上下左右)、瞳の大きさ、ハイライト、閉じ方の種類。</li> - <li>口:笑いの深さ、口の開き、舌、口角の点、太さ、色。</li> - <li>「目線パッド」をドラッグすると、選んだ側の目線が動きます(「左右を連動させる」中は両目)。</li> - <li>プリセット(にっこり・ウインク・びっくり…)から始めると早いです。</li> - <li>「手描きパーツを使う」を選ぶと、元のGIMP製パーツに切り替わります。</li> - </ul> - - <h3>3Dのまま/2Dにする</h3> - <ul> - <li>「表示」で リアル/フラット(トゥーン)/線画/線画(透明) を切り替えます。</li> - <li>線画は輪郭線+白ぬり。線の太さと色を変えられます。</li> - <li>「正投影」にすると遠近のゆがみがなくなり、図面のような絵になります。</li> - <li>背景は透明・白・好きな色から選べます。<code>PNG保存</code>は透明のまま保存できます。</li> - </ul> - - <h3>キーボード</h3> - <ul class="keys"> - <li><kbd>S</kbd> PNG保存</li> - <li><kbd>C</kbd> 画像をコピー</li> - <li><kbd>Tab</kbd> パネルの表示/非表示</li> - <li><kbd>?</kbd> このヘルプ</li> - <li><kbd>1</kbd>–<kbd>5</kbd> カメラの向き(正面・斜め・横・後ろ・俯瞰)</li> - <li><kbd>R</kbd> ポーズをリセット</li> - <li><kbd>G</kbd> ギズモの切り替え</li> - <li><kbd>Space</kbd> 生きている演出(ゆれ・まばたき)の開始/停止</li> - </ul> - - <h3>書き出しのヒント</h3> - <ul> - <li>PNGは「書き出しサイズ」を2倍・3倍にすると高解像度になります(印刷やスライド用)。</li> - <li>ポーズと表情の全設定は「設定を保存」でJSONに残せます。READMEも参照してください。</li> - </ul> - </div> -</div> - -<div id="start-notice" hidden> - <div class="start-sheet" role="dialog" aria-modal="true" aria-labelledby="start-title"> - <h2 id="start-title">ご利用の前に</h2> - <p>このスタジオは、市政・政治活動とは関係のない個人的な制作物です。</p> - <p>このスタジオで作成した画像などは、自由に使っていただけます。ただし、商用利用やそのほか特殊な使い方をされる場合は、小平市の確認が必要ですので、このサイトの<a href="/contact/" target="_blank" rel="noopener">お問い合わせ</a>からご連絡ください。</p> - <p>次のような使い方はご遠慮ください。</p> - <ul> - <li>公序良俗に反する目的での利用</li> - <li>ぶるべーのイメージを損なうような利用(たとえば、攻撃的・差別的・性的・過激な利用、誹謗中傷など)</li> - <li>反社会的勢力や違法行為に関わる利用</li> - <li>政治的意図があるように見える利用(例:特定の政治家や政党をぶるべーが応援しているような表現)</li> - <li>特定の宗教・宗派への勧誘や布教と誤解される利用</li> - <li>小平市が公認・推薦・後援しているように見える利用(市の公式発表や公文書と誤認させる利用を含む)</li> - <li>特定の企業・商品・思想・団体を、ぶるべーや小平市が推薦・保証しているように見える利用</li> - </ul> - <p>ぶるべーの著作権は小平市にあります。このスタジオと3Dモデルは作者(安竹洋平)が自作したものです。</p> - <div class="start-actions"> - <label class="start-skip"><input type="checkbox" id="start-skip"> 次回から表示しない</label> - <button type="button" id="start-ok" class="start-ok">同意して使う</button> - </div> - </div> -</div> - -<script> -/* - * 起動時のご利用について。毎回出し、「次回から表示しない」を選んだときだけ覚える。 - * アプリが立ち上がってから出す(読み込みに失敗したときは、その説明を隠さないため)。 - * モジュールが読めない場合でも動くよう、module ではない普通のスクリプト。 - */ -(function () { - var KEY = 'bluebey.usage-notice.v1'; - var box = document.getElementById('start-notice'); - if (!box) return; - try { if (localStorage.getItem(KEY) === 'skip') return; } catch (error) {} - var timer = setInterval(function () { - if (!window.__bluebeyReady) return; - clearInterval(timer); - box.hidden = false; - }, 150); - document.getElementById('start-ok').addEventListener('click', function () { - box.hidden = true; - try { - if (document.getElementById('start-skip').checked) localStorage.setItem(KEY, 'skip'); - } catch (error) {} - }); -})(); -</script> - -<script type="module" src="src/main.js"></script> -</body> -</html> |
