aboutsummaryrefslogtreecommitdiffhomepage
path: root/public/bluebey-studio/index.html
diff options
context:
space:
mode:
authorYasutake Yohei <61961825+yasutakeyohei@users.noreply.github.com>2026-10-07 23:09:40 +0900
committerYasutake Yohei <61961825+yasutakeyohei@users.noreply.github.com>2026-10-07 23:09:40 +0900
commitbc2821adb11a30244fc4663f4fafb756877d9508 (patch)
treefea8d30d2eb1e67f895097dbf7ec4d152361243e /public/bluebey-studio/index.html
parent0d50c5ede0812ba7b67b775c9cd0bf52d7b65e02 (diff)
bluebey-studio: public/ の外へ移動し非公開化
Diffstat (limited to 'public/bluebey-studio/index.html')
-rw-r--r--public/bluebey-studio/index.html241
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>