suchen

Heim  >  Fragen und Antworten  >  Hauptteil

Wie lässt sich der Sekundenzeiger einer Uhr nur vorwärts bewegen?

Ich habe mit React eine analoge Uhr gebaut, aber ich habe ein Problem mit dem Sekundenzeiger. Der Sekundenzeiger beginnt im Uhrzeigersinn, aber sobald er die 59-Sekunden-Marke erreicht, bewegt er sich gegen den Uhrzeigersinn, bis er die 1-Sekunden-Marke erreicht. Danach bewegt es sich wieder im Uhrzeigersinn. Wie kann man es kontinuierlich im Uhrzeigersinn bewegen?

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;

Ich bin mir nicht sicher, ob das CSS hilft, aber hier ist es.

.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粉952365143434 Tage vor586

Antworte allen(1)Ich werde antworten

  • P粉221046425

    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;
    

    我删除了一些不必要的逻辑,我将解释我添加的一些内容

    • 关键帧对于实现此目标至关重要,因为它将定义动画如何旋转(从初始旋转到初始旋转 + 360),并且还可以与动画属性一起使用,这对 ClockStick 很有帮助
    • ClockStick 是一个样式组件,它将接收初始度数以及动画完成一个循环所需的秒数
    • 我仅声明了一种状态,其初始度数与用户运行应用程序的特定时间相对应
    • 然后,我传递每根棒 (ClockStick) 完成循环所需的秒数(216000 => 表示小时,3600 => 表示分钟,60 => 表示秒)

    这是结果

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

    与答案相关的一些链接

    Antwort
    0
  • StornierenAntwort