Get pixel color from canvas, on mousemove
Here's a complete, self-contained example. First, use the following HTML:
<canvas id="example" width="200" height="60"></canvas>
<div id="status"></div>
Then put some squares on the canvas with random background colors:
var example = document.getElementById('example');
var context = example.getContext('2d');
context.fillStyle = randomColor();
context.fillRect(0, 0, 50, 50);
context.fillStyle = randomColor();
context.fillRect(55, 0, 50, 50);
context.fillStyle = randomColor();
context.fillRect(110, 0, 50, 50);
And print each color on mouseover:
$('#example').mousemove(function(e) {
var pos = findPos(this);
var x = e.pageX - pos.x;
var y = e.pageY - pos.y;
var coord = "x=" + x + ", y=" + y;
var c = this.getContext('2d');
var p = c.getImageData(x, y, 1, 1).data;
var hex = "#" + ("000000" + rgbToHex(p[0], p[1], p[2])).slice(-6);
$('#status').html(coord + "<br>" + hex);
});
The code above assumes the presence of jQuery and the following utility functions:
function findPos(obj) {
var curleft = 0, curtop = 0;
if (obj.offsetParent) {
do {
curleft += obj.offsetLeft;
curtop += obj.offsetTop;
} while (obj = obj.offsetParent);
return { x: curleft, y: curtop };
}
return undefined;
}
function rgbToHex(r, g, b) {
if (r > 255 || g > 255 || b > 255)
throw "Invalid color component";
return ((r << 16) | (g << 8) | b).toString(16);
}
function randomInt(max) {
return Math.floor(Math.random() * max);
}
function randomColor() {
return `rgb(${randomInt(256)}, ${randomInt(256)}, ${randomInt(256)})`
}
See it in action here:
- https://bl.ocks.org/wayneburkett/ca41a5245a9f48766b7bc881448f9203
// set up some sample squares with random colors
var example = document.getElementById('example');
var context = example.getContext('2d');
context.fillStyle = randomColor();
context.fillRect(0, 0, 50, 50);
context.fillStyle = randomColor();
context.fillRect(55, 0, 50, 50);
context.fillStyle = randomColor();
context.fillRect(110, 0, 50, 50);
$('#example').mousemove(function(e) {
var pos = findPos(this);
var x = e.pageX - pos.x;
var y = e.pageY - pos.y;
var coord = "x=" + x + ", y=" + y;
var c = this.getContext('2d');
var p = c.getImageData(x, y, 1, 1).data;
var hex = "#" + ("000000" + rgbToHex(p[0], p[1], p[2])).slice(-6);
$('#status').html(coord + "<br>" + hex);
});
function findPos(obj) {
var curleft = 0, curtop = 0;
if (obj.offsetParent) {
do {
curleft += obj.offsetLeft;
curtop += obj.offsetTop;
} while (obj = obj.offsetParent);
return { x: curleft, y: curtop };
}
return undefined;
}
function rgbToHex(r, g, b) {
if (r > 255 || g > 255 || b > 255)
throw "Invalid color component";
return ((r << 16) | (g << 8) | b).toString(16);
}
function randomInt(max) {
return Math.floor(Math.random() * max);
}
function randomColor() {
return `rgb(${randomInt(256)}, ${randomInt(256)}, ${randomInt(256)})`
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<canvas id="example" width="200" height="60"></canvas>
<div id="status"></div>
Get pixel color from resized canvas, on mouseover
You need to apply a scale factor inside the mouse handler method. The scale factor is the relationship between your canvas's bitmap (actual size) and the element size (CSS size).
For example:
// find scale:
var sx = example.width / parseInt(example.style.width, 10);
var sy = example.height / parseInt(example.style.height, 10);
// apply to x/y
x = (x * sx)|0; // scale and cut any fraction to get integer value
y = (y * sy)|0;
Updated fiddle
In addition the code need to have some boundary check of the coordinates so getImageData()
won't fail (not shown here).
get rgb values of pixel of image in fabric.js on mouse move
FabricJS does not have a native method for getting the pixel colors.
The workaround is to use native html5 canvas to fetch the pixel data:
Create your Fabric image objects. Be sure to specify
crossOrigin
as 'anonymous' otherwise the canvas will be tainted with a security violation and then the pixel data will be unavailable.Listen on Fabric's 'mouse:move' event. When it fires, get the current mouse position and use native canvas's
context.getImageData
to fetch that pixel's color array.
Good luck with your project!
Here's annotatede code and a Demo:
// create a Fabric.Canvas
var canvas = new fabric.Canvas("canvas");
// get a reference to <p id=results></p>
// (used to report pixel color under mouse)
var results = document.getElementById('results');
// get references to the html canvas element & its context
var canvasElement = document.getElementById('canvas');
var ctx = canvasElement.getContext("2d");
// create a test Fabric.Image
addFabricImage('https://cdn.pixabay.com/photo/2019/12/12/05/34/afro-4689826_1280.jpg');
// listen for mouse:move events
canvas.on('mouse:move', function(e) {
// get the current mouse position
var mouse = canvas.getPointer(e.e);
var x = parseInt(mouse.x);
var y = parseInt(mouse.y);
// get the color array for the pixel under the mouse
var px = ctx.getImageData(x, y, 1, 1).data;
// report that pixel data
results.innerHTML = 'At [' + x + ' / ' + y + ']: Red/Green/Blue/Alpha = [' + px[0] + ' / ' + px[1] + ' / ' + px[2] + ' / ' + px[3] + ']';
});
// create a Fabric.Image at x,y using a specified imgSrc
function addFabricImage(imgSrc, x, y) {
// create a new javascript Image object using imgSrc
var img = new Image();
// be sure to set crossOrigin or else
// cross-domain imgSrc's will taint the canvas
// and then we can't get the pixel data
// IMPORTANT!: the source domain must be properly configured
// to allow crossOrigin='anonymous'
img.crossOrigin = 'anonymous';
// when the Image object is fully loaded,
// use it to create a new fabric.Image object
img.onload = function() {
var fabImg = new fabric.Image(this, {
left: 30,
top: 30
});
canvas.add(fabImg);
}
// use imgSrc as the image source
img.src = imgSrc;
}
body {
background-color: ivory;
}
canvas {
border: 1px solid red;
}
<script src="http://cdnjs.cloudflare.com/ajax/libs/fabric.js/1.4.0/fabric.min.js"></script>
<p id="results">Move mouse over canvas</p>
<canvas id=canvas width=300 height=300></canvas>
How to shift pixel value to the next mousemove position in canvas?
I am very short on time ATM so code only.
Uses an offscreen canvas brush
to get a copy of the background canvas background
where the mouse was last frame. Then use a radial gradient to feather the brush using ctx.globalCompositeOperation = "destination-in"
. Then draw the updated brush at the next mouse position.
The main canvas is use just to display, the canvas being smeared is called background
You can put whatever content you want on that canvas (eg image) and it can be any size, and you can zoom, pan, rotate the background though you will have to convert the mouse coordinates to match the background coordinates
Click drag mouse to smear colours.
const ctx = canvas.getContext("2d");const background = createCanvas(canvas.width,canvas.height);const brushSize = 64;const bs = brushSize;const bsh = bs / 2;const smudgeAmount = 0.25; // values from 0 none to 1 full
// helpersconst doFor = (count, cb) => { var i = 0; while (i < count && cb(i++) !== true); }; // the ; after while loop is important don't removeconst randI = (min, max = min + (min = 0)) => (Math.random() * (max - min) + min) | 0;
// simple mouseconst mouse = {x : 0, y : 0, button : false}function mouseEvents(e){ mouse.x = e.pageX; mouse.y = e.pageY; mouse.button = e.type === "mousedown" ? true : e.type === "mouseup" ? false : mouse.button;}["down","up","move"].forEach(name => document.addEventListener("mouse"+name,mouseEvents));
// brush gradient for featherconst grad = ctx.createRadialGradient(bsh,bsh,0,bsh,bsh,bsh);grad.addColorStop(0,"black");grad.addColorStop(1,"rgba(0,0,0,0)");const brush = createCanvas(brushSize)
// creates an offscreen canvasfunction createCanvas(w,h = w){ var c = document.createElement("canvas"); c.width = w; c.height = h; c.ctx = c.getContext("2d"); return c;}
// get the brush from source ctx at x,yfunction brushFrom(ctx,x,y){ brush.ctx.globalCompositeOperation = "source-over"; brush.ctx.globalAlpha = 1; brush.ctx.drawImage(ctx.canvas,-(x - bsh),-(y - bsh)); brush.ctx.globalCompositeOperation = "destination-in"; brush.ctx.globalAlpha = 1; brush.ctx.fillStyle = grad; brush.ctx.fillRect(0,0,bs,bs);}
// short cut vars var w = canvas.width;var h = canvas.height;var cw = w / 2; // center var ch = h / 2;var globalTime;var lastX;var lastY;
// update background is size changedfunction createBackground(){ background.width = w; background.height = h; background.ctx.fillStyle = "white"; background.ctx.fillRect(0,0,w,h); doFor(64,()=>{ background.ctx.fillStyle = `rgb(${randI(255)},${randI(255)},${randI(255)}`; background.ctx.fillRect(randI(w),randI(h),randI(10,100),randI(10,100)); });}
// main update functionfunction update(timer){ globalTime = timer; ctx.setTransform(1,0,0,1,0,0); // reset transform ctx.globalAlpha = 1; // reset alpha if(w !== innerWidth || h !== innerHeight){ cw = (w = canvas.width = innerWidth) / 2; ch = (h = canvas.height = innerHeight) / 2; createBackground(); }else{ ctx.clearRect(0,0,w,h); } ctx.drawImage(background,0,0);
// if mouse down then do the smudge for all pixels between last mouse and mouse now if(mouse.button){ brush.ctx.globalAlpha = smudgeAmount; var dx = mouse.x - lastX; var dy = mouse.y - lastY; var dist = Math.sqrt(dx*dx+dy*dy); for(var i = 0;i < dist; i += 1){ var ni = i / dist; brushFrom(background.ctx,lastX + dx * ni,lastY + dy * ni); ni = (i+1) / dist; background.ctx.drawImage(brush,lastX + dx * ni - bsh,lastY + dy * ni - bsh); } }else{ brush.ctx.clearRect(0,0,bs,bs); /// clear brush if not used } lastX = mouse.x; lastY = mouse.y; requestAnimationFrame(update);}requestAnimationFrame(update);
canvas { position : absolute; top : 0px; left : 0px; }
<canvas id="canvas"></canvas>
Get Pixel Color from Canvas
The code seem to read the color from the marker rather than the color "behind" it.
The color needs to be read from the position and then set the marker or you will get the color of the marker instead in that position; and of course as the marker is black that color will be returned each time.
Related Topics
Three.Js Ray Intersect Fails by Adding Div
Best Practice: Access Form Elements by HTML Id or Name Attribute
Selecting All Text in HTML Text Input When Clicked
Including Both Href and Onclick to HTML ≪A≫ Tag
"Uncaught Typeerror: Illegal Invocation" in Chrome
Input Placeholders For Internet Explorer
How to Hide the Cursor in a Webpage Using CSS or JavaScript
How to Insert a Row in an HTML Table Body in JavaScript
What Is Offsetheight, Clientheight, Scrollheight
Detecting If a Browser Is Using Private Browsing Mode
(Change) VS (Ngmodelchange) in Angular
When Is Nodelist Live and When Is It Static
Retrieving the Text of the Selected ≪Option≫ in ≪Select≫ Element
How Can Get the Text of a Div Tag Using Only JavaScript (No Jquery)
After Submitting a Post Form Open a New Window Showing the Result