Using the feColorMatrix SVG filter in CSS versus applying it in JavaScript yields varied outcomes

If we want to apply an SVG filter on a canvas element, there are different ways to achieve this. According to this resource, we can apply a SVG filter to the CanvasRenderingContext2D in javascript using the following code snippet:

ctx.filter = "url(#bar)";

Alternatively, we can also apply the filter in CSS directly on the whole canvas like so:

#canvas {
  filter: url(#bar);
}

In my case, I need to apply the filter in javascript as I only want part of the canvas to be affected. It's worth noting that when applying a feColorMatrix to some or all of the shapes, the results may vary depending on whether the filter was applied through JS on the 2D Context or via CSS on the entire canvas element.

Here is a sample JavaScript code snippet demonstrating how to apply the filter selectively:

const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
ctx.filter = "url(#bar)";
ctx.fillRect(10,10,100,100);
ctx.fillRect(10,120,100,100);
ctx.fillRect(120,10,100,100);
ctx.fillStyle = 'red';
ctx.beginPath();
ctx.ellipse(170, 170, 50, 50, Math.PI / 4, 0, 2 * Math.PI);
ctx.fill();
#canvas {
  /* Uncomment to see the difference */
  /* filter: url(#bar); */
}
<svg xmlns="http://www.w3.org/2000/svg" version="1.1>
  <defs>
    <filter id="bar">
      <fegaussianblur in="SourceGraphic" stdDeviation="10" result="blur"></fegaussianblur>
      <fecolormatrix in="blur" mode="matrix" values="1 0 0 0 0  0 1 0 0 0  0 0 1 0 0  0 0 0 18 -7"></fecolormatrix>
    </filter>
  </defs>
</svg>
<canvas id="canvas" width="400" height="400"></canvas>

Answer №1

When applying CSS filters, it affects the entire canvas image as a whole, which differs from applying filters to individual rectangles in JavaScript code.

Consider this example where transparent rectangles are drawn. The left side shows each rectangle being drawn separately, while the right side has all rectangles drawn in one operation. The difference in results due to globalAlpha is evident.

const ctx = document.querySelector("canvas").getContext("2d");

ctx.globalAlpha = 0.25;
for(let y = 0; y<150; y+=10) {
  // draws each rectangle one after the other
  ctx.fillRect(0, 0, 50, y);
}
for(let y = 0; y<150; y+=10) {
  ctx.rect(100, 0, 50, y);
}
// draws all the right-side rectangles in one go
ctx.fill();
<canvas></canvas>

The same principle applies to filters.
To achieve consistent results, draw all your rectangles once and then redraw the canvas with the filter applied to the whole image.

const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');

ctx.fillRect(10,10,100,100);
ctx.fillRect(10,120,100,100);
ctx.fillRect(120,10,100,100);
ctx.fillStyle = 'red';
ctx.beginPath();
ctx.ellipse(170, 170, 50, 50, Math.PI / 4, 0, 2 * Math.PI);
ctx.fill();
ctx.filter = "url(#bar)";
// clears previous content; alternatively, a second canvas could be used
ctx.globalCompositeOperation = "copy";
ctx.drawImage(canvas, 0, 0);
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" style="position:absolute;z-index:-1">
  <defs>
    <filter id="bar">
      <fegaussianblur in="SourceGraphic" stdDeviation="10" result="blur"></fegaussianblur>
      <fecolormatrix in="blur" mode="matrix" values="1 0 0 0 0  0 1 0 0 0  0 0 1 0 0  0 0 0 18 -7"></fecolormatrix>
    </filter>
  </defs>
</svg>
<canvas id="canvas" width="400" height="400"></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

Exploring Angular 8 Route Paths

Working on an Angular 8 project, I encountered an issue with my code: src/app/helpers/auth.guard.ts import { AuthenticationService } from '@app/services'; The AuthenticationService ts file is located at: src/app/services/authentication.servic ...

Customized Error Handling Function for Ajax Requests

I have a function that works perfectly, but I need to add six more buttons without repeating code. I want each callback to be customizable, with different text for each scenario (e.g. displaying "Please Log In" if the user is not an admin). How can I make ...

Tips for automatically closing SweetAlert after an AJAX request finishes

I recently implemented Sweet-alert into my Angular project. function RetrieveDataFromAPI(url) { SweetAlert.swal( { title: "", text: "Please wait.", imageUrl: "../../app/app-img/loading_spinner.gif", showConfirmB ...

Issue with combining overflow-x, Firefox, and JavaScript

In Firefox, an issue arises that does not occur in other browsers. To see the problem in action, please visit this example page: -removed- Try selecting a page other than the home page. The window will scroll to your selection. You can then scroll down u ...

Leveraging ES6 Symbols in Typescript applications

Attempting to execute the following simple line of code: let INJECTION_KEY = Symbol.for('injection') However, I consistently encounter the error: Cannot find name 'Symbol'. Since I am new to TypeScript, I am unsure if there is somet ...

The variable within my function is not being cleared properly despite using a jQuery function

Recently, I encountered an issue with a function that displays a dialog box to ask users if their checks printed correctly. Upon clicking on another check to print, the "checked_id" value remains the same as the previously executed id. Surprisingly, this i ...

What methods are available for generating a short-lived banner using JavaScript?

I recently entered this industry and am in the process of constructing a website. Utilizing HTML and CSS, I crafted a cookie notification banner. I am seeking guidance on how to ensure that it only appears once "every 24 hours for each user." I attempted ...

Adjust color scheme of drop-down menu

Having trouble changing the background color for my drop down menu. I tried to change the color for the sub div but it's not working. Can anyone help me fix this issue? Here is the code snippet: http://jsfiddle.net/3VBQ6/4/ #nav li:hover ul.sub li { ...

Modifying the DOM within a getJSON callback

My current challenge involves fetching data from the YouTube API and displaying it on my website. However, I am facing an issue where the DOM changes made inside the getJSON's callback function are not reflecting on the webpage. Even though I can see ...

Retrieve JSON information from the driver's console using Selenium with Python

I am trying to retrieve JSON data from the console, which is shown in this image. Here are the codes I have used so far: j = driver.execute_script(" return document.getElementsByClassName('form-group text required assessment_questions_choices_text ...

Storing JWT securely in cookie or local storage for a Node.js/Angular 2 web application

I've been researching how to save jwt tokens in either local storage or cookies but I'm having trouble finding clear instructions online. Can someone provide guidance on how to instruct the server to recognize a user for future sessions? //a ...

Despite receiving a 404 fetch response, the page still exists

I have encountered an issue with my Fetch code (POST) where the response shows status: 404 even though the URL returns a JSON when accessed through the browser. Surprisingly, changing the URL to https://httpbin.org/post brings back normal data. Furthermore ...

Incorporated React component from Rails-assets.org into a Rails application

I have been trying to incorporate a react component from rails-assets.org into my Rails application. Currently, I am using the react-rails gem to write react view in my application. Now, I want to use other react components such as react-router, react-sel ...

Dynamically populate select options using Spring Boot Ajax technology

Hey everyone, I need some help with populating a select tag with a list of objects in JavaScript. Here's an example of the code: @RequestMapping(value="/getAllIndustries") @ResponseBody public List<IndustryModel>getAllIndustries() { return ...

Using CSS :active can prevent the click event from firing

I've designed a navigation menu that triggers a jquery dialog box to open when a link is clicked. My CSS styling for the links includes: .navigationLinkButton:active { background:rgb(200,200,200); } To attach the dialog box, I simply use: $("#l ...

How to trigger a file download instead of opening it in a new tab when clicking on a txt or png file in AngularJS

After retrieving my file URL from the backend API, I am trying to enable downloading when the user clicks a button. Currently, the download function works smoothly for Excel files (`.xlsx`), but for text (`.txt`) files or images (`.jpeg`, `.png`), it only ...

Enhance your SVG progress circle by simply selecting checkboxes

I have a unique system with 5 checkboxes that act as a To-Do list. When I click on each checkbox, the circle's diameter should progressively fill up in increments of 1/5 until all 5 checkboxes are completed. The order in which the checkboxes are click ...

An issue arises in vue.js where the v class binding takes precedence over other bindings and fails to properly remove

I have a game with a punching bag where I want to incorporate an animation class each time the bag is clicked. Once the health meter hits zero, I intend to replace the bag image with one depicting a burst bag. Things are running smoothly up until the poin ...

Guide to dynamically implementing pagination through AJAX calls

In this javascript code snippet, I have a class named PurchaseHistory. var baseUrl = null; var parameters = null; var currentPageNumber = null; var TotalPages = null; var PageSize = null; $(document).ready(function () { baseUrl = "http://localhost/AP ...

The compatibility of Datatables responsive feature with ajax calls appears to be limited

I recently started using the datatables plugin and have encountered an issue with responsive tables. While I successfully implemented a responsive table and an AJAX call on a previous page, I am facing difficulties with it on a new page for unknown reasons ...