为翻页和滚动时钟独立添加12/24小时制切换
- FlipClock组件独立实现12/24H切换功能 - RollClock组件独立实现12/24H切换功能 - 分别使用独立的CSS样式(flip-format-toggle/roll-format-toggle) - 各组件状态独立,互不干扰 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
0f0809b1c0
commit
d2a9a94d3b
26
src/App.css
26
src/App.css
@ -57,7 +57,7 @@
|
||||
}
|
||||
|
||||
.digital-clock-period {
|
||||
font-family: system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;
|
||||
font-family: Arial, sans-serif;
|
||||
font-weight: 600;
|
||||
color: #fff;
|
||||
text-shadow: 0 0 10px rgba(255, 255, 255, 0.5);
|
||||
@ -81,24 +81,6 @@
|
||||
background-color: rgba(255, 255, 255, 0.15);
|
||||
}
|
||||
|
||||
.format-toggle {
|
||||
padding: 6px 12px;
|
||||
font-size: 12px;
|
||||
font-weight: 500;
|
||||
color: #888;
|
||||
background-color: rgba(255, 255, 255, 0.05);
|
||||
border: none;
|
||||
border-radius: 6px;
|
||||
cursor: pointer;
|
||||
transition: all 0.2s ease;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.format-toggle:hover {
|
||||
color: #fff;
|
||||
background-color: rgba(255, 255, 255, 0.15);
|
||||
}
|
||||
|
||||
.clock-container {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
@ -109,12 +91,6 @@
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.digital-clock-wrapper {
|
||||
position: relative;
|
||||
display: inline-flex;
|
||||
align-items: flex-start;
|
||||
}
|
||||
|
||||
.digital-clock {
|
||||
font-family: 'DSEG7', monospace;
|
||||
font-weight: bold;
|
||||
|
||||
@ -6,7 +6,6 @@ import './App.css'
|
||||
type ClockStyle = 'digital' | 'flip' | 'roll'
|
||||
|
||||
function DigitalClock({ time, size, period, is24Hour, onToggleFormat }: { time: string; size: number; period?: string; is24Hour: boolean; onToggleFormat: () => void }) {
|
||||
// Match visual height with flip/roll clocks
|
||||
const fontSize = Math.floor(size * 0.95)
|
||||
const periodSize = Math.floor(size * 0.25)
|
||||
|
||||
|
||||
@ -1,3 +1,44 @@
|
||||
.flip-clock-outer {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
gap: 0;
|
||||
}
|
||||
|
||||
.flip-clock-side-panel {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-end;
|
||||
justify-content: center;
|
||||
gap: 4px;
|
||||
margin-right: 4px;
|
||||
}
|
||||
|
||||
.flip-clock-period {
|
||||
font-family: Arial, sans-serif;
|
||||
font-weight: 600;
|
||||
color: #fff;
|
||||
text-shadow: 0 0 10px rgba(255, 255, 255, 0.5);
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.flip-format-toggle {
|
||||
padding: 4px 8px;
|
||||
font-size: 12px;
|
||||
font-weight: 500;
|
||||
color: #888;
|
||||
background-color: rgba(255, 255, 255, 0.05);
|
||||
border: none;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
transition: all 0.2s ease;
|
||||
}
|
||||
|
||||
.flip-format-toggle:hover {
|
||||
color: #fff;
|
||||
background-color: rgba(255, 255, 255, 0.15);
|
||||
}
|
||||
|
||||
.flip-clock-container {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
import { useState } from 'react';
|
||||
import { FlipDigit } from './FlipDigit';
|
||||
import './FlipClock.css';
|
||||
|
||||
@ -7,46 +8,77 @@ interface FlipClockProps {
|
||||
}
|
||||
|
||||
export function FlipClock({ time, size }: FlipClockProps) {
|
||||
const [hours, minutes, seconds] = time.split(':');
|
||||
const [is24Hour, setIs24Hour] = useState(true);
|
||||
|
||||
// Parse time and convert if needed
|
||||
const [hoursStr, minutes, seconds] = time.split(':');
|
||||
let hours = parseInt(hoursStr, 10);
|
||||
let period: string | undefined;
|
||||
|
||||
if (!is24Hour) {
|
||||
period = hours >= 12 ? 'PM' : 'AM';
|
||||
hours = hours % 12 || 12;
|
||||
}
|
||||
|
||||
const displayHours = String(hours).padStart(2, '0');
|
||||
const periodSize = size * 0.25;
|
||||
|
||||
return (
|
||||
<div className="flip-clock-container">
|
||||
{/* Hours */}
|
||||
<div className="flip-clock-digit-group">
|
||||
<FlipDigit value={parseInt(hours[0], 10)} size={size} />
|
||||
<FlipDigit value={parseInt(hours[1], 10)} size={size} />
|
||||
<div className="flip-clock-outer">
|
||||
<div className="flip-clock-side-panel">
|
||||
{!is24Hour && period && (
|
||||
<span
|
||||
className="flip-clock-period"
|
||||
style={{ fontSize: `${periodSize}px` }}
|
||||
>
|
||||
{period}
|
||||
</span>
|
||||
)}
|
||||
<button
|
||||
className="flip-format-toggle"
|
||||
onClick={() => setIs24Hour(!is24Hour)}
|
||||
>
|
||||
{is24Hour ? '24H' : '12H'}
|
||||
</button>
|
||||
</div>
|
||||
<div className="flip-clock-container">
|
||||
{/* Hours */}
|
||||
<div className="flip-clock-digit-group">
|
||||
<FlipDigit value={parseInt(displayHours[0], 10)} size={size} />
|
||||
<FlipDigit value={parseInt(displayHours[1], 10)} size={size} />
|
||||
</div>
|
||||
|
||||
<span
|
||||
className="flip-clock-separator"
|
||||
style={{
|
||||
fontSize: `${size * 0.5}px`,
|
||||
marginTop: `${-size * 0.08}px`
|
||||
}}
|
||||
>
|
||||
:
|
||||
</span>
|
||||
<span
|
||||
className="flip-clock-separator"
|
||||
style={{
|
||||
fontSize: `${size * 0.5}px`,
|
||||
marginTop: `${-size * 0.08}px`
|
||||
}}
|
||||
>
|
||||
:
|
||||
</span>
|
||||
|
||||
{/* Minutes */}
|
||||
<div className="flip-clock-digit-group">
|
||||
<FlipDigit value={parseInt(minutes[0], 10)} size={size} />
|
||||
<FlipDigit value={parseInt(minutes[1], 10)} size={size} />
|
||||
</div>
|
||||
{/* Minutes */}
|
||||
<div className="flip-clock-digit-group">
|
||||
<FlipDigit value={parseInt(minutes[0], 10)} size={size} />
|
||||
<FlipDigit value={parseInt(minutes[1], 10)} size={size} />
|
||||
</div>
|
||||
|
||||
<span
|
||||
className="flip-clock-separator"
|
||||
style={{
|
||||
fontSize: `${size * 0.5}px`,
|
||||
marginTop: `${-size * 0.08}px`
|
||||
}}
|
||||
>
|
||||
:
|
||||
</span>
|
||||
<span
|
||||
className="flip-clock-separator"
|
||||
style={{
|
||||
fontSize: `${size * 0.5}px`,
|
||||
marginTop: `${-size * 0.08}px`
|
||||
}}
|
||||
>
|
||||
:
|
||||
</span>
|
||||
|
||||
{/* Seconds */}
|
||||
<div className="flip-clock-digit-group">
|
||||
<FlipDigit value={parseInt(seconds[0], 10)} size={size} />
|
||||
<FlipDigit value={parseInt(seconds[1], 10)} size={size} />
|
||||
{/* Seconds */}
|
||||
<div className="flip-clock-digit-group">
|
||||
<FlipDigit value={parseInt(seconds[0], 10)} size={size} />
|
||||
<FlipDigit value={parseInt(seconds[1], 10)} size={size} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
@ -1,3 +1,44 @@
|
||||
.roll-clock-outer {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
gap: 0;
|
||||
}
|
||||
|
||||
.roll-clock-side-panel {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-end;
|
||||
justify-content: center;
|
||||
gap: 4px;
|
||||
margin-right: 4px;
|
||||
}
|
||||
|
||||
.roll-clock-period {
|
||||
font-family: Arial, sans-serif;
|
||||
font-weight: 600;
|
||||
color: #fff;
|
||||
text-shadow: 0 0 10px rgba(255, 255, 255, 0.5);
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.roll-format-toggle {
|
||||
padding: 4px 8px;
|
||||
font-size: 12px;
|
||||
font-weight: 500;
|
||||
color: #888;
|
||||
background-color: rgba(255, 255, 255, 0.05);
|
||||
border: none;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
transition: all 0.2s ease;
|
||||
}
|
||||
|
||||
.roll-format-toggle:hover {
|
||||
color: #fff;
|
||||
background-color: rgba(255, 255, 255, 0.15);
|
||||
}
|
||||
|
||||
.roll-clock-wrapper {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
|
||||
@ -10,9 +10,21 @@ interface RollClockProps {
|
||||
export function RollClock({ time, size }: RollClockProps) {
|
||||
// Roll direction: 'down' = roll down, 'up' = roll up
|
||||
const [direction, setDirection] = useState<'down' | 'up'>('down');
|
||||
const [is24Hour, setIs24Hour] = useState(true);
|
||||
|
||||
const [hours, minutes, seconds] = time.split(':');
|
||||
// Parse time and convert if needed
|
||||
const [hoursStr, minutes, seconds] = time.split(':');
|
||||
let hours = parseInt(hoursStr, 10);
|
||||
let period: string | undefined;
|
||||
|
||||
if (!is24Hour) {
|
||||
period = hours >= 12 ? 'PM' : 'AM';
|
||||
hours = hours % 12 || 12;
|
||||
}
|
||||
|
||||
const displayHours = String(hours).padStart(2, '0');
|
||||
const buttonSize = size * 0.25;
|
||||
const periodSize = size * 0.25;
|
||||
|
||||
// Toggle direction
|
||||
const toggleDirection = () => {
|
||||
@ -20,65 +32,83 @@ export function RollClock({ time, size }: RollClockProps) {
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="roll-clock-wrapper">
|
||||
<div className="roll-clock-container">
|
||||
{/* Hours */}
|
||||
<div className="roll-clock-digit-group">
|
||||
<RollDigit value={parseInt(hours[0], 10)} size={size} direction={direction} />
|
||||
<RollDigit value={parseInt(hours[1], 10)} size={size} direction={direction} />
|
||||
</div>
|
||||
|
||||
<span
|
||||
className="roll-clock-separator"
|
||||
style={{
|
||||
fontSize: `${size * 0.5}px`,
|
||||
marginTop: `${-size * 0.08}px`
|
||||
}}
|
||||
<div className="roll-clock-outer">
|
||||
<div className="roll-clock-side-panel">
|
||||
{!is24Hour && period && (
|
||||
<span
|
||||
className="roll-clock-period"
|
||||
style={{ fontSize: `${periodSize}px` }}
|
||||
>
|
||||
{period}
|
||||
</span>
|
||||
)}
|
||||
<button
|
||||
className="roll-format-toggle"
|
||||
onClick={() => setIs24Hour(!is24Hour)}
|
||||
>
|
||||
:
|
||||
</span>
|
||||
|
||||
{/* Minutes */}
|
||||
<div className="roll-clock-digit-group">
|
||||
<RollDigit value={parseInt(minutes[0], 10)} size={size} direction={direction} />
|
||||
<RollDigit value={parseInt(minutes[1], 10)} size={size} direction={direction} />
|
||||
</div>
|
||||
|
||||
<span
|
||||
className="roll-clock-separator"
|
||||
style={{
|
||||
fontSize: `${size * 0.5}px`,
|
||||
marginTop: `${-size * 0.08}px`
|
||||
}}
|
||||
>
|
||||
:
|
||||
</span>
|
||||
|
||||
{/* Seconds */}
|
||||
<div className="roll-clock-digit-group">
|
||||
<RollDigit value={parseInt(seconds[0], 10)} size={size} direction={direction} />
|
||||
<RollDigit value={parseInt(seconds[1], 10)} size={size} direction={direction} />
|
||||
</div>
|
||||
{is24Hour ? '24H' : '12H'}
|
||||
</button>
|
||||
</div>
|
||||
<div className="roll-clock-wrapper">
|
||||
<div className="roll-clock-container">
|
||||
{/* Hours */}
|
||||
<div className="roll-clock-digit-group">
|
||||
<RollDigit value={parseInt(displayHours[0], 10)} size={size} direction={direction} />
|
||||
<RollDigit value={parseInt(displayHours[1], 10)} size={size} direction={direction} />
|
||||
</div>
|
||||
|
||||
{/* Direction toggle button */}
|
||||
<button
|
||||
className="roll-clock-button"
|
||||
style={{
|
||||
width: `${buttonSize}px`,
|
||||
height: `${buttonSize}px`,
|
||||
borderRadius: `${buttonSize / 2}px`,
|
||||
marginLeft: '8px',
|
||||
}}
|
||||
onClick={toggleDirection}
|
||||
>
|
||||
<span
|
||||
className="roll-clock-button-text"
|
||||
style={{ fontSize: `${buttonSize * 0.6}px` }}
|
||||
<span
|
||||
className="roll-clock-separator"
|
||||
style={{
|
||||
fontSize: `${size * 0.5}px`,
|
||||
marginTop: `${-size * 0.08}px`
|
||||
}}
|
||||
>
|
||||
:
|
||||
</span>
|
||||
|
||||
{/* Minutes */}
|
||||
<div className="roll-clock-digit-group">
|
||||
<RollDigit value={parseInt(minutes[0], 10)} size={size} direction={direction} />
|
||||
<RollDigit value={parseInt(minutes[1], 10)} size={size} direction={direction} />
|
||||
</div>
|
||||
|
||||
<span
|
||||
className="roll-clock-separator"
|
||||
style={{
|
||||
fontSize: `${size * 0.5}px`,
|
||||
marginTop: `${-size * 0.08}px`
|
||||
}}
|
||||
>
|
||||
:
|
||||
</span>
|
||||
|
||||
{/* Seconds */}
|
||||
<div className="roll-clock-digit-group">
|
||||
<RollDigit value={parseInt(seconds[0], 10)} size={size} direction={direction} />
|
||||
<RollDigit value={parseInt(seconds[1], 10)} size={size} direction={direction} />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Direction toggle button */}
|
||||
<button
|
||||
className="roll-clock-button"
|
||||
style={{
|
||||
width: `${buttonSize}px`,
|
||||
height: `${buttonSize}px`,
|
||||
borderRadius: `${buttonSize / 2}px`,
|
||||
marginLeft: '8px',
|
||||
}}
|
||||
onClick={toggleDirection}
|
||||
>
|
||||
{direction === 'down' ? '↓' : '↑'}
|
||||
</span>
|
||||
</button>
|
||||
<span
|
||||
className="roll-clock-button-text"
|
||||
style={{ fontSize: `${buttonSize * 0.6}px` }}
|
||||
>
|
||||
{direction === 'down' ? '↓' : '↑'}
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user