Maison > Questions et réponses > le corps du texte
J'ai construit une horloge analogique en utilisant React mais j'ai un problème avec la trotteuse. La trotteuse démarre dans le sens des aiguilles d’une montre, mais une fois qu’elle atteint la marque des 59 secondes, elle se déplace dans le sens inverse des aiguilles d’une montre jusqu’à atteindre la marque des 1 secondes. Après cela, il se déplace à nouveau dans le sens des aiguilles d'une montre. Comment le faire bouger continuellement dans le sens des aiguilles d'une montre ?
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;
Je ne sais pas si le CSS aide, mais le voici.
.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
Lorsque vous essayez d'injecter du js en CSS pour atteindre votre objectif, je vous recommande d'utiliser des composants stylisés pour obtenir certains avantages, de passer au niveau supérieur et d'utiliser des variables js en CSS
La principale limitation du code est que vous ne pouvez pas spécifier que l'animation continuera indéfiniment, afin qu'elle redémarre lorsque 360 degrés sont atteints
Cela peut être réalisé grâce à des images clés et des animations CSS, mais sans utiliser de composants stylisés, il est difficile de transmettre certains paramètres nécessaires aux images clés et aux animations, tels que les degrés initiaux et les secondes pour terminer la boucle
C'est plus ou moins comment styliser les composants
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;
J'ai supprimé certaines logiques inutiles et j'expliquerai certaines des choses que j'ai ajoutées
Voici le résultat
https://codesandbox.io/s/dawn-rgb-qn58t6
Quelques liens liés aux réponses