我使用 React 建立了一個類比時鐘,但秒針有問題。 秒針以順時針方向開始,但一旦到達 59 秒標記,它就會逆時針移動,直到到達 1 秒標記。之後它又順時針移動。如何讓它連續順時針移動?
import React, { useEffect, useState } from 'react'; import './AnalogClock.css'; const AnalogClock = () => { const [time, setTime] = useState(new Date()); useEffect(() => { const interval = setInterval(() => { const newTime = new Date(); setTime(newTime); }, 1000); return () => { clearInterval(interval); }; }, []); const getRotation = (unit, max) => { const value = time[`get${unit}`](); let rotation = (value * 360) / max; if (unit === 'Seconds') { const seconds = value + time.getMilliseconds() / 1000; rotation = (seconds * 6) % 360; if (rotation < 0) { rotation += 360; } } return { transform: `translate(-50%, -100%) rotate(${rotation}deg)`, }; }; const renderNumbers = () => { const numbers = []; for (let i = 1; i <= 12; i++) { const angle = (i * 30) * (Math.PI / 180); const numberStyle = { left: `calc(50% + ${Math.sin(angle) * 140}px)`, top: `calc(50% - ${Math.cos(angle) * 140}px)`, }; numbers.push( <div key={i} className="number" style={numberStyle}> {i} </div> ); } return numbers; }; return ( <div className="clock"> {renderNumbers()} <div className="hour-hand" style={getRotation('Hours', 12)}></div> <div className="minute-hand" style={getRotation('Minutes', 60)}></div> <div className="second-hand" style={ time.getSeconds() === 59 ? { ...getRotation('Seconds', 60), transition: 'none' } : getRotation('Seconds', 60) } ></div> <div className="center-circle"></div> </div> ); }; export default AnalogClock;
不確定 css 是否有幫助,但它就在這裡。
.clock { position: relative; width: 300px; height: 300px; border-radius: 50%; background-color: #e0e0e0; box-shadow: 20px 20px 40px rgba(0, 0, 0, 0.2), -20px -20px 40px rgba(255, 255, 255, 0.7); padding: 20px; } .hour-hand, .minute-hand, .second-hand { position: absolute; background-color: #333; transform-origin: bottom center; transition: transform 0.5s ease-in-out; box-shadow: 4px 4px 8px rgba(0, 0, 0, 0.2), -4px -4px 8px rgba(255, 255, 255, 0.7); } .hour-hand { width: 8px; height: 90px; top: 50%; left: 50%; transform: translate(-50%, -100%) translateX(-1px); border-radius: 8px 8px 0 0; } .minute-hand { width: 6px; height: 120px; top: 50%; left: 50%; transform: translate(-50%, -100%) translateX(-1px); border-radius: 6px 6px 0 0; } .second-hand { width: 4px; height: 130px; top: 50%; left: 50%; transform: translate(-50%, -100%) translateX(-1px); border-radius: 4px 4px 0 0; background-color: #ff0000; } .center-circle { position: absolute; top: 50%; left: 50%; width: 16px; height: 16px; background-color: #333; border-radius: 50%; transform: translate(-50%, -50%); box-shadow: 2px 2px 4px rgba(0, 0, 0, 0.2), -2px -2px 4px rgba(255, 255, 255, 0.7); } .number { position: absolute; font-size: 29px; font-weight: bold; color: #333; transform: translate(-50%, -50%); }
P粉2210464252023-09-07 13:12:52
當你嘗試在 css 中註入 js 來實現你的目標時,我建議你使用樣式化元件來獲得一些好處,將其提升到一個新的水平,並在 css 中使用 js 變數
程式碼的主要限制是您無法指定動畫將永遠繼續,以便在達到 360 度時重新啟動動畫
這可以透過 css 關鍵影格和動畫來實現,但如果不使用樣式化元件,則很難將一些必要的參數傳遞給關鍵影格和動畫,例如初始度數和完成迴圈的秒數
這或多或少是樣式化元件的方法
import React, { useEffect, useState } from 'react'; import styled, { keyframes } from 'styled-components'; import './styles.css'; const rotate = (degree) => keyframes` from { transform: translate(-50%, -100%) rotate(${degree}deg); } to { transform: translate(-50%, -100%) rotate(${degree+360}deg); } ` const ClockStick = styled.div` animation: ${(props) => rotate(props.degree)} ${(props) => props.seconds}s linear; ` const App = () => { const [degrees, setDegrees] = useState({}); useEffect(() => { setDegrees({ hour: getRotation('Hours', 12), minute: getRotation('Minutes', 60), second: getRotation('Seconds', 60) }) }, []); const getRotation = (unit, max) => { const time = new Date(); const value = time[`get${unit}`](); const rotation = (value * 360) / max; return rotation; }; const renderNumbers = () => { const numbers = []; for (let i = 1; i <= 12; i++) { const angle = (i * 30) * (Math.PI / 180); const numberStyle = { left: `calc(50% + ${Math.sin(angle) * 140}px)`, top: `calc(50% - ${Math.cos(angle) * 140}px)`, }; numbers.push( <div key={i} className="number" style={numberStyle}> {i} </div> ); } return numbers; }; return ( <div className="clock"> {renderNumbers()} <ClockStick className="hour-hand" seconds={216000} degree={degrees.hour}></ClockStick> <ClockStick className="minute-hand" seconds={3600} degree={degrees.minute}></ClockStick> <ClockStick className="second-hand" seconds={60} degree={degrees.second} ></ClockStick> <div className="center-circle"></div> </div> ); }; export default App;
我刪除了一些不必要的邏輯,我將解釋我添加的一些內容
這是結果
https://codesandbox.io/s/dawn-rgb-qn58t6
與答案相關的一些連結