座標自動維持ボタン(離席用)
by
cutfloss
05/03 [2026/05/03 22:36:02]
押すとその場でグルグル回り続けるボタンが表示される
@@ -6,68 +6,84 @@
javascript:(function(){
if(document.getElementById('afk-rotate-btn')) return;
- /* 1. ボタン作成(誤タップ防止のため画面上部中央) */
+ /* 1. ボタン作成(🌀マークのみの最小サイズ) */
const btn = document.createElement('button');
btn.id = 'afk-rotate-btn';
- btn.innerHTML = '🌀 ぐるぐる OFF';
+ btn.innerHTML = '🌀';
Object.assign(btn.style, {
position: 'fixed',
- top: '15px',
- left: '50%',
- transform: 'translateX(-50%)',
+ top: '60px', /* 左上から少し下げた位置 */
+ left: '10px',
zIndex: '10000',
- padding: '10px 20px',
- backgroundColor: 'rgba(15, 23, 42, 0.9)',
+ width: '40px',
+ height: '40px',
+ lineHeight: '40px',
+ textAlign: 'center',
+ backgroundColor: 'rgba(0, 0, 0, 0.3)', /* 控えめな透過黒 */
color: '#fff',
- border: '2px solid #334155',
- borderRadius: '25px',
- fontSize: '14px',
- fontWeight: 'bold',
+ border: '1px solid rgba(255, 255, 255, 0.5)',
+ borderRadius: '50%',
+ fontSize: '20px',
cursor: 'pointer',
- boxShadow: '0 4px 15px rgba(0,0,0,0.5)'
+ padding: '0',
+ outline: 'none'
});
document.body.appendChild(btn);
let rotateInterval = null;
let step = 0;
- /* 上・右・下・左 の方向ベクトル */
- const dirs = [
- {x: 0, y: -1}, {x: 1, y: 0}, {x: 0, y: 1}, {x: -1, y: 0}
- ];
+ const dirs = [{x: 0, y: -1}, {x: 1, y: 0}, {x: 0, y: 1}, {x: -1, y: 0}];
- const toggle = () => {
+ /* 停止・解除関数 */
+ const stopRotate = () => {
+ if (!rotateInterval) return;
+ clearInterval(rotateInterval);
+ rotateInterval = null;
+ btn.style.backgroundColor = 'rgba(0, 0, 0, 0.3)';
+ btn.style.borderColor = 'rgba(255, 255, 255, 0.5)';
+
+ if(typeof inputState !== 'undefined') {
+ inputState.dx = 0;
+ inputState.dy = 0;
+ inputState.drawing = false;
+ if(typeof sendInput === 'function') sendInput();
+ }
+ };
+
+ /* 開始関数 */
+ const startRotate = (e) => {
+ if (e) e.stopPropagation();
if (rotateInterval) {
- clearInterval(rotateInterval);
- rotateInterval = null;
- btn.innerHTML = '🌀 ぐるぐる OFF';
- btn.style.borderColor = '#334155';
- /* 停止時は入力をリセット */
- if(typeof inputState !== 'undefined') {
- inputState.dx = 0;
- inputState.dy = 0;
- inputState.drawing = false;
- if(typeof sendInput === 'function') sendInput();
- }
- } else {
- btn.innerHTML = '🌀 ぐるぐる稼働中!';
- btn.style.borderColor = '#22c55e'; /* 稼働中は緑に */
- rotateInterval = setInterval(() => {
- if (typeof inputState !== 'undefined' && typeof sendInput === 'function') {
- const d = dirs[step % 4];
- /* 1. 入力値を書き換え */
- inputState.dx = d.x;
- inputState.dy = d.y;
- inputState.drawing = true;
-
- /* 2. ゲーム側の送信ロジックを発火させる */
- sendInput();
-
- step++;
- }
- }, 200); /* 0.2秒刻み */
+ stopRotate();
+ return;
}
+ btn.style.backgroundColor = 'rgba(255, 0, 0, 0.6)'; /* 稼働中は赤く光る */
+ btn.style.borderColor = '#fff';
+ rotateInterval = setInterval(() => {
+ if (typeof inputState !== 'undefined' && typeof sendInput === 'function') {
+ const d = dirs[step % 4];
+ inputState.dx = d.x;
+ inputState.dy = d.y;
+ inputState.drawing = true;
+ sendInput();
+ step++;
+ }
+ }, 200);
};
- btn.onclick = toggle;
- console.log('Rotate Script Active: Logic sync with client-game.js');
+ btn.onclick = startRotate;
+
+ /* 2. 操作介入による自動解除のリスナー */
+ /* タッチ・マウス・キーボードのいずれかがあったら停止 */
+ const inputEvents = ['touchstart', 'mousedown', 'keydown'];
+ inputEvents.forEach(eventType => {
+ window.addEventListener(eventType, (e) => {
+ /* ぐるぐるボタン自体へのクリックは無視して、それ以外の操作で停止 */
+ if (e.target !== btn && rotateInterval) {
+ stopRotate();
+ }
+ }, { capture: true, passive: true });
+ });
+
+ console.log('🌀 Minimal Auto-Rotate: Input-interruption mode active.');
})();
/*
* @title 座標自動維持ボタン(離席用)
* @description 押すとその場でグルグル回り続けるボタンが表示される
* @private
*/
javascript:(function(){
if(document.getElementById('afk-rotate-btn')) return;
/* 1. ボタン作成(🌀マークのみの最小サイズ) */
const btn = document.createElement('button');
btn.id = 'afk-rotate-btn';
btn.innerHTML = '🌀';
Object.assign(btn.style, {
position: 'fixed',
top: '60px', /* 左上から少し下げた位置 */
left: '10px',
zIndex: '10000',
width: '40px',
height: '40px',
lineHeight: '40px',
textAlign: 'center',
backgroundColor: 'rgba(0, 0, 0, 0.3)', /* 控えめな透過黒 */
color: '#fff',
border: '1px solid rgba(255, 255, 255, 0.5)',
borderRadius: '50%',
fontSize: '20px',
cursor: 'pointer',
padding: '0',
outline: 'none'
});
document.body.appendChild(btn);
let rotateInterval = null;
let step = 0;
const dirs = [{x: 0, y: -1}, {x: 1, y: 0}, {x: 0, y: 1}, {x: -1, y: 0}];
/* 停止・解除関数 */
const stopRotate = () => {
if (!rotateInterval) return;
clearInterval(rotateInterval);
rotateInterval = null;
btn.style.backgroundColor = 'rgba(0, 0, 0, 0.3)';
btn.style.borderColor = 'rgba(255, 255, 255, 0.5)';
if(typeof inputState !== 'undefined') {
inputState.dx = 0;
inputState.dy = 0;
inputState.drawing = false;
if(typeof sendInput === 'function') sendInput();
}
};
/* 開始関数 */
const startRotate = (e) => {
if (e) e.stopPropagation();
if (rotateInterval) {
stopRotate();
return;
}
btn.style.backgroundColor = 'rgba(255, 0, 0, 0.6)'; /* 稼働中は赤く光る */
btn.style.borderColor = '#fff';
rotateInterval = setInterval(() => {
if (typeof inputState !== 'undefined' && typeof sendInput === 'function') {
const d = dirs[step % 4];
inputState.dx = d.x;
inputState.dy = d.y;
inputState.drawing = true;
sendInput();
step++;
}
}, 200);
};
btn.onclick = startRotate;
/* 2. 操作介入による自動解除のリスナー */
/* タッチ・マウス・キーボードのいずれかがあったら停止 */
const inputEvents = ['touchstart', 'mousedown', 'keydown'];
inputEvents.forEach(eventType => {
window.addEventListener(eventType, (e) => {
/* ぐるぐるボタン自体へのクリックは無視して、それ以外の操作で停止 */
if (e.target !== btn && rotateInterval) {
stopRotate();
}
}, { capture: true, passive: true });
});
console.log('🌀 Minimal Auto-Rotate: Input-interruption mode active.');
})();
- Permalink
- このページへの個別リンクです。
- RAW
- 書かれたコードへの直接のリンクです。
- Packed
- 文字列が圧縮された書かれたコードへのリンクです。
- Userscript
- Greasemonkey 等で利用する場合の .user.js へのリンクです。
- Loader
- @require やソースコードが長い場合に多段ロードする Loader コミのコードへのリンクです。
- Metadata
- コード中にコメントで @xxx と書かれたメタデータの JSON です。