import React, { useState, useEffect } from 'react'; import { Ruler, ArrowUpRight, ArrowDownRight, RefreshCw, Calculator, Info, Edit3, Target } from 'lucide-react'; const App = () => { // 基本設定の状態 (すべてmm単位) // 初期値を文字列で管理することで、入力時の挙動を制御しやすくする const [totalLength, setTotalLength] = useState('10000'); const [totalHeightDiff, setTotalHeightDiff] = useState('100'); const [slopeDirection, setSlopeDirection] = useState(1); // 1: 下がり, -1: 上がり // 基点設定 const [baseLevel, setBaseLevel] = useState('75'); const [baseSign, setBaseSign] = useState(1); // 1: プラス, -1: マイナス // 測りたい場所 (最小50, 最大10000, 5mm刻み) const [currentDist, setCurrentDist] = useState('5000'); // 計算結果 const [finalLevel, setFinalLevel] = useState(0); const [slopePercent, setSlopePercent] = useState(0); // 数値変換用ヘルパー const num = (val) => Number(val) || 0; // 計算ロジック useEffect(() => { const L = num(totalLength); const H = num(totalHeightDiff); const D = num(currentDist); const B = num(baseLevel); if (L > 0) { const slopeRatio = H / L; const deltaH = slopeRatio * D * (slopeDirection === 1 ? -1 : 1); const startLevel = B * baseSign; const result = startLevel + deltaH; setFinalLevel(result.toFixed(1)); const percent = (H / L) * 100; setSlopePercent(percent.toFixed(2)); } }, [totalLength, totalHeightDiff, slopeDirection, baseLevel, baseSign, currentDist]); // 入力フォーカス時の処理(全選択) const handleFocus = (e) => { e.target.select(); }; // リセット const resetFields = () => { setTotalLength('10000'); setTotalHeightDiff('100'); setSlopeDirection(1); setBaseLevel('75'); setBaseSign(1); setCurrentDist('5000'); }; return (
{/* ヘッダー */}

勾配レベル計算 V4

Kawabata-Gumi Edition

{/* 1. 全体条件 (mm) */}

全体の条件 (mm)

勾配: {slopePercent}%
setTotalLength(e.target.value)} className="w-full bg-slate-950 border border-slate-700 rounded-xl py-2.5 px-3 focus:ring-2 focus:ring-blue-500 text-lg font-bold text-white transition-all outline-none" /> mm
setTotalHeightDiff(e.target.value)} className="w-full bg-slate-950 border border-slate-700 rounded-xl py-2.5 px-3 focus:ring-2 focus:ring-blue-500 text-lg font-bold text-white transition-all outline-none" /> mm
{/* 2. 基点の設定 */}

基点(0mm地点)の設計レベル

setBaseLevel(e.target.value)} className="w-full h-full bg-slate-950 border border-slate-700 rounded-xl py-2 px-4 focus:ring-2 focus:ring-blue-500 text-4xl font-black text-white text-right outline-none transition-all" /> Start Lv mm
{/* 3. 測りたい場所 */}

測りたい場所 (5mm単位)

STEP: 5mm
setCurrentDist(e.target.value)} className="w-full h-4 bg-slate-800 rounded-lg appearance-none cursor-pointer accent-blue-500 border border-slate-700" />
setCurrentDist(e.target.value)} className="w-full bg-slate-950 border-2 border-slate-800 rounded-3xl py-6 px-8 text-center text-5xl font-black text-white focus:ring-8 focus:ring-blue-500/10 focus:border-blue-500 outline-none shadow-2xl transition-all" placeholder="タップして入力" /> mm
{/* 結果表示エリア */}

現在の設計レベル

{num(finalLevel) > 0 ? '+' : ''} {finalLevel} mm
勾配率: {slopePercent}%
比率: 1/{Math.round(num(totalLength) / (num(totalHeightDiff) || 1))}
{/* 視覚プレビュー */}
{/* グリッド線 */} {/* 勾配メインライン */} {/* 現在位置ピン */} {num(totalLength) > 0 && ( )} START END
); }; export default App;