Creating luminous patterns on a blank page

Hello, I am experimenting with drawing lights in a canvas similar to this:

<canvas id="myCanvas" width="600" height="300"></canvas>
<script>
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");

ctx.fillStyle = "rgba(0,0,0,0.75)";
ctx.fillRect(0,0,300,300);

ctx.clearRect(0,0,300,300);

var grd = ctx.createRadialGradient(150,150,0,150,150,150);
grd.addColorStop(0, "rgba(255,255,0,0)");
grd.addColorStop(1, "rgba(0,0,0,0.75)");
ctx.fillStyle = grd;
ctx.fillRect(0,0,300,300);

ctx.clearRect(300,0,600,300);

var grd = ctx.createRadialGradient(450,150,0,450,150,150);
grd.addColorStop(0, "rgba(255,255,0,0)");
grd.addColorStop(1, "rgba(0,0,0,0.75)");
ctx.fillStyle = grd;
ctx.fillRect(300,0,600,300);

</script>

The issue arises when the lights overlap

<canvas id="myCanvas" width="500" height="300"></canvas>
<script>
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");

ctx.fillStyle = "rgba(0,0,0,0.75)";
ctx.fillRect(0,0,300,300);

ctx.clearRect(0,0,300,300);

var grd = ctx.createRadialGradient(150,150,0,150,150,150);
grd.addColorStop(0, "rgba(255,255,0,0)");
grd.addColorStop(1, "rgba(0,0,0,0.75)");
ctx.fillStyle = grd;
ctx.fillRect(0,0,300,300);

ctx.clearRect(200,0,500,300);

var grd = ctx.createRadialGradient(350,150,0,350,150,150);
grd.addColorStop(0, "rgba(255,255,0,0)");
grd.addColorStop(1, "rgba(0,0,0,0.75)");
ctx.fillStyle = grd;
ctx.fillRect(200,0,500,300);

</script>

I want the lights to merge without overlapping and also require an image visible under the canvas. How can I achieve this?

Here is the desired effect

I have utilized two canvases, one for the background scenery and another above for the lights.

Although close to my desired outcome, it seems a bit dark where the lights intersect, there is insufficient brightness at the center of each light, giving more of a white glow rather than yellow. Review the existing code here

Thank you

Answer №1

If you're aiming to blend those two gradients together, here are a few recommendations:

  • Avoid using the clearRect() method.
  • Adjust the color stops in the gradient code so that the second stop has a 0 alpha value. This will create a smoother fade effect towards the edges of the circle. Overlapping circles work best when they have fading edges.
  • Consider using arcs instead of fillRect().

Take a look at this example: https://jsfiddle.net/fL4xffnq/3/. While I didn't maintain the original colors, it should give you a clear direction on how to proceed.

Answer №2

jsFiddle : https://jsfiddle.net/UniqueCoder/qwerty123/

coding in javascript

let canvas = document.getElementById('myCanvas');
let ctx = canvas.getContext("2d");

let image = new Image();
image.src = "http://images4.examplesite.com/image/photos/abcdefg.jpg";

image.onload = function () {
    ctx.drawImage(image, 0, 0, 500, 400);

    let gradient1 = ctx.createRadialGradient(150, 150, 0, 0, 150, 200);
    gradient1.addColorStop(0, "rgba(255,255,0,1)");
    gradient1.addColorStop(1, "rgba(0,0,0,0)");
    ctx.beginPath();
    ctx.fillStyle = gradient1;
    ctx.arc(150, 150, 200, 0, Math.PI * 2, false)
    ctx.fill();

    let gradient2 = ctx.createRadialGradient(350, 150, 0, 350, 150, 200);
    gradient2.addColorStop(0, "rgba(255,255,0,1)");
    gradient2.addColorStop(1, "rgba(0,0,0,0)");
    ctx.beginPath();
    ctx.fillStyle = gradient2;
    ctx.arc(350, 150, 200, 0, Math.PI * 2, false)
    ctx.fill();
};

Answer №3

Enhancing @nisargjhaveri's response by incorporating the setting

ctx.globalCompositeOperation = "lighter"
produces a visually pleasing effect.

function drawBackground() {
  var can = document.getElementById('background');
  var ctx = can.getContext('2d');
  var grd = ctx.createLinearGradient(0, 0, 0, 150);
  grd.addColorStop(0, "rgba(0,255,255,1)");
  grd.addColorStop(1, "rgba(30,100,200,1)");
  ctx.fillStyle = grd;
  ctx.fillRect(0, 0, 500, 150);
  var grd = ctx.createLinearGradient(0, 150, 0, 300);
  grd.addColorStop(0, "rgba(15,75,25,1)");
  grd.addColorStop(1, "rgba(30,150,50,1)");
  ctx.fillStyle = grd;
  ctx.fillRect(0, 150, 500, 300);
}

drawBackground();

var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
var bg = document.getElementById("background");

var x1 = 150;
var y1 = 150;

var x2 = 350;
var y2 = 150;

var step1 = {
  x: 1,
  y: 1
};
var step2 = {
  x: -1,
  y: 1
};

function loop() {
  ctx.save();
  ctx.fillStyle = "rgba(0,0,0,1)";
  ctx.clearRect(0, 0, 500, 300);

  // Creating a gradient for the circles

  // Circle one
  var grd = ctx.createRadialGradient(x1, y1, 0, x1, y1, 150);
  grd.addColorStop(.75, "rgba(255,255,0,1)");
  grd.addColorStop(1, "rgba(255,255,0,0)");
  ctx.beginPath();
  ctx.fillStyle = grd;
  ctx.arc(x1, y1, 150, 0, Math.PI * 2, false)
  ctx.fill();

  // Circle two
  var grd = ctx.createRadialGradient(x2, y2, 0, x2, y2, 150);
  grd.addColorStop(.75, "rgba(255,255,255,1)");
  grd.addColorStop(1, "rgba(255,255,255,0)");
  ctx.beginPath();
  ctx.fillStyle = grd;
  ctx.arc(x2, y2, 150, 0, Math.PI * 2, false)
  ctx.fill();

  ctx.globalCompositeOperation = "source-atop";
  ctx.drawImage(bg, 0, 0, bg.width, bg.height);

  ctx.globalCompositeOperation = "destination-atop"
  ctx.fillStyle = "rgba(63,63,63,1)";
  ctx.fillRect(0, 0, c.width, c.height);

  ctx.restore();


  step1.x = x1 > c.width ? -1 : x1 < 0 ? 1 : step1.x;
  step1.y = y1 > c.height ? -1 : y1 < 0 ? 1 : step1.y;
  step2.x = x2 > c.width ? -1 : x2 < 0 ? 1 : step2.x;
  step2.y = y2 > c.height ? -1 : y2 < 0 ? 1 : step2.y;
  x1 += step1.x;
  y1 += step1.y;
  x2 += step2.x;
  y2 += step2.y;


  setTimeout(loop, 1000 / 60);
}

loop()
<canvas id="background" width="500" height="300" style='display:none'></canvas>
<canvas id="myCanvas" width="500" height="300"></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

Are you interested in monitoring the website's past activity?

Similar Question: How to maintain browser history when utilizing Ajax? I've been trying to find a solution for this issue, but so far I haven't had any luck. Here's the thing: I created a template for my homepage that might not be perfe ...

Upgrade button-group to dropdown on small screens using Bootstrap 4

I am currently developing a web application and incorporating Bootstrap 4 for certain components such as forms and tables. Within the design, I have included buttons grouped together to display various actions. Below is an example code snippet: <li ...

angular.js:13920 Alert: [ngRepeat:dupes] Multiple occurrences in a repeater

I encountered an issue while attempting to parse a JSON file and map it in HTML. Here is the JavaScript code snippet: searhController.orderlogs.results = JSON.stringify(response.data); This is how it's implemented in Angular: <tr ng-hide="searh ...

Mastering the alignment of Material-UI Menu items

When using the menu and menu item components of material-ui to create a select dropdown menu, I encountered an unusual issue where the dropdown menu always expands to the left side of the box, as shown in the image below: https://i.stack.imgur.com/ykRrp.jp ...

obtain the $http service and make a request

I am trying to access the $http service in AngularJS and execute the get function within my custom asyncAction function call without involving any HTML or Bootstrap. Can anyone help figure out a way to achieve this without manually inserting markup or trig ...

How to easily toggle multiple elements using jQuery

I'm having trouble getting this block of code to function properly: $("a.expand_all").on("click",function(){ $(this).text('Hide'); $('.answer').each(function () { $(this).slideDown(150, function () { $( ...

Explore our collection of videos featuring exclusive content on our video gallery. Please note

I am attempting to create a video gallery using YouTube videos. Here is the current code I have: //html... <div id="videogal" ></div> //javascript //initializing the gallery //mplv is an array, retrieving data after a database query //mplv[ ...

Definition of a class in Typescript when used as a property of an object

Currently working on a brief .d.ts for this library, but encountered an issue with the following: class Issuer { constructor(metadata) { // ... const self = this; Object.defineProperty(this, 'Client', { va ...

What is the correct way to execute a POST request?

Currently tackling a basic API project. Managed to nail the GET & DELETE requests, but the POST request is giving me a hard time. I'm almost positive it's a beginner mistake, but I can't seem to figure out the logic here. This specific file ...

How do you populate a dropdownlistfor in ASP.NET MVC after a form

My issue is that <form> @Html.DropDownListFor(x => x.City, provinces, "--Select City--", new { @class = "dropdownList" }) @Html.DropDownListFor(x => x.district, Enumerable.Empty<SelectListItem>(), "--Select district--") < ...

Error encountered: Uncaught SyntaxError - An unexpected token '<' was found while matching all routes within the Next.js middleware

I am implementing a code in the middleware.ts file to redirect users to specific pages based on their role. Here is the code snippet: import { NextResponse } from 'next/server' import type { NextRequest } from 'next/server' import { get ...

Detecting the click area within a window using JavaScript to automatically close an element

Hello everyone, I am currently working on implementing a JavaScript code that is commonly used to detect click areas for closing an element such as a side navigation or a floating division when the user clicks outside of the element. The functionality wo ...

Error: A reference to an undefined alertbox with a value extracted from a list was not caught

When I click on a button, I want to display the first value in a list using an alert. I found some inspiration from this discussion. Although the original solution used a table instead of a list, I attempted to adapt it to my needs. However, it seems like ...

Issue with PHP functionality not functioning properly

I've been working on implementing an AJAX Form to allow users to upload their profile picture on my website. However, I've encountered some difficulties with the process. I have created a PHP page where the form is supposed to be posted using AJA ...

Best approach for retrieving and adding a large number of images when dealing with slower connections

Currently, I am retrieving 100-200 images using a combination of ajax-php-mongodb. The process involves ajax making an initial call with parameters, php on the server side locating the appropriate mongo document containing all image file ids in grid fs, fe ...

When attempting to modify an object that was initialized outside of a function, I am unable to change its value, or sometimes the function may not run at all. This

Currently in the process of constructing a social network utilizing nodejs, my knowledge on the subject matter is quite novice. This marks my initial discourse on the topic, and I would greatly appreciate your comprehension. Within my social network frame ...

Having difficulty including the Column Name in the Jqgrid footer for sum calculation

I was working on the Jqgrid code and found a way to display the sum correctly in the footer of the grid. var colSum = $("#dataGrid").jqGrid('getCol', 'Amount', false, 'sum'); $("#dataGrid").jqGrid('footerData', &a ...

Incorporate a .php webpage into a div using Ajax and Javascript

(I'm still learning the ropes here.) I've created a page where users can toggle between different sorting options for posts. Depending on their selection, the corresponding content should be displayed. function loadNewContent() { $.ajax({ ...

Unable to display JSON results in a tabular format

After successfully implementing the AJAX method in jQuery, I am able to receive a response. However, I am encountering difficulties when trying to display the arrays in a table format. success:function(resp){ var json =JSON.parse(JSON.stringif ...

Struggles with handling asynchronous events in Angular

I'm currently working on a piece of code that iterates through an array containing 10 items. For each item, a request is made and the returned data is stored in another array. The entire process goes smoothly until reaching the line that contains $q.a ...