Looking for a demonstration on how to utilize fabricjs.d.ts in TypeScript?

I am currently using fabricjs in a project that I am transitioning to TypeScript, but I am having trouble understanding how to integrate it. In the past, I would create custom objects like this:

my.namespace.Control = fabric.util.createClass(fabric.Object, {
    id: "",
    type: 'Control',
    color: "#000000", 
    ...
});

For my new project, I have downloaded the TypeDefinition file from this source, but I am unsure of how to proceed.

Upon inspecting the .d.ts file, it seems that fabric.Object is not recognized as a Function, meaning it cannot be passed to createClass. Additionally, createClass itself returns void, preventing me from assigning its value to a variable.

Assuming all these issues were resolved, how should I structure this to adhere to TypeScript conventions? More specifically, how do I export it for use elsewhere when the Control class is required?

Has anyone successfully implemented this and can provide examples?

Answer №1

To create a TypeScript class that extends a Fabric class, you can define the following interfaces and class:

export interface IMindObjectOptions {
    item: IMindItem;
}

export interface IMindExpanderOptions extends IMindObjectOptions {
    x: number;
    y: number;
    radius: number;
    isExpanded: boolean;
}

export class MindExpander extends fabric.Circle implements IMindObjectOptions {

    public constructor(options: IMindExpanderOptions) {
        const circleOptions: ICircleOptions = {
            originX: "center",
            originY: "center",
            left: options.x,
            top: options.y,
            radius: options.radius,
            stroke: "#000000",
            fill: options.isExpanded ? "#00FFFF": "#00FF00",
            selectable: false
        };
        super(circleOptions);
        this.item = options.item;
    }

    public readonly item: IMindItem;
}

Although the code above functions properly in a browser environment, it may encounter issues when executed in Node.js.


If you intend to use the code in a Node.js setting, like for running unit tests without a browser, follow these steps:

import {assert} from "chai";
import * as f from 'fabric';
import {ITextOptions} from "fabric";

declare function require(s: string): any;
declare const __dirname: string;

const fabric = require("fabric").fabric;

interface ITextConstructor {
    new(text: string, options: ITextOptions): f.Text;
}
function getTextConstructor(): ITextConstructor {
    return fabric.Text;
}

describe("Node.js configuration", function () {
    it("Fabric module is correctly imported", function () {
        const x = fabric.Text as f.Text;
        assert.equal(typeof x, "function");
    });
    it("The Fabric class can be extended", function () {
        class SubText extends getTextConstructor() {
            public constructor(text: string, options: fabric.ITextOptions) {
                super(text, options);
            }
        }

        const c = new SubText("Hello", {left: 100, top: 100});
        assert.equal(c.text, "Hello");
        assert.isNotNull(c);
    });
});

Answer №2

When incorporating fabricjs.d.ts into your code, the traditional approach was to place it at the beginning of your file :

/// <reference path="path/to/your/fabricjs.d.ts" />

If you acquire it through tsd, you must reference your tsd.d.ts bundle file.

However, with typescript 1.6.2 and vscode, all you need to do is download the reference file via tsd to access the definitions in your code.

Inside the d.ts file, there are two method signatures:

createClass(parent: Function, properties?: any): void;

createClass(properties?: any): void;

Hence, your code may seem invalid because fabric.Object as the interface IObjectStatict cannot be assigned to type Function. To resolve this, you can cast fabric.Object as a Function by:

my.namespace.Control = fabric.util.createClass(<Function>fabric.Object, {
  id: '',
  type: 'Control',
  color: '#000000', 
  ...
});

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 it possible to implement lazy loading for data in TypeScript classes?

Looking to optimize my Angular application's data structure when consuming a RESTful API. My goal is to only load necessary data from the server on demand. For instance, if I have a collection of Building objects each with a set of tenant IDs in an a ...

Determining the final value of the last handle in a jQuery UI slider with multiple sliders present

I need help retrieving the first and last handle values from a jQuery UI range slider when there are multiple sliders on the page. Currently, my code is set up to grab the last value from the last slider's last handle. I attempted to address this by u ...

What is the best method for accessing a store in Next.js with Redux Toolkit?

Currently, I am working on incorporating integration testing for my application using Jest. To achieve this, I need to render components in order to interact with various queries. However, in order to render a component, it must be wrapped in a Provider to ...

Getting rid of mysterious Google Analytics script from WordPress

My client has requested that I incorporate Google Analytics into her website. After accessing her Google account, I attempted to paste the tracking code into the appropriate section of the Wordpress plugin. To my surprise, the code did not work as expect ...

EBUSY: Unable to access resource due to being busy or locked, unable to retrieve information from 'C:hiberfil.sys'

I am running into an issue while attempting to publish an npm package. The error message I keep receiving is causing me some trouble. Does anyone have any suggestions on how I can resolve this? Your help would be greatly appreciated! Thank you in advance ...

Why does a basic multiline regex work in ECMAScript but not in .NET?

Currently, I am working on a small utility program in C# that aims to enhance all of my Visual Studio C# item templates by adding extra using ; statements. To achieve this, I have developed a simple regular expression to extract the existing namespace impo ...

How to retrieve an anchor element from a list using JavaScript

My current code loops through each <li> within a <td> cell and adds a class to the <li>. I have now inserted <a> tags between each <li> and am facing challenges in accessing the <a> tags. What I actually want is to assig ...

Click a button to spin images around

Is there a way to rotate an image by 90 degrees, 180 degrees, and 360 degrees with the click of a button? <img class="test" id="image" src="images/image" alt="This is the Display Image" /> I attempted to use the following script, but was not satisf ...

Why isn't JQuery's .prependTo('body') function functioning correctly?

It's getting late and I should probably call it a night, but I am completely puzzled. I hate to admit it, but why isn't this working?? var informationBox = ''; informationBox += '<div class="informationBox">'; informati ...

Generate and save a document

Upon clicking the button, I am trying to generate a CSV file and download it right away. My current approach is as follows: html: <a class="btn btn-primary" @click="downloadCsv">Download CSV</a> <a v-if="fileObjectUrl !== null" ref="down ...

Discord.js counter feature

Recently, I attempted to create my own counting system for my server inspired by bots like countr. Here is the code snippet I came up with: if (message.channel.id === "794733520458612736") { const numdb = db.get("numdb"); if (me ...

Encountering a NoSuchElementException when transitioning from frame[0] to window[1] in Firefox GeckoDriver using Selenium with Python

Encountered an issue with the Firefox GeckoDriver browser where I receive an error stating `element not found`. The problem arises when I navigate from window[1] to frame[0], back to window[1], and then attempt to click the close frame button. I prefer u ...

When choosing an item in the typeahead feature, the selected value is empty

I'm currently integrating typeahead into an existing project, so I assume the issue lies within Below is my code snippet: <pre>Model: {{entry.value | json}}</pre> <input ng-show="entry.isToShow" class="form-control col-xs-12 " ng-mo ...

Manipulate the name of a property or field using TypeScript

I am in the process of creating a bilingual blog using Nuxt.js and TypeScript. This application interacts with a REST API to retrieve data that is structured like this: { "Headline_de": "Mein erster Blogpost", "Headline_en" ...

Avoid consistently updating information

I am experiencing a strange issue in my project. I have 2 tabs, and in one tab, there are checkboxes and a submit button. The user selects items from the checkboxes, and upon clicking the button, they should see their selections in the other tab. This fu ...

Invalid file format for product images in Magento version 1.9.0.1

Every time I try to upload an image in the product option, Magento 1.9.0.1 gives me an error saying "Disallowed file format." ...

PHP Dropdown List - Default option should be set to "all" (or "Alle")

My website displays data to users based on the State they reside in, with a filter provided through a drop-down list allowing them to select any specific State or view data from all States. Currently, the default selection shows the user data from their ow ...

JSON schema for validating HTML forms

As someone new to Angular, I've been looking for ways to implement form validation using JSON schema with no luck so far. If anyone has any insights or solutions, I would greatly appreciate the help! ...

Seeking assistance with TypeScript promises

Just starting out with typescript and nodejs, but I've got to tackle some issues in the typescript code. I'm looking to execute an ECS one-off task using Pulumi. I have the documentation on how to run the task from the taskDefinition, which can ...

Discover the power of catching Custom DOM Events in Angular

When working with an Angular library, I encountered a situation where a component within the library dispatches CustomEvents using code like the following: const domEvent = new CustomEvent('unselect', { bubbles: true }); this.elementRef.nati ...