ウェブフロント
- angular
- corewebvitals
- editorconfig
- gatsby
- hls
- html
- javascript
querySelectorAllで取得した要素は配列ではないらしい
JavaScript 配列内のオブジェクトの更新ってどうする?
デバッグ関数とかnullチェック関数をutil/index.tsにおいとけば楽なことに今頃気づいた。
ブラウザからジャイロセンサーを使ってみる
JS 画像のアップロード、プレビュー機能を実装
「数値から各桁の値を取り出す処理」って言われたら数学的な処理が一番に思い浮かぶけど、JSならそんなことなかった。
Callback時代の関数をPromise化する
個人的実装されてほしいECMA Script Proposal
JavaScriptのprototypeを使う
音声をなみなみさせる
AudioWorkletとAudioWorkletProcessorを使って音声のビジュアライゼーション
- next
- nuxt
- playwright
- prettier
- react
- reactnative
- tensorflowjs
- tools
- typescript
- wasm
- websocket
- ポエム
- 開発環境
サーバー
その他
ReactNative StopWatch作るの結構むずい
はじめに
ストップウォッチ作るコードってラップ機能付きだとあまりないし, React Hooksってなるとほんとに見つからないよね
コード
const [now, setNow] = useState(0);
const [start, setStart] = useState(0);
const [intervalId, setIntervalId] = useState<number>();
const [laps, setLaps] = useState<number[]>([]);
useEffect(() => {
// component will unmount
return () => clearInterval(intervalId);
}, []);
const handleStart = () => {
const id = setInterval(() => {
setNow(new Date().getTime());
}, 100);
setIntervalId(id);
setStart(new Date().getTime());
setLaps([0]);
};
const handleStop = () => {
clearInterval(intervalId);
const [firstLap, ...other] = laps;
setLaps([firstLap + now - start, ...other]);
setStart(0);
setNow(0);
};
const handleResume = () => {
setStart(new Date().getTime());
setNow(new Date().getTime());
const id = setInterval(() => {
setNow(new Date().getTime());
}, 100);
setIntervalId(id);
};
const handleLap = () => {
const [firstLap, ...other] = laps;
setLaps([0, firstLap + now - start, ...other]);
setStart(new Date().getTime());
setNow(new Date().getTime());
};
const handleReset = () => {
setLaps([]);
setStart(0);
setNow(0);
};
解説
必要なstateは
- now: 今の時刻
- state: タイマーを開始した時刻
- laps: ラップを格納する配列
- intervalId: タイマーのId
handleStart関数内のsetIntervalでタイマーを開始し, 返り値のidをセットしてラップを0にします.
handleStop関数内のclearIntervalでタイマーを停止し, ラップは firstLap + now - start にします.
firstLapはラップの最初の値, now - start が経過時間です.
firstLapはラップの最初の値, now - start が経過時間です.
handleResume関数は 停止 -> 再開 の時の関数です.
handleRap関数はラップ時の関数で, タイマーは動かしたまま, lapに記録します.
handleResetで全てをリセットします.
最後にuseEffectのcleanup関数でタイマーをクリアーします.
表示部分
const Timer = ({ interval, style }: any) => {
const pad = (n: number) => n < 10 ? "0" + n : n;
const duration = moment.duration(interval);
const centimes = Math.floor(duration.milliseconds() / 10);
return (
<View style={styles.timerContainer}>
{duration.minutes() < 0
? (
<React.Fragment>
<Text style={style}>00</Text>
<Text style={style}>00</Text>
<Text style={style}>00</Text>
</React.Fragment>
)
: (
<React.Fragment>
<Text style={style}>{pad(duration.minutes())}</Text>
<Text style={style}>{pad(duration.seconds())}</Text>
<Text style={style}>{pad(centimes)}</Text>
</React.Fragment>
)}
</View>
);
};
return (
<React.Fragment>
<Timer
interval={laps.reduce((prev, curr) => prev + curr, 0) + now - start}
style={styles.timer}
/>
{laps.length === 0 && (
<TouchableOpacity onPress={handleStart}>
<Text>START</Text>
</TouchableOpacity>
)}
{start > 0 && (
<React.Fragment>
<TouchableOpacity onPress={handleStop}>
<Text>STOP</Text>
</TouchableOpacity>
<TouchableOpacity onPress={handleLap}>
<Text>LAP</Text>
</TouchableOpacity>
</React.Fragment>
)}
{laps.length > 0 && start === 0 && (
<React.Fragment>
<TouchableOpacity onPress={handleReset}>
<Text>RESET</Text>
</TouchableOpacity>
<TouchableOpacity onPress={handleResume}>
<Text>RESUME</Text>
</TouchableOpacity>
</React.Fragment>
)}
{laps.map((lap, i) => <Text key={i}>{lap}</Text>)}
</React.Fragment>
);
解説
合計値は
あとは大体いい感じにです..
laps.reduce((prev, curr) => prev + curr, 0) + now - start
で求められます.あとは大体いい感じにです..
Thanks you for reading.