Artwork - Circular design disappears without warning

While working on a clock project purely for enjoyment, I noticed that the minute arc disappears from the canvas as soon as a new minute begins. Any idea why this is happening?

Check out the clock in action: https://jsfiddle.net/y0bson6f/

HTML

<canvas id="clock"></canvas>

CSS

body,
html {
    width: 100%;
    height: 100%;
    margin: 0px;
    font-family: Josefin Sans, Helvetica, sans-serif;
    background: #1A4978;
}

JS

    var canvas = document.getElementById('clock');
    var context = canvas.getContext('2d');

    function setDimensions() {
        context.canvas.width = window.innerWidth * 0.69;
        context.canvas.height = window.innerHeight;
    }

    setDimensions();

    var x = 0.5 * canvas.width;
    var y = canvas.height / 2;
    var radius = 0.25 * context.canvas.width;
    var startAngle = 0;
    var endAngle = 2 * Math.PI;
    var startAnimationMinuteDone = false;
    var firstTime = false;

    function updateMinute(start, end) {
        if (startAnimationMinuteDone == false && firstTime == false) {
            context.clearRect(0, 0, canvas.width, canvas.height);
        }

        setDimensions();
        context.beginPath();
        context.strokeStyle = "#FF7519";
        context.arc(x, y, radius, start, end);
        context.lineWidth = 20;
        context.stroke();
        context.closePath();
    }

    function updateSecond(start, end) {
        context.beginPath();
        context.strokeStyle = "#FFA319";
        radius = 0.25 * context.canvas.width + 20;
        context.arc(x, y, radius, start, end);
        context.stroke();
        context.closePath();
    }

    function minuteAntialias(start, end) {
        context.clearRect(0, 0, canvas.width, canvas.height);
        setDimensions();
        context.beginPath();
        context.strokeStyle = "#1A4978";
        context.arc(x, y, radius, start, end);
        context.lineWidth = 20;
        context.stroke();
        context.closePath();
    }

    function secondAntialias(start, end) {
        context.beginPath();
        context.strokeStyle = "#1A4978";
        radius = 0.25 * context.canvas.width + 40;
        context.arc(x, y, radius, start, end);
        context.stroke();
        context.closePath();
    }

    $(document).ready(function() {
        var time = 0;
        var count = 0;

        function clock() {
            var date = new Date();
            var year = date.getFullYear();
            var month = date.getMonth();
            var day = date.getDay();
            var hour = date.getHours();

            if (hour > 12) {
                hour -= 12;
            }

            var minute = date.getMinutes();
            var second = date.getSeconds();

            var newestMinuteStart = (time + 1.5) * Math.PI;
            var newestSecondStart = (time + 1.5) * Math.PI;

            var cachedTime;

            if (count <= minute / 30 && !startAnimationMinuteDone) {
                time += 0.01;
                updateMinute(1.5 * Math.PI, (time + 1.5) * Math.PI);
                count += 0.01;
                cachedTime = time;

            } else if (!startAnimationMinuteDone) {
                time = 0;
                count = 0;
                startAnimationMinuteDone = true;

            } else if (count <= second / 30 || second == 0 && startAnimationMinuteDone) {
                time += 0.01;
                updateSecond(1.5 * Math.PI, (time + 1.5) * Math.PI);
                secondAntialias(0, 2 * Math.PI); // Arc matching background colour gives the effect of greater sharpness
                count += 0.01;

                if (second == 0) {
                    context.clearRect(0, 0, canvas.width, canvas.height);
                    startAnimationMinuteDone = false;
                    firstTime = true;
                    time = 0;
                    count = 0;
                }

                console.log(second);
                console.log(startAnimationMinuteDone);
            }
        }

        setInterval(clock, 10);
    });

Answer №1

In this demonstration, I am showcasing the usage of different radii for both the minute and second arcs. By setting the interval to display the current time as 1 second instead of 10 milliseconds, which can be resource-intensive for the CPU. It is important to keep animations and time calculations separate:

var canvas = document.getElementById('canvas');
var context = canvas.getContext('2d');
var canvasWidth = canvas.width;
var canvasHeight = canvas.height;

// To ensure that the arc starts at an angle of 90 degrees, we need to rotate/translate the canvas
context.rotate(-degtorad(90));
context.translate(-canvasWidth, 0);

var centerX = canvasWidth * 0.5;
var centerY = canvasHeight * 0.5;

var minuteRadius = canvasWidth * 0.45;
var secondRadius = canvasWidth * 0.25;

function degtorad(degrees) { return degrees * (Math.PI / 180); }

function updateMinuteArc(startAngle, endAngle) {
    context.beginPath();
    context.strokeStyle = "#FFA319";
    context.arc(centerX, centerY, minuteRadius, startAngle, endAngle);
    context.stroke();
    context.closePath();
}

function updateSecondArc(startAngle, endAngle) {
    context.beginPath();
    context.strokeStyle = "#1A4978";
    context.arc(centerX, centerY, secondRadius, startAngle, endAngle);
    context.stroke();
    context.closePath();
}

setInterval(function() {

    var dateObj = new Date();
    var minutes = dateObj.getMinutes();
    var seconds = dateObj.getSeconds();

    var secDegrees = seconds * 6;
    var minDegrees = minutes * 6;

    console.log('secDegrees: ', secDegrees, seconds);
    console.log('minDegrees: ', minDegrees, minutes);

    context.clearRect(0, 0, canvasWidth, canvasHeight);

    updateMinuteArc(0, degtorad(minDegrees));
    updateSecondArc(0, degtorad(secDegrees));

}, 1000);

HTML:

<canvas id="canvas" width="300" height="300"></canvas>

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Mastering advanced authentication with Passport and the JwtStrategy

During a recent project I downloaded from the internet... In one specific part of the code, the following is implemented: passport.use(new JwtStrategy({ secretOrKey: credentials.secret, jwtFromRequest: ExtractJwt.fromAuthHeader(), }, ...

Design for implementing "new" functionality in JavaScript

I recently delved into the world of JavaScript Patterns through Stoyan Stefanov's book. One pattern that caught my attention involves enforcing the use of the new operator for constructor functions, demonstrated with the following code snippet: funct ...

Set up a single array containing multiple objects in a table, each with its own unique set of keys

I am currently developing an application that retrieves data from one or multiple databases, each with different names and varying numbers of columns. The goal is to consolidate this data into a single report screen and export it as a table. While the tabl ...

Encountering an issue while attempting to run a Node.js server on a Mac, receiving the error message "no appropriate image located."

unknown406c8f2d5ecb:proves airrider3$ node tronServer.js [Error: dlopen(/Users/airrider3/Documents/proves/node_modules/now/node_modules/node-proxy/build/Release/nodeproxy.node, 1): no suitable image found. Did find: /Users/airrider3/Documents/proves/n ...

Query inputting time displaying additional numerical values beyond just minutes

I am adding a time field to a table with a length of 6 in the database. Utilizing the Tempos Dominus Bootstrap library for the time within the form HTML Form <div class="form-group"> <label for="time">Hora</label> ...

Using SQL to Insert Values into Select/Option

I am attempting to create a select form element with predetermined options. <select name="select1"> <option value="value1">Value 1</option> <option value="value2">Value 2</option> <option value="value3">Value 3 ...

Windows and MacOS each use unique methods for displaying linear gradients

Check out this code snippet featuring a background gradient background: rgba(0,0,0,0) linear-gradient(rgb(245, 245, 245),rgba(0,0,0,0)) repeat scroll 0 0; This code renders correctly on Windows (chrome, ie, firefox) https://i.stack.imgur.com/XU2gW ...

Navigating through a PHP table, tracking your progress with a

I have encountered a problem that I need help with. I have been searching the internet for information on how to add a progress bar to my PHP code. Most solutions I found use the style method to display the progress percentage. In the image below, you can ...

Burst or displace meshes outward from the center

I am attempting to separate all the meshes that make up the loaded obj file from each other in order for the user to easily view each mesh individually. I am striving to replicate a similar functionality as shown in this example: Demo To achieve this ef ...

Flexbox: Arrange header and footer in a sidebar layout using flexbox styling

In my content layout, I have structured the sections as header, content, and footer. While I want to maintain this order for small devices, I am looking to shift the header and footer to the sidebar on desktop. I have already implemented this using floats ...

Leveraging python's BeautifulSoup library, one can easily implement HTML selection

Recently, I've started diving into Automate the Boring Stuff and exploring how to create my own programs. Currently, I'm experimenting with beautiful soup's 'select' method in order to extract the value '33' from this cod ...

Experiencing SyntaxError when utilizing rewire and mocha for Node.js testing. Unexpected token encountered

Trying to test a function exported from a nodejs file, I am utilizing q to manage promises. The function returns a promise that is either resolved or rejected internally through a callback. Within this callback, another function from a different location i ...

Performing an HTTP GET request to an endpoint within a RESTful API

I am looking to integrate a feature in my web application that displays the list of online users on my website. To achieve this, I need to make an HTTP GET request to the URL which returns the user data in JSON format. The returned JSON data contains var ...

Pass information from one .jsp file to a JavaScript function in another .jsp file

Here is the content of OneEmployee.jsp: <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> <form> <td> <c:out value="${emp.getEmpid()}"/></td> <td> <input type="text" id="fname" value="<c:out v ...

Form validation has not passed the necessary checks

Struggling to create a new user POST form with Bootstrap form validation but encountering an issue. The button code is as follows: <button class="btn btn-primary btn-addUser" type="submit">Add User</button> This button trig ...

Create unique error messages using Vue validators

Two fields named text and email are included in my template. Below is the structure of the template: HTML <!DOCTYPE html> <html> <head> <title>Vue - Validations</title> <script src="Libraries/vue/vue.min.js&qu ...

Arranging an image next to a form with rows

Note: Utilizing Bootstrap Framework This is the design I am aiming for: https://i.sstatic.net/vAhzY.png Code: <!DOCTYPE> <html> <head> <link rel="stylesheet" type="text/css" href="css/bootstrap.css"> </head> <style> ...

Display a pop-up when hovering over a layer with react-leaflet

I am attempting to display a popup when hovering over a layer in react leaflet. Utilizing GeoJson to render all layers on the map and onEachFeature() to trigger the popup on hover, I encountered an issue where the popup only appeared upon click, not hover. ...

Verifying the existing user in a personalized Ajax form that is used to update a Woocommerce order

Currently, I am developing a form that allows users to update specific order details, such as expenses and the reason for the expense. After updating the order, a JavaScript alert confirms the successful update, and the order's metadata is updated acc ...

Utilizing HTML data retrieved from an ajax request

I am utilizing a load more button to display content fetched from a database via ajax. Here is how the ajax call is structured: // JavaScript Document // Function to load more builds $(document).ready(function(){ var pageIndex = 1; $('#loadmorebuild ...