1

I have a a div with a sun and moon. Currently there is an animation that changes color of the background and animates the sun and moon. How can I make this animation sync to realtime so that the animation reflects the time of the day and the position of the sun and moon.

@keyframes sunrise {
    from {
        transform: rotate(-45deg);
    }

    to {
        transform: rotate(315deg);
    }
}

@keyframes moonrise {
    from {
        transform: rotate(0deg);
    }

    to {
        transform: rotate(180deg);
    }
}

@keyframes dawn {
    0% {
        opacity: 0;
    }
    10% {
        opacity: 1;
    }
    60% {
        opacity: 0;
    }
}

@keyframes noon {
    0% {
        opacity: 0;
    }
    50% {
        opacity: 1;
    }
    75% {
        opacity: 0;
    }
}

@keyframes dusk {
    0% {
        opacity: 0;
    }
    50% {
        opacity: 0;
    }
    70% {
        opacity: 1;
    }
    90% {
        opacity: 0;
    }
}

@keyframes midnight {
    0% {
        opacity: 1;
    }
    25% {
        opacity: 0;
    }
    50% {
        opacity: 0;
    }
    80% {
        opacity: 1;
    }
}

body {
    --animation-speed: 4s;
    background-color: rgb(37, 29, 24);
}

.sky {
    width: 100vw;
    height: 100vh;

    top: 0;
    left: 0;
    max-height: 600px;
    overflow: hidden;
}

.sky__phase {
    position: absolute;
    top: 0;
    left: 0;
    height: 100%;
    width: 100%;
    transition: opacity 0.2s;
}

.sky__dawn {
    background: linear-gradient(
        0deg,
        rgba(254, 215, 102, 1) 0%,
        rgba(205, 237, 246, 1) 100%
    );
    animation: linear dawn infinite var(--animation-speed);
}

.sky__noon {
    background: linear-gradient(
        0deg,
        rgba(205, 237, 246, 1) 0%,
        rgba(36, 123, 160, 1) 100%
    );
    animation: linear noon infinite var(--animation-speed);
}

.sky__dusk {
    background: linear-gradient(
        0deg,
        rgba(255, 32, 110, 1) 0%,
        rgba(10, 0, 94, 1) 100%
    );
    animation: linear dusk infinite var(--animation-speed);
}

.sky__midnight {
    background: linear-gradient(
        0deg,
        rgba(2, 0, 20, 1) 0%,
        rgba(10, 0, 94, 1) 100%
    );
    animation: linear midnight infinite var(--animation-speed);
}

.orbit {
    position: relative;
    width: 500px;
    height: 500px;
    margin: 200px auto;
    transform: rotate(-45deg);
    animation: linear sunrise infinite var(--animation-speed);
}

@media (min-width: 768px) {
    .sky {
        max-height: 600px;
    }
    .orbit {
        width: 100px;
        height: 700px;
        margin: 150px auto;
    }
}

@media screen and (min-width: 1080px) and (max-width: 1920px) {
    .sky {
        max-height: 1920px;
    }
    .orbit {
        width: 600px;
        height: 1100px;
        margin: 1000px auto;
    }
}


.sun {
    position: absolute;
    top: -40px;
    left: -40px;
    width: 80px;
    height: 80px;
    background-color: rgb(254, 215, 102);
    border-radius: 50%;
    box-shadow: 0 0 14px 14px rgba(254, 215, 102, 0.2);
}

.moon {
    position: absolute;
    bottom: -40px;
    right: -40px;
    width: 80px;
    height: 80px;
    border-radius: 50%;
    background-color: #fff;
    box-shadow: 0 0 7px 7px rgba(255, 255, 255, 0.2);
}
<div class="sky">
    <div class="sky__phase sky__dawn"></div>
    <div class="sky__phase sky__noon"></div>
    <div class="sky__phase sky__dusk"></div>
    <div class="sky__phase sky__midnight"></div>
    <div class="orbit">
        <div class="sun"></div>
        <div class="moon"></div>
    </div>
</div>

Added a css animation to animate gradient and revolve the sun. The animation time is 4 seconds at the moment.

ruleboy21
  • 5,510
  • 4
  • 17
  • 34
mindprojx
  • 11
  • 2
  • where are you getting the information on sunrise/sundown from? or are you just going for "based on local time, sunrise is at 8am and sundown is at 8pm"? – Plagiatus Feb 28 '23 at 09:42
  • Maybe this can help https://stackoverflow.com/questions/29513628/use-javascript-in-order-to-set-the-current-percentage-of-a-css-animation – Алексей Мартинкевич Feb 28 '23 at 09:43
  • Why not use JS to get current hour or time slot and set animation based on that ? – medelito Feb 28 '23 at 09:49
  • 'and the position of the sun and the moon' - do you have a source for finding these out - and how are you getting the lat and lng of the current user? Please show us the JS you have so far. – A Haworth Feb 28 '23 at 09:57

1 Answers1

0

Assuming you're not going for a "realistic" approach that includes the geographical position of the user and just want to have it sync to their clock, I'd recommend doing something like this:

First, set the animation time to 24 hours:

--animation-speed: 86400s;

Then, use js to get the users current time inside the day and set the animation-delay accordingly.
You're already using css variables, so I recommend you keep doing that and set it once in the root element.

let date = new Date();
let hours = date.getHours();
let minutes = date.getMinutes();
// the animation starts at sunup, so when do you want this to occur?
// I set it to 6am, full hour.
let offset = 6;

let delay = -(((hours - offset) * 60) + minutes ) * 60;
document.body.style.setProperty("--animation-delay", delay + "s");
/* changes:
--animation-speed set to 24 hours

--animation-delay variable in body
use of said variable in all animations */

@keyframes sunrise {
    from {
        transform: rotate(-45deg);
    }

    to {
        transform: rotate(315deg);
    }
}

@keyframes moonrise {
    from {
        transform: rotate(0deg);
    }

    to {
        transform: rotate(180deg);
    }
}

@keyframes dawn {
    0% {
        opacity: 0;
    }
    10% {
        opacity: 1;
    }
    60% {
        opacity: 0;
    }
}

@keyframes noon {
    0% {
        opacity: 0;
    }
    50% {
        opacity: 1;
    }
    75% {
        opacity: 0;
    }
}

@keyframes dusk {
    0% {
        opacity: 0;
    }
    50% {
        opacity: 0;
    }
    70% {
        opacity: 1;
    }
    90% {
        opacity: 0;
    }
}

@keyframes midnight {
    0% {
        opacity: 1;
    }
    25% {
        opacity: 0;
    }
    50% {
        opacity: 0;
    }
    80% {
        opacity: 1;
    }
}

body {
    --animation-speed: 86400s;
    --animation-delay: 0s;
    background-color: rgb(37, 29, 24);
}

.sky {
    width: 100vw;
    height: 100vh;

    top: 0;
    left: 0;
    max-height: 600px;
    overflow: hidden;
}

.sky__phase {
    position: absolute;
    top: 0;
    left: 0;
    height: 100%;
    width: 100%;
    transition: opacity 0.2s;
}

.sky__dawn {
    background: linear-gradient(
        0deg,
        rgba(254, 215, 102, 1) 0%,
        rgba(205, 237, 246, 1) 100%
    );
    animation: linear dawn infinite var(--animation-speed);
    animation-delay: var(--animation-delay);
}

.sky__noon {
    background: linear-gradient(
        0deg,
        rgba(205, 237, 246, 1) 0%,
        rgba(36, 123, 160, 1) 100%
    );
    animation: linear noon infinite var(--animation-speed);
    animation-delay: var(--animation-delay);
}

.sky__dusk {
    background: linear-gradient(
        0deg,
        rgba(255, 32, 110, 1) 0%,
        rgba(10, 0, 94, 1) 100%
    );
    animation: linear dusk infinite var(--animation-speed);
    animation-delay: var(--animation-delay);
}

.sky__midnight {
    background: linear-gradient(
        0deg,
        rgba(2, 0, 20, 1) 0%,
        rgba(10, 0, 94, 1) 100%
    );
    animation: linear midnight infinite var(--animation-speed);
    animation-delay: var(--animation-delay);
}

.orbit {
    position: relative;
    width: 500px;
    height: 500px;
    margin: 200px auto;
    transform: rotate(-45deg);
    animation: linear sunrise infinite var(--animation-speed);
    animation-delay: var(--animation-delay);
}

@media (min-width: 768px) {
    .sky {
        max-height: 600px;
    }
    .orbit {
        width: 100px;
        height: 700px;
        margin: 150px auto;
    }
}

@media screen and (min-width: 1080px) and (max-width: 1920px) {
    .sky {
        max-height: 1920px;
    }
    .orbit {
        width: 600px;
        height: 1100px;
        margin: 1000px auto;
    }
}


.sun {
    position: absolute;
    top: -40px;
    left: -40px;
    width: 80px;
    height: 80px;
    background-color: rgb(254, 215, 102);
    border-radius: 50%;
    box-shadow: 0 0 14px 14px rgba(254, 215, 102, 0.2);
}

.moon {
    position: absolute;
    bottom: -40px;
    right: -40px;
    width: 80px;
    height: 80px;
    border-radius: 50%;
    background-color: #fff;
    box-shadow: 0 0 7px 7px rgba(255, 255, 255, 0.2);
}
<!-- No changes -->
<div class="sky">
    <div class="sky__phase sky__dawn"></div>
    <div class="sky__phase sky__noon"></div>
    <div class="sky__phase sky__dusk"></div>
    <div class="sky__phase sky__midnight"></div>
    <div class="orbit">
        <div class="sun"></div>
        <div class="moon"></div>
    </div>
</div>
Plagiatus
  • 360
  • 2
  • 12