Animate the coloring process with dynamic motion

Is there a way to dynamically fill a canvas with color and apply animation? I have successfully created a canvas cylinder that fills with color, but I'm hoping for a slow animation effect when the color is filled.

I've tried searching on Google and found suggestions to use animations like 'fadein' or 'ease in', but none seem to be working for me.

Below is the code snippet I'm currently using:


var perc = 0;
$(document).ready(function () {
    // Input focusout event
    $("#my_input").focusout(function (event) {
        if ($("#my_input").val().indexOf("%") != -1) {

            if ($.isNumeric($("#my_input").val().replace('%', ''))) {

                // Allow only specific key presses
                if (event.keyCode == 46 || event.keyCode == 8 || event.keyCode == 37) {
                    //$("#myCanvas").animate({ opacity: 0.25 });
                } else {
                    // Ensure input is a number and block invalid keypresses
                    if (event.keyCode < 48 || event.keyCode > 57) {
                        event.preventDefault();
                    }
                }
                perc = parseInt($("#my_input").val().replace('%', '')) / 100;
                draw();
            }
        } else {
            alert('Value should be in percentage format');
        }
    });
});

The above code handles the filling of the canvas based on the percentage value entered into an input field. The goal is to animate this process smoothly.

If you have any insights or solutions on how to achieve this type of dynamic color filling animation on a canvas element, please let me know!

Answer №1

To ensure that all drawing occurs within a cylindrical container, you can create the container as a clipping region.

This method guarantees that all content will only be visible inside the cylinder-shaped container.

For a visual demonstration and sample code, check out this Demo.

<!doctype html>
<html>
<head>
<link rel="stylesheet" type="text/css" media="all" href="css/reset.css" /> <!-- reset css -->
<script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script>
<style>
    body{ background-color: ivory; }
    canvas{border:1px solid red;}
</style>
<script>
$(function(){

    // canvas related variables
    var canvas = document.getElementById("canvas");
    var ctx = canvas.getContext("2d");
    var cw=canvas.width;
    var ch=canvas.height;

    // general variables
    var PI=Math.PI;
    var PI2=PI*2;

    // cylinder related variables
    var cx=cw/2;
    var cy=ch/2;
    var width=65;
    var height=100;
    var fillY=cy+height/2+5;
    var w2=width/2;
    var h2=height/2;
    var h4=height/4;
    var h8=height/8;
    var h16=height/16;
    var ytop=-h2+h8;
    var cpYtop=-h2-h16;
    var ybottom=h2-h8;
    var cpYbottom=h2+h16;
    var degreeAngle,rAngle,dx,dy,r,a,xx,yy;

    // start the cylinder upright (at 0 degree angle)
    setContainerAngle(0);

    // start the animations
    requestAnimationFrame(animateFill);

    // animate filling the cylinder
    function animateFill(){
        if(fillY>cy-height/2+h8){
            requestAnimationFrame(animateFill);
        }else{
            requestAnimationFrame(animateEmpty);
        }
        draw();
        drawPouring(cx,0,fillY);
        fillY-=0.50;
    }

    // animate emptying the cylinder
    function animateEmpty(){
        if(degreeAngle>-91){
            requestAnimationFrame(animateEmpty);
        }else{
            fillY=cy+height/2+5;
            requestAnimationFrame(animateToBeginning);
        }
        draw();
        drawPouring(xx,yy,ch);    
        setContainerAngle(degreeAngle-0.50);
    }

    // animate rotating the empty cylinder back to upright
    function animateToBeginning(){
        if(degreeAngle<=0){
            requestAnimationFrame(animateToBeginning);
        }else{
            setContainerAngle(0);
            requestAnimationFrame(animateFill);
        }
        draw();
        setContainerAngle(degreeAngle+1);
    }


    // draw the scene (background, cylinder, liquid in cylinder)
    function draw(){

        ctx.fillStyle="gray";
        ctx.fillRect(0,0,cw,ch);

        ctx.save();

        defineFillOutline(cx,cy,width,height,degreeAngle);

        if(degreeAngle>=-90){
            ctx.clip();
            ctx.fillStyle='gold';
            ctx.fillRect(0,Math.max(fillY,yy),cw,ch);
        }

        ctx.restore();

        drawContainer(cx,cy,width,height,degreeAngle);

    }

    // draw the liquid being poured in a vertical stream
    function drawPouring(xx,yy,yyy){
        ctx.save();
        ctx.beginPath();
        ctx.moveTo(xx,yy);
        ctx.lineTo(xx,yyy);
        ctx.lineWidth=5;
        ctx.shadowColor="gold";
        ctx.shadowBlur=8;
        ctx.strokeStyle="gold";
        ctx.stroke();
        ctx.restore();
    }

    // define the clipping region (which is the cylinder)
    function defineFillOutline(x,y,w,h,degrees){
        ctx.save();
        ctx.translate(x,y);
        ctx.rotate(degreeAngle*PI / 180);
        //
        ctx.beginPath();
        ctx.moveTo(-w2,ytop);
        ctx.bezierCurveTo( -w2,cpYtop, w2,cpYtop, w2,ytop);
        ctx.lineTo(w2,h2-h8);
        ctx.bezierCurveTo( w2,cpYbottom, -w2,cpYbottom, -w2,ybottom);
        ctx.closePath();
        //
        ctx.restore();
    }

    // draw the cylinder at the specified angle
    function drawContainer(cx,cy,width,height,degreeAngle){
        //
        defineFillOutline(cx,cy,width,height,degreeAngle);
        //
        ctx.save();
        ctx.translate(cx,cy);
        ctx.rotate(degreeAngle*PI / 180);

        // this is the top-outer lip of the cylinder
        ctx.moveTo(-w2,-h2+h8);        
        ctx.bezierCurveTo( -w2,-h4, w2,-h4, w2,-h2+h8);
        ctx.strokeStyle="royalblue";
        ctx.lineWidth=2;
        ctx.stroke();
        //
        ctx.restore();
    }

    // change the angle of the cylinder
    function setContainerAngle(degrees){
        degreeAngle=degrees;
        rAngle=degreeAngle*Math.PI/180;
        dx=width/2;
        dy=height/2-height/8;
        r=Math.sqrt(dx*dx+dy*dy);
        a=Math.atan2(dy,dx)+Math.PI+rAngle;
        xx=cx+r*Math.cos(a);
        yy=cy+r*Math.sin(a);
    }

}); // end $(function(){});
</script>
</head>
<body>
    <canvas id="canvas" width=300 height=300></canvas>
</body>
</html>

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

Angular UI grid: Arranging numbers in a straight line at the decimal point

I am interested in aligning decimal numbers in Angular UI Grid as shown below. 11.293 .89 233424 .34345 I have considered different approaches such as using a cell template with aligned divs or transparent 0s. Has anyone successfully imp ...

Sinatra application encounters internal server error resulting in AJAX request failure

I'm currently developing a game where a user's guess is submitted to the backend for evaluation and then feedback is returned in the form of an array. To achieve this, I am utilizing AJAX to fetch a set of data from a Sinatra backend. Below is th ...

Updating an iframe's content URL

I am currently working on building a website using Google Web Design and everything is going well so far. I have added an iFrame to the site and now I am trying to figure out how to change its source when a button is pressed. Most of the information I fo ...

Is it possible to modify the global CSS in react-router according to the different routes?

I am attempting to customize a global CSS class (.ant-content) on a per-route basis. I have experimented with importing CSS files that override .ant-content for specific React components loaded in different routes. However, the issue is that these CSS fi ...

Revamping the Bootstrap framework in a major project

Currently, I am undertaking a project that involves the use of bootstrap 2.3.2 stylesheets along with bootstrap 3.0.0 .js scripts. The client side technology is significantly outdated and my primary objective is to update the bootstrap files to leverage th ...

The pqselect plugin in jquery is malfunctioning without any visible errors

I'm really struggling to get this plugin to work. It's the jQuery pqselect plugin for creating multiple select boxes with checkboxes. Even though I've followed the usage instructions, it still doesn't seem to be functioning correctly. ...

I am having trouble getting bootstrap-icons to work in my Angular project and I'm eager to figure it out

I am having trouble incorporating bootstrap-icons into my angular project. Despite running the npm i bootstrap-icons command, I am unable to successfully add icons using icon fonts on my webpage. As a temporary solution, I have added the bootstrap icon CD ...

What is the best way to move the Grid upward when the above content is not visible?

Let me demonstrate what I have been working on. Currently, I am creating a weather application to explore the functionalities of https://material-ui.com/. I am attempting to prototype an animation inspired by Google Flights, which can be seen here: https: ...

Unable to hide jQuery form and receiving undefined function output

I seem to be facing an issue with one of the buttons. It's not functioning properly. Whenever I click on the "Add Run" button followed by the "Home" button, most functions stop working as expected. The dynamically created form doesn't hide, the ...

Creating a scrolling effect similar to the Nest Thermostat

After researching countless references, I am determined to achieve a scrolling effect similar to the Nest Thermostat. I came across this solution on this JSFiddle, but unfortunately, the parent element has a fixed position that cannot be utilized within my ...

Close button situated at the top-right corner overlapped by HTML/CSS styling

Currently attempting to position a button overlapping and extending outside of its parent div, much like the illustration provided. However, my current efforts result in the button being contained within the parent DIV. The visual reference below showcases ...

The div is not showing the image as expected

Having some trouble creating a slideshow within my angular application. Struggling to get the images to display in the html code. To tackle this, I decided to create a separate component specifically for the slideshow (carousel.component). In the main app ...

Tips for creating seamless image transitions using a toggle button

My transition effect is working smoothly, but I am having trouble setting it up for the image. How can I resolve this issue? I attempted the following: var lightsOff = document.querySelector("#lights-off"); var lightsOn = document.querySelector("#lights-o ...

JavaScript toggle display function not functioning properly when clicked

I've been attempting to create a drop-down list using HTML and JavaScript, but for some inexplicable reason, it's just not functioning as expected despite scouring through countless tutorials on YouTube. Below is the snippet of code that I'm ...

Identify certain lines from the paragraph text

Suppose you have an HTML Paragraph Element (e.g., <p>) with certain text sections highlighted using a HTML Mark Element (e.g., <mark>). I am interested in adding a vertical line in the margin or gutter (uncertain about the appropriate term) tha ...

In Wordpress, I am using Php to display posts. How can I create a new list item after every 3 posts, with each subsequent post displayed inside the new list item?

I am new to using PHP and feeling a bit confused with the code below, which is a team slider. In the <ul> tag, there is one <li> containing 3 nested <div>s (each representing a person). Can someone review my code and help me improve it? I ...

Enforce a restriction on the user's input value for the amount field within a React application

I'm looking to limit the user from entering more than 50000 in the input value. How can I achieve this using React? I am currently handling this on the onchange event. onPaymentAmountChanged = (e) => { let inputValue = e.target.value; if (i ...

Selecting elements by class in jQuery using a variable for the class name

Is there a way in jQuery to apply actions to all elements with a specific class, where the class name is determined by a variable? I want to select elements based on this dynamically generated class name. var x = $(this).attr('href').slice(1); ...

Can IE Conditional Comments have a negative impact on page speed?

Debates between "CSS hacks" and "Conditional Comments" have become a regular occurrence for me lately, so I wanted to hear the thoughts of the Stack Overflow community on this topic. <!--[if IE]> <link type="text/css" rel="stylesheet" href="ie-s ...

The JSON GET method displays HTML content when accessed through code or console, but presents a JSON object when accessed through a web address

I am currently trying to execute the following code: $(document).ready(function () { $.ajax({ url: 'http://foodfetch.us/OrderApi/locations', type: 'GET', success: function(data){ alert(data); ...