Animating the scaling of bezier curves

I am looking to create an animation that scales the two Bezier curves of my Heart canvas element. I attempted to adjust the values in front of all bezier curve parameters, but unfortunately, it stopped drawing the bezier curve altogether. How can I successfully scale both curves to make them larger?

Heartdraw()

    draw2(): void {

        crc2.beginPath();
        crc2.restore();
        crc2.moveTo(this.x, this.y); 
        crc2.bezierCurveTo(this.x + 82, this.y - 40, this.x, this.y - 80, this.x, this.y - 50);
        crc2.save();
        crc2.stroke();
        crc2.moveTo(this.x, this.y);
        crc2.bezierCurveTo(this.x - 82, this.y - 40, this.x, this.y - 80, this.x, this.y - 50);
        crc2.fillStyle = "Red";
        crc2.fill();
        crc2.restore();
        crc2.closePath();
        crc2.save();


    }

}

My previous attempts:

  initScale: number = 1;
    scaleVal: number;


    animate(): void {

        if(this.scaleVal == 1){
        this.scaleVal += 2;
        }
        else if (this.scaleVal == 3) {
            this.scaleVal -= 2;
        }

    }




    draw2(): void {

        crc2.beginPath();

        crc2.restore();
        crc2.moveTo(this.x, this.y); 
        crc2.bezierCurveTo(this.scaleVal * this.x + 82, this.scaleVal * this.y - 40, this.scaleVal * this.x, this.scaleVal *  this.y - 80, this.scaleVal * this.x, this.scaleVal *  this.y - 50);
        crc2.save();
        crc2.stroke();
        crc2.moveTo(this.x, this.y);
        crc2.bezierCurveTo(this.x - 82, this.y - 40, this.x, this.y - 80, this.x, this.y - 50);
        crc2.fillStyle = "Red";
        crc2.fill();
        crc2.scale(this.xScale, this.yScale);
        crc2.restore();
        crc2.closePath();
        crc2.save();


    }

}

Answer №1

Changing the appearance of drawn elements

Utilize canvas transformation to modify the appearance of drawn elements.

In the instance below, ctx.translate is employed to position the rendering and ctx.scale for scaling purposes.

The transformation can be reverted using

ctx.setTransform(1, 0, 0, 1, 0, 0)
, which is more efficient than using ctx.save and ctx.restore.

Adjusting path without affecting stroke

To maintain a consistent lineWidth, reset the transformation after specifying the Bezier path and prior to calling stroke.

requestAnimationFrame(mainLoop);  // initiate animation
const ctx = canvas.getContext("2d");
const heart = {
    x: 100, y : 100, scale : 1,
    draw() {
        ctx.fillStyle = "Red";
        ctx.lineWidth = 4;

        ctx.translate(this.x, this.y);     // specify origin 
        ctx.scale(this.scale, this.scale); // set scale

        ctx.beginPath();
        ctx.moveTo(0, 0); 
        ctx.bezierCurveTo(82, -40, 0, -80, 0, -50);
        ctx.bezierCurveTo(0, -80, -80, -40, 0, 0);
        
        // resetting transform to maintain constant line width after forming the path
        ctx.setTransform(1, 0, 0, 1, 0, 0);  // revert to default transform
        ctx.stroke();
        ctx.fill();
    }
}

function mainLoop(time) {
    ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
    heart.scale = Math.sin(time / 100) * 0.2 + 1; // animate scale
    heart.draw();
    requestAnimationFrame(mainLoop);
}
<canvas id="canvas"></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

Is there a specific reason why Angular2 always allows for the creation of a unidirectional data flow?

Here is a great article that I came across. The article explains the speed difference between angular1 and angular2, stating that one reason for the faster performance of angular2 is its ability to create a unidirectional change detection tree. However, ...

Creating object-oriented designs in TypeScript: leveraging subclassing to account for differences in constructors

Working with ES6 classes and TypeScript to create a user interface, I have a base class named Control. I am looking for a way to create a Button, which is essentially an instance of Control with predefined properties. To achieve this, I have used Button as ...

Enhance the variety of types for an external module in TypeScript

I am in the process of migrating an existing codebase from a JavaScript/React/JSX setup to TypeScript. My plan is to tackle this task file by file, but I have a question regarding the best approach to make the TypeScript compiler work seamlessly with the e ...

Angular interceptor allows the execution of code after the outgoing request has completed its process

In the process of creating a simple interceptor, I have encountered an issue. The interceptor is designed to check if an outgoing request is targeting a specific endpoint type, namely events and favoriteevents. While the interceptor works almost as intend ...

What is the best way to incorporate the active class in the initial div utilizing *ngFor within Angular 7?

I've got a series of carousel-item divs being repeated using *ngFor. Now, I'm trying to figure out how to dynamically add the active class to just the first div (carousel-item). Any suggestions on how to achieve this in Angular 7? component.html ...

Tips on updating x-label formatting (to display months in words) utilizing morris.js with Angular 5

Snapshot of my Request. I'm looking to alter the xLabel (2018-01 - to - Jan) and I am utilizing morris.js. ...

Ways to tally selected checkboxes in Angular 7?

I'm struggling to count the checked checkboxes on my form that reads data from an array. I have tried a few methods, but nothing seems to work. Since this is new to me and I am not familiar with how it works, could someone please provide guidance? I a ...

Can you explain the significance of "..." in Angular2 and what purpose it serves?

Can you explain the use of "..." in Angular and what it is called? I am curious about why "...flash" is a parameter in the addFlash method within an array.push(). In the toggleFlash method, why is there "..." instead of using the this keyword? flashs: IF ...

Updating a data structure to include a new attribute within a subcategory (Routes)

Is there a way to include the whenRoute optional parameter in the data section of the Route type without directly altering the Angular types file? const routes: Routes = [ { path: 'pages', loadChildren: () => import('./pages/pa ...

Enforcing Type Safety on String Enums in Typescript Using the 'const' Assertion

I am trying to use an enum for type checking purposes. Here is the enum I have: enum Options { Option1 = "xyz", Option2 = "abc" } My goal is to create a union type of 'xyz' | 'abc'. However, when I attempt to d ...

Unleashing the power of Angular 7+: Extracting data from a JSON array

As a newcomer to Angular and API integration, I am facing a challenge in fetching currency exchange rates data from the NBP Web API. The JSON file structure that I'm working with looks like: https://i.stack.imgur.com/kO0Cr.png After successfully ret ...

Encountering an issue with React Redux and Typescript involving the AnyAction error while working on implementing

While integrating redux-persist into my React project, I encountered an error. Previously, Redux was working smoothly, but upon the addition of redux-persist, I started receiving this error message: Types of property 'dispatch' are incompatib ...

Is there an alternative method to incorporate the 'environment.ts' file into a JSON file?

In my Angular application, I need to import assets based on the env configuration. I am attempting to extract the patch information from environment.ts and save it into my assets as a json file. However, I am unsure of the proper method to accomplish this. ...

Assistance required in creating a numerical list from an array of objects

I'm currently facing an issue with creating a numbered list from an array of objects. Below, you'll find the code containing the objects. You need to add the necessary TS code to display the atom names along with their weights in a numbered list ...

Exploring Generics and Type Inference within TypeScript

(In reference to this question) I've developed a function that takes in a configuration object containing state definitions, essentially creating a state machine. For example: const machine = createStateMachine({ initial: 'inactive', s ...

Creating a customized Axios instance in Typescript can provide more flexibility and control over

I am looking to create an API with a customizable instance using Axios. Ideally, I want to be able to use a basic instance like this: api.get("url")... In addition, I would like to have the flexibility to add dynamic bodies and access them using something ...

Storing an arrayBuffer in a MySQL database using blob and xdevapi in Typescript can be accomplished by converting

I need to save various user files (mostly images) that are uploaded via a HTML input field into a MySQL database. My goal is to store the arrayBuffer of these files in a MySQL blob using @mysql/xdevapi. Current setup: Using Angular with Electronjs MySQL ...

Can template literal types be utilized to verify if one numeric value is greater than another?

I am attempting to define the Record for migration functions, which use the direction of the migration as the key: v${number}-v${number}, Considering that these migrations are all UP, they need to be validated as v${first-number}-v${first-number + 1} and ...

Tips for preventing duplicate data fetching in Next.js version 13

I am currently in need of retrieving information from the database, generating metadata, and displaying the page content. The current method I am using is as follows: export const generateMetadata = async ({ params: { questionSlug }, }: Props): Promise&l ...

Create dynamic text on an HTML canvas starting from the center, displaying one character at a time while constantly adapting to the formatting

I am currently in the process of developing a website that has the capability to animate text, drawing each character onto a canvas one by one. I have successfully completed the initial coding for this functionality. However, my next challenge involves cen ...