CroaToa
CroaToa

Reputation: 910

How to get pixel color from canvas with background-color gradient?

I have canvas element with background color linear gradient. I want to get clicked pixel color, but every time I got [0, 0, 0, 0]. Then I've tried to get color of first pixel, but no luck.. What is wrong with that code?

const canvas = document.getElementById("example");

canvas.onclick = function(event) {
	const ctx = event.target.getContext("2d").getImageData(1, 1, 1, 1).data;
	console.log(ctx)
}
#example {
    background: linear-gradient(54deg, rgba(179, 63, 19, 1) 0%, rgba(160, 79, 44, 1) 8%, rgba(33, 238, 20, 1) 42%, rgba(35, 182, 208, 1) 61%, rgba(0, 212, 255, 1) 76%, rgba(0, 212, 255, 1) 84%, rgba(0, 212, 255, 1) 96%);
	width: 500px;
	height: 60px;
}
<canvas id="example"></canvas>

Upvotes: 1

Views: 2498

Answers (2)

Taki
Taki

Reputation: 17654

in addition to the previous answer, to get the color of the clicked pixel you need to get the x and y of the mouse :

var canvas = document.querySelector('#example')
var ctx = canvas.getContext('2d');

var gradient = ctx.createLinearGradient(0, 0, 300, -300);
gradient.addColorStop(0, 'rgba(179, 63, 19, 1)');
gradient.addColorStop(8 / 100, 'rgba(160, 79, 44, 1)');
gradient.addColorStop(42 / 100, 'rgba(33, 238, 20, 1)');
gradient.addColorStop(61 / 100, 'rgba(35, 182, 208, 1)');
gradient.addColorStop(76 / 100, 'rgba(0, 212, 255, 1)');
gradient.addColorStop(84 / 100, 'rgba(0, 212, 255, 1)');
gradient.addColorStop(96 / 100, 'rgba(0, 212, 255, 1)');
ctx.fillStyle = gradient;
ctx.fillRect(0, 0, 500, 60);

let pixel = ctx.getImageData(1, 1, 1, 1).data;

canvas.onclick = function(event) {
  var x = event.clientX;
  var y = event.clientY;
  var colors = ctx.getImageData(x, y, 1, 1).data;
  console.log(colors)
}
<canvas id="example" width="500" height="60"></canvas>

Upvotes: 1

M&#225;t&#233; Safranka
M&#225;t&#233; Safranka

Reputation: 4106

The linear gradient is a CSS property of the canvas, it's not drawn on the underlying bitmap you manipulate via the rendering context. That bitmap is blank by default and can only be modified programmatically.

What you need to do is draw the gradient in your JS code, then you can extract the color data. Unfortunately it's a lot more finicky than CSS, but it can be done. I threw together an example, just as a proof of concept.

Read up on createLinearGradient on MDN:

https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/createLinearGradient

var ctx = document.querySelector('#example').getContext('2d');

var gradient = ctx.createLinearGradient(0, 0, 50, 60);
gradient.addColorStop(0, 'rgba(179, 63, 19, 1)');
gradient.addColorStop(8/100, 'rgba(160, 79, 44, 1)');
gradient.addColorStop(42/100, 'rgba(33, 238, 20, 1)');
gradient.addColorStop(61/100, 'rgba(35, 182, 208, 1)');
gradient.addColorStop(76/100, 'rgba(0, 212, 255, 1)');
gradient.addColorStop(84/100, 'rgba(0, 212, 255, 1)');
gradient.addColorStop(96/100, 'rgba(0, 212, 255, 1)');
ctx.fillStyle = gradient;
ctx.fillRect(0, 0, 500, 60);

let pixel = ctx.getImageData(1, 1, 1, 1).data;
console.log(pixel);
<canvas id="example" width="500" height="60"></canvas>

Important: Note that the size of the canvas is set in the width and height attributes of the element, and not in CSS. This is because, as I said, there is a difference between the <canvas> element and its underlying bitmap. The attributes let you specify the size of the bitmap, and by default that's how big your canvas will be as well. If you modify the size of the canvas via CSS, the image you draw on the bitmap will be stretched to fit those dimensions, which is rarely what you want.

Upvotes: 2

Related Questions