Tide Clock: Tidal Tracker

This script creates a digital replication of a mechanical tide clock by tracking the M2 lunar tidal constituent, which dictates that a full cycle from high tide to high tide takes exactly 44,714 seconds. It uses a mathematical modulo operation to calculate where the current moment falls within that continuous cycle, relative to a fixed baseline date in the past. Once it pinpoints that position, it translates the elapsed time into a 360-degree rotation for the CSS hand and updates the text to display whether the water is high, falling, low, or rising. 

To keep the clock perfectly calibrated for your local port, you must periodically adjust the syncHighTide variable to account for natural atmospheric and tidal drift. You do this by finding a verified high tide from the UK Hydrographic Office and updating the timestamp within the new Date('YYYY-MM-DDTHH:MM:SSZ') string, ensuring you maintain the UTC format so daylight saving hours do not skew the maths.

The refresh frequency of the visual display is governed by the setInterval function at the bottom, which you can naturally adjust to whatever timing interval you prefer for the widget.
High
Falling
Low
Rising

Whitehaven Tides

Calculating status...

Tide Clock v1.0
<style>
    .whitehaven-tide-container {
        display: flex;
        flex-direction: column;
        align-items: center;
        font-family: Arial, sans-serif;
        margin: 10px 0;
        width: 100%;
    }
    
    .wt-tide-clock {
        width: 100%;
        max-width: 250px;
        aspect-ratio: 1 / 1;
        border-radius: 50%;
        background: #ffffff;
        border: 10px solid #1a365d;
        position: relative;
        box-shadow: 0 4px 10px rgba(0,0,0,0.1);
        box-sizing: border-box;
    }
    
    .wt-center-dot {
        width: 14px;
        height: 14px;
        background: #1a365d;
        border-radius: 50%;
        position: absolute;
        top: 50%;
        left: 50%;
        transform: translate(-50%, -50%);
        z-index: 10;
    }
    
    .wt-label {
        position: absolute;
        font-weight: bold;
        color: #1a365d;
        text-transform: uppercase;
        font-size: 11px;
        letter-spacing: 0.5px;
    }
    
    .wt-high-tide { top: 12px; left: 50%; transform: translateX(-50%); }
    .wt-low-tide { bottom: 12px; left: 50%; transform: translateX(-50%); }
    .wt-ebb { top: 50%; right: 12px; transform: translateY(-50%); }
    .wt-flood { top: 50%; left: 12px; transform: translateY(-50%); }
    
    .wt-hand {
        width: 4px;
        height: 45%;
        background: #e53e3e;
        position: absolute;
        bottom: 50%;
        left: 50%;
        transform-origin: bottom center;
        transform: translateX(-50%) rotate(0deg);
        border-radius: 2px;
        transition: transform 1s linear;
        z-index: 5;
    }
    
    .wt-info {
        text-align: center;
        margin-top: 15px;
        color: #2d3748;
    }
    
    .wt-info h3 {
        margin: 0 0 5px 0;
        color: #1a365d;
        font-size: 16px;
    }
    
    .wt-info p {
        margin: 0;
        font-size: 14px;
        font-weight: bold;
    }
</style>

<div class="whitehaven-tide-container">
    <div class="wt-tide-clock">
        <div class="wt-label wt-high-tide">High</div>
        <div class="wt-label wt-ebb">Falling</div>
        <div class="wt-label wt-low-tide">Low</div>
        <div class="wt-label wt-flood">Rising</div>
        <div class="wt-hand" id="wt-tide-hand"></div>
        <div class="wt-center-dot"></div>
    </div>
    <div class="wt-info">
        <h3>Whitehaven Tides</h3>
        <p id="wt-status-text">Calculating status...</p>
    </div>
</div>

<script>
    (function() {
        const tideCycleSeconds = 44714;
        const syncHighTide = new Date('2026-06-18T00:14:00Z').getTime();

        function updateClock() {
            const now = new Date().getTime();
            const elapsedSeconds = Math.floor((now - syncHighTide) / 1000);
            
            let currentCyclePosition = elapsedSeconds % tideCycleSeconds;
            if (currentCyclePosition < 0) {
                currentCyclePosition += tideCycleSeconds; 
            }
            
            const degrees = (currentCyclePosition / tideCycleSeconds) * 360;
            
            const hand = document.getElementById('wt-tide-hand');
            if (hand) {
                hand.style.transform = `translateX(-50%) rotate(${degrees}deg)`;
            }
            
            let status = '';
            if (degrees > 345 || degrees <= 15) {
                status = 'High Tide';
            } else if (degrees > 15 && degrees <= 165) {
                status = 'Falling (Ebb)';
            } else if (degrees > 165 && degrees <= 195) {
                status = 'Low Tide';
            } else {
                status = 'Rising (Flood)';
            }
            
            const statusText = document.getElementById('wt-status-text');
            if (statusText) {
                statusText.innerText = status;
            }
        }

        updateClock();
        setInterval(updateClock, 1000);
    })();
</script>

Post a Comment

0 Comments

Notice:
Comments are moderated and may not appear immediately. Please keep your comments respectful, and relevant to the post. Spam will not be tolerated. My site. My rules.

Post a Comment (0)