Is there a way to ensure that only individual objects are selected in FabricJS on the Canvas, rather than a group of objects?

One issue I am facing is with my method for selecting objects on the canvas by clicking a button. How do I ensure that it skips selecting groups and only selects individual objects?

Generating a group of shapes here:

const group = new fabric.Group([
      new fabric.Rect({ width: 100, height: 100, fill: 'red' }),
      new fabric.Rect({ width: 100, height: 100, fill: 'yellow', left: 100 }),
      new fabric.Rect({ width: 100, height: 100, fill: 'blue', top: 100 }),
      new fabric.Rect({
        width: 100,
        height: 100,
        fill: 'green',
        left: 100,
        top: 100
      })
    ])
this.canvas.add(group)

Creating an individual shape:

let rect1 = new fabric.Rect( {
      width: 100,
      height: 100,
      fill: 'transparent',
      stroke: 'blue',
      left: 140
    });
this.canvas.add(rect1)

Creating another individual shape:

let rect2 = new fabric.Rect( {
      width: 100,
      height: 100,
      fill: 'transparent',
      stroke: 'blue',
      left: 240
    });
this.canvas.add(rect2)

My current select method is selecting both the group and individual objects. How can I modify it to only select individual objects and not groups?

multiseleccion(){
    this.canvas?.discardActiveObject();
    
      this.selection = new fabric.ActiveSelection(this.canvas?.getObjects(), {
      canvas: this.canvas
      });
      this.canvas?.setActiveObject(this.selection);
      this.canvas?.requestRenderAll();

Answer №1

When using Fabricjs, the getObjects() method can provide an array of objects, but it doesn't offer a direct way to differentiate between a group and a single shape. However, there is a workaround available. Groups have a unique property called _objects which individual shapes do not possess.

To address this issue, we can iterate over the returned array, identify objects with the _objects property, and remove them accordingly. Subsequently, we can pass the refined array to the setActiveObject() method for further processing.

Here's a demonstration:

var canvas = new fabric.Canvas('c');
const group = new fabric.Group([
    new fabric.Rect({
        width: 100,
        height: 100,
        fill: 'red'
    }),
    ...
])
canvas.add(group);

let rect1 = new fabric.Rect({
    width: 100,
    height: 100,
    fill: 'transparent',
    stroke: 'blue',
    left: 140
});
canvas.add(rect1);
...
multiseleccion();
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/5.2.4/fabric.min.js" integrity="sha512-HkRNCiaZYxQAkHpLFYI90ObSzL0vaIXL8Xe3bM51vhdYI79RDFMLTAsmVH1xVPREmTlUWexgrQMk+c3RBTsLGw==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<canvas id="c" width="400" height="300" style="border:1px solid #ccc"></canvas>

Answer №2

Each element (predefined) within fabric possesses a type property that serves to distinguish one object from another. In this scenario, you have the ability to sort through objects of the 'group' type, which would provide the most streamlined solution.

I've made adjustments to your multiselection function in order to group all canvas objects excluding those classified as groups.

multiselection() {
  this.canvas?.discardActiveObject();

  const objectsWithoutGroups = this.canvas?.getObjects().filter(fabricObject => fabricObject.type !== 'group') || []
  if(objectsWithoutGroups.length) {
    this.selection = new fabric.ActiveSelection(objectsWithoutGroups, {
      canvas: this.canvas
    });
    this.canvas?.setActiveObject(this.selection);
    this.canvas?.requestRenderAll();
  }
}

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

The alignment of elements side by side in Angular Flex is not supported, specifically in versions Angular 8.2.1 and Flex-Layout 8.0.0.beta 26

I'm attempting to arrange my boxes in a single line, with the ability to wrap and switch to column mode on smaller phone screens. Desired layout: Wins Losses Ties Points On shrinking screen: Wins Losses Ties Points Code ...

Having trouble fetching information from a JSON file stored in a local directory while using Angular 7

I am currently experiencing an issue with my code. It works fine when fetching data from a URL, but when I try to read from a local JSON file located in the assets folder, it returns an error. searchData() { const url: any = 'https://jsonplaceholde ...

A versatile method to organize a multi-dimensional array of items

I need help sorting a nested array using a generic function. The sorting should be based on the values of the items within the nested array. Here is an example of my array: type Person = { id: number, name: string, childs: Child[] } type Chil ...

Angular throws a NullInjectorError when a unit test fails due to issues with dependency

As a newcomer to Angular, I am struggling to grasp the concept of Dependency Injection (DI) and how it functions. My current challenge involves trying to pass a unit test successfully. Below is the code for the test; import { TestBed } from '@angula ...

What is the best way to predefine a value for a checkbox in Angular?

Here is the code snippet I am currently using: <input type="checkbox" [(ngModel)]="i.checkt" [ngModelOptions]= {standalone:true} (change)="recovery(i.checkt,i.TherapeuticArea)"> {{i.TherapeuticArea}} I have encountered an issue where setting stan ...

Arrange a collection of objects by two criteria: the end time, followed by the status in accordance with the specified array order if the end times are equal

Is this the best method to arrange data by using infinity? I gave it a try but it doesn't quite meet my requirements. data = [{ "status": "Accepted", "endTime": "" }, { "status": "New", ...

Context failing to refresh value upon route changes

My current context setup is as follows: import { createContext, ReactNode, useState } from "react"; type props = { children: ReactNode; }; type GlobalContextType = { name: string; setName: (value: string) => void; }; export const Glob ...

What steps can I take to troubleshoot and repair my accordion feature within an Angular project?

As a newcomer to Angular, I recently attempted to create an accordion component but encountered unexpected behavior. Here is the HTML code for my attempt: <div class="faq-item-container"> <h1 class="mt-1 mb-5"><strong>Frequently A ...

React textarea trigger function on blur event

https://codesandbox.io/s/react-textarea-callback-on-blur-yoh8n?file=/src/App.tsx When working with a textarea in React, I have two main objectives: To remove focus and reset certain states when the user presses "Escape" To trigger a callback function (sa ...

What is the process for adjusting the color of axes in vue-chartjs?

Seeking help on how to adjust the color of the axis in my graph. Has anyone encountered a similar issue before? The chart I'm working with resembles the one shown in the image. Not sure if this issue is related to it being a time graph. Below is the V ...

I encountered an issue while trying to install the latest version of AngularFire, receiving an error

Recently, I initiated a new Angular Material project and encountered the following errors: moblizeit@Vikrams-MBP scanbuddyadmin % ng add @angular/fire@latest ℹ Using npm as the package manager ⚠ There are unmet peer dependencies within the package. Add ...

Running a single test in Angular without using fdescribe or fit

My project has numerous tests that are not being maintained, causing errors when running ng test due to import issues in .spec.ts files. Is there a way to execute a single file test for a service without having to clean up all the tests? Perhaps using Php ...

Use Typescript to access and utilize the value stored in local storage by using the

Trying to retrieve the language setting from localHost and implement it in a translation pipe as shown below: transform(value: string): string {... localStorage.setItem("language", JSON.stringify("en")); let language = JSON.parse(loca ...

Validator for IP addresses in Angular reactive forms

Hey there, I'm currently trying to implement a validator for an IP address in Angular. Strangely, even when I input an invalid IP address like 12.2.2.2..., the GUI indicates it is valid (as shown in the image). However, the console logs reveal that it ...

Having Trouble Retrieving Data from Observable in Angular 2 and Typescript

I've encountered a promise error when trying to access a variable that receives data from an observable. Here's an example: Within my component, I have defined the Stat class: export class Stats { name: string; percentage: number; constru ...

Retrieving the ng-content from an ng-template within one component and passing it to another component

Although there are various approaches available, my preference is to utilize ng-template, ng-content, and the @ContentChild() decorator in a specific way inspired by the implementation of Angular Material components. In this scenario, I have defined two c ...

Is it possible to access your app directly from the browser without requiring any user prompts?

After successfully setting up my app for both android and ios with the necessary app link and universal link, I am now focusing on redirecting users from a specific website to my app. The mobile aspect is all set, but I need to work on the browser/server s ...

Deriving types from object combinations

Can the Foo type be 'flattened' to return { A?: string; B? number } in the code snippet below? type Foo = { A: string } | { B: number } type Flatten< T, Keys extends keyof T = T extends any ? keyof T : never, > = { [K in Keys]?: T[K] } ...

Passing Imported Module to Feature Module in Angular 7

In my Angular 7 app, I have set up a hierarchy of feature modules. The structure looks like this: app admin (UI module imported here) feature1 feature2 public Within the admin module, I have included a UI framework module. My question is, if modules ...

When the mat-tree collides with a stylish css grid

Is there a way to transform a lengthy checkbox tree into a more manageable grid layout? The main issue is the lack of grouping wrappers, with only partial padding indicating group relationships. Check out this StackBlitz link for reference It seems that ...