recherche

Maison  >  Questions et réponses  >  le corps du texte

Comment faire avancer la trotteuse d'une horloge uniquement ?

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粉952365143P粉952365143448 Il y a quelques jours608

répondre à tous(1)je répondrai

  • P粉221046425

    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

    • Les images clés sont cruciales pour atteindre cet objectif car elles définiront la manière dont l'animation tourne (de la rotation initiale à la rotation initiale + 360) et peuvent également être utilisées avec les propriétés d'animation, ce qui peut être utile avec ClockStick
    • ClockStick est un composant de style qui recevra le degré initial et le nombre de secondes nécessaires à l'animation pour boucler une boucle
    • J'ai uniquement déclaré un état dont le degré initial correspond à un moment précis où l'utilisateur exécute l'application
    • Ensuite je passe le nombre de secondes qu'il faut à chaque stick (ClockStick) pour boucler la boucle (216000 => pour les heures, 3600 => pour les minutes, 60 => pour les secondes)

    Voici le résultat

    https://codesandbox.io/s/dawn-rgb-qn58t6

    Quelques liens liés aux réponses

    répondre
    0
  • Annulerrépondre