Changing image on click with canvas - javascript

I have been struggling with a problem for some time now. I am trying to create a image onto a canvas, and when the user clicks on a div outside the canvas the background of the canvas should be changed to that image. This works, but the problem is that when I click a image nothing happens, if I click on a different image the image I clicked before gets loaded. This is making me so frustrated, and I really could need a set of new eyes on this.
The code that generates the image is very complex, it is a angular app and it depends on many directives to do some heavy lifting. The code that is generating the image is below:
var canvas = document.getElementById("image");
var context = canvas.getContext("2d");
// Setup the margin box
context.fillStyle = '#000000';
context.globalAlpha = 0;
context.fillRect(53, 53, 319, 107);
context.globalAlpha = 1;
$scope.resultTempImage = false;
$scope.generate = {
price: 1
};
$scope.color = "#ffffff";
$scope.product = {
bg: 'img/bg/bg-green-pattern.png',
icon: '',
color: "#000000",
font: 'Acme',
text1: "",
text2: "",
text3: "",
quantity: 120,
price: {
id: 1,
value: 17900
}
};
// Generates the first image
var firstLoadBg = false;
var bgImage = new Image();
var loadBg = function(image, callback) {
bgImage.src = '';
bgImage.onload = function() {
firstLoadBg = true;
callback(this);
};
bgImage.src = image;
}
var iconImage = new Image();
iconImage.onload = function() {
console.log('icon image loaded');
context.drawImage(this, 53, 53);
};
$scope.generateImage = function(product) {
/**
* Generates the image in the canvas
*/
// Generate a bg image
loadBg(product.bg, function(image) {
if (firstLoadBg == true) {
context.drawImage(image, 0, 0);
console.log('bg drawn');
}
if (product.icon) {
iconImage.src = '';
iconImage.src = product.icon;
}
// Add lines to the lines array
var lines = [];
if (product.text1 != "") {
lines.push(product.text1);
}
if (product.text2 != "") {
lines.push(product.text2);
}
if (product.text3 != "") {
lines.push(product.text3);
}
calculatePaint(lines, product.icon, product.font, function(Paint) {
/**
* Response from the Paint function, holds the position of the generated text.
*/
context.font = Paint.textSize;
context.fillStyle = product.color;
context.textAlign = "center";
context.textBaseline = "middle";
// Draw text lines
var y = Paint.bleedHeight;
angular.forEach(lines, function(value, key) {
if (lines.length == 2) {
context.textBaseline = "top";
if (key == 0) {
y = y - Paint.topPadding;
}
if (key == 1) {
y = y + Paint.padding;
}
}
if (lines.length == 3) {
context.textBaseline = "top";
if (key == 0) {
y = y - Paint.topPadding;
}
if (key == 1) {
y = y + Paint.padding;
}
if (key == 2) {
y = y + Paint.padding;
}
}
context.fillText(lines[key], Paint.bleedWidth, y, Paint.maxWidth);
});
var dataURL = canvas.toDataURL();
$scope.resultTempImage = dataURL;
console.log('done painting');
});
});
}
function calculatePaint(lines, icon, font, callback) {
/**
* #function for fitting text to the margin box
* #param line1 String
* #param line2 String
* #param line3 String
* #return obj
*/
// Margin of icon
var iconMargin = 90;
// Initial fontSize
var fontSize = 80;
// Bleed
var marginWidth = 53;
var marginHeight = 53;
// Inner box width
var w = 319;
var iconw = 319 - 100;
// Inner box height
var h = 107;
var Paint = {
bleedWidth: marginWidth + (w / 2),
bleedHeight: marginHeight + (h / 2),
maxWidth: w,
padding: 2,
topPadding: 53
};
if (icon) {
Paint.bleedWidth = marginWidth + 100 + (iconw / 2);
Paint.textSize = fontSize + 'px ' + font;
Paint.maxWidth = iconw;
fontSize = 60;
}
// Check lines array
if (lines.length == 1) {
// only one line is present
Paint.textSize = fontSize + 'px ' + font;
}
if (lines.length == 2) {
Paint.textSize = (Paint.bleedHeight / 2) - 8 + 'px ' + font;
Paint.padding = Paint.padding + (Paint.bleedHeight / 2) - 2;
}
if (lines.length == 3) {
Paint.textSize = (Paint.bleedHeight / 3) - 8 + 'px ' + font;
Paint.padding = Paint.padding + (Paint.bleedHeight / 3) - 2;
}
callback(Paint);
}

I found a solution to my own problem. What i did was preload all the images when the page load. Like this:
Data.get( 'assets/images' ).then( function( res ) {
if( res.success == true ) {
$scope.items = res.message;
angular.forEach( res.message, function( item, key ) {
preload( item.data, function(image) {
item.image = image;
} )
} );
}
} );
var preload = function( src, callback ) {
var image = new Image();
image.onload = function() {
callback( this );
}
image.src = src;
}
This preloads all my images and when im ready to draw my canvas I have all the image obj ready to go.

Related

How to position image on canvas same as overlaped div of same dimension

I have two div of same dimension which overlap each other using z-index.
Ist div contain image and 2nd div contain a canvas
I am trying to draw image on canvas same place as Ist div. I am using hammerjs library to zoomin/out , reposition and rotate image. I found these code somewhere else
function getMeta(url){
img = new Image();
var remoteImage = {}
img.src = url;
remoteImage.width = img.naturalWidth
remoteImage.height = img.naturalHeight
remoteImage.src = url;
return remoteImage
}
var urlImage = getMeta('https://www.penghu-nsa.gov.tw/FileDownload/Album/Big/20161012162551758864338.jpg')
var text = document.querySelector("#text");
var oImg=document.querySelector("#img_scan");
oImg.style['transition-duration'] = '100ms';
var timeInMs = 0;
var preAngle = 0;
var rotateAngle = 0;
var preRotation = 0;
var originalSize = {
width : oImg.offsetWidth,
height : oImg.offsetHeight,
}
var current = {
x : 0,
y : 0,
z : 1,
angle : 0,
width: originalSize.width,
height: originalSize.height,
}
var last = {
x : 0,
y : 0,
z : 1,
}
var oImgRec = oImg.getBoundingClientRect();
var cx = oImgRec.left + oImgRec.width * 0.5;
var cy = oImgRec.top + oImgRec.height * 0.5;
var imageCenter = {
x:cx,
y:cy
}
var pinchImageCenter = {}
var deltaIssue = { x: 0, y: 0 };
var pinchStart = { x: undefined, y: undefined, isPanend:false}
var panendDeltaFix = {x:0,y:0,isPanend:false}
var pinchZoomOrigin = undefined;
var lastEvent = ''
var hammer = new Hammer(oImg);
hammer.get('pinch').set({enable: true});
hammer.get('pan').set({direction: Hammer.DIRECTION_ALL}).recognizeWith(hammer.get('pinch'));
hammer.on("pinchstart", function(e) {
last.x = current.x;
last.y = current.y;
pinchStart.x = e.center.x;
pinchStart.y = e.center.y;
pinchImageCenter = {
x: imageCenter.x + last.x,
y: imageCenter.y + last.y
}
lastEvent = 'pinchstart';
});
hammer.on("pinchmove", function(e) {
if(preAngle == 0){
preAngle = Math.round(e.rotation);
preRotation = Math.round(e.rotation);
}else{
if(Math.abs(Math.round(e.rotation)-preRotation)>=300){
if(e.rotation > 0){
preAngle+=360;
}else if(e.rotation < 0){
preAngle-=360;
}
}
current.angle = rotateAngle + (Math.round(e.rotation)-preAngle);
preRotation = Math.round(e.rotation);
}
var newScale = (last.z * e.scale) >= 0.1 ? (last.z * e.scale) : 0.1;
var d = scaleCal(e.center, pinchImageCenter, last.z, newScale)
current.x = d.x + last.x;
current.y = d.y + last.y;
current.z = d.z + last.z;
update();
lastEvent = 'pinchmove';
});
hammer.on("pinchend", function(e) {
last.x = current.x;
last.y = current.y;
last.z = current.z;
rotateAngle = current.angle;
preAngle = 0;
lastEvent = 'pinchend';
});
hammer.on("panmove", function(e) {
var panDelta = {
x:e.deltaX,
y:e.deltaY
}
if (lastEvent !== 'panmove') {
deltaIssue = {
x: panDelta.x,
y: panDelta.y
}
}
current.x = (last.x+panDelta.x-deltaIssue.x);
current.y = (last.y+panDelta.y-deltaIssue.y);
lastEvent = 'panmove'
update();
});
hammer.on("panend", function(e) {
last.x = current.x;
last.y = current.y;
lastEvent = 'panend';
});
hammer.on('tap', function(e) {
if((Date.now()-timeInMs)<300){
if(last.z > 1){
last.z = 1;
current.z = 1;
update();
}else if(last.z <= 1){
last.z = 2;
current.z = 2;
update();
}
}
timeInMs = Date.now();
lastEvent = 'tap';
});
function scaleCal(eCenter, originCenter, currentScale, newScale) {
var zoomDistance = newScale - currentScale;
var x = (originCenter.x - eCenter.x)*(zoomDistance)/currentScale;
var y = (originCenter.y - eCenter.y)*(zoomDistance)/currentScale;
var output = {
x: x,
y: y,
z: zoomDistance
}
return output
}
function update() {
current.height = originalSize.height * current.z;
current.width = originalSize.width * current.z;
if(current.z < 0.1){
current.z = 0.1;
}
oImg.style.transform = " translate3d(" + current.x + "px, " + current.y + "px, 0)rotate("+current.angle+"deg)scale("+current.z+")"
}
So by above code user can zoomin/zoom out , rotate image . After they set image in their desired position i am putting that image on canvas so i can use dataurl method to save image later.
I tried below code to draw image on canvas same place as div ,same dimension and with same angle but sadly image is not getting exactly same positioned as div
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
$("#btn").click(copyoncanvas);
function copyoncanvas(){
var bound=objimg.getBoundingClientRect();
var objimg=new Image();
objimg.src="https://www.penghu-nsa.gov.tw/FileDownload/Album/Big/20161012162551758864338.jpg";
ctx.drawImage(objimg,bound.left,bound.top,current.width,current.height);
drawRotated(current.angle,bound.left,bound.top);
}
function drawRotated(degrees,l,t){
const objimg=document.getElementById("img_scan");
ctx.clearRect(0,0,canvas.width,canvas.height);
ctx.save();
var x=canvas.width/2;
var y=canvas.height/2;
ctx.translate(x,y);
ctx.rotate(degrees * Math.PI/180);
ctx.drawImage(objimg,-l,-t,current.width,current.height);
ctx.restore();
}
I think my problem is with drawrotated function because it work fine without using it but i want to rotate image on canvas too
HTML
<div id="container">
<div class="box"><canvas id="canvas"></canvas></div>
<div id="imgcont">
<img src="https://www.penghu-nsa.gov.tw/FileDownload/Album/Big/20161012162551758864338.jpg" id="img_scan" class="img-custom-img2"/>
</div>
</div>
<button id="btn">Copy on canvas</button>
CSS
#container{
position:relative;margin: 0px;
padding:0px;background:#ff0;
top:0px; overflow:hidden;
width:300px;
border:1px solid #000; height:250}
#img_scan,.box{
width:100%; height:100%;
position: absolute;
top: 0;
left: 0; margin:0; padding:0px
}
.box{z-index:98;height:250}
#canvas{width:100%;margin:0;
padding:0;
width:300;height:250}
#img_scan{width:300px;height:250px}
#imgcont{width:100%;height:250px;z-index:99}

Javascript - How to refactor a code to look cleaner

I have a function that looks kind of primitive, I am wondering whether anyone has any solution on how to improve the looks of this function. Can I change this primitive loop if()... if()... to something that looks cleaner and nicer?
function drawPlayers () {
if (players[0].nick != null) {
let player1Img = new Image(SQUARE, SQUARE)
player1Img.onload = function() {
ctx.drawImage(player1Img, LEFT_LINE + players[0].x * SQUARE, UPPER_LINE + players[0].y * SQUARE, this.width, this.height)
}
player1Img.src = "sprites/player1.png"
}
if (players[1].nick != null) {
let player2Img = new Image(SQUARE, SQUARE)
player2Img.onload = function() {
ctx.drawImage(player2Img, LEFT_LINE + players[1].x * SQUARE, UPPER_LINE + players[1].y * SQUARE, this.width, this.height)
}
player2Img.src = "sprites/player1.png"
}
if (players[2].nick != null) {
let player3Img = new Image(SQUARE, SQUARE)
player3Img.onload = function() {
ctx.drawImage(player3Img, LEFT_LINE + players[2].x * SQUARE, UPPER_LINE + players[2].y * SQUARE, this.width, this.height)
}
player3Img.src = "sprites/player1.png"
}
if (players[3].nick != null) {
let player4Img = new Image(SQUARE, SQUARE)
player4Img.onload = function() {
ctx.drawImage(player4Img, LEFT_LINE + players[3].x * SQUARE, UPPER_LINE + players[3].y * SQUARE, this.width, this.height)
}
player4Img.src = "sprites/player1.png"
}
}
Like this
players.forEach(player => {
if (player.nick != null) {
let img = new Image(SQUARE, SQUARE)
img.onload = function() {
ctx.drawImage(img, LEFT_LINE + player.x * SQUARE, UPPER_LINE + player.y * SQUARE, this.width, this.height)
}
img.src = "sprites/player1.png"; // or `sprites/${player.image}`;
}
});
If you have another array for image names you can add an index to the forEach :
players.forEach((player,i) => {
if (player.nick != null) {
let img = new Image(SQUARE, SQUARE)
img.onload = function() {
ctx.drawImage(img, LEFT_LINE + player.x * SQUARE, UPPER_LINE + player.y * SQUARE, this.width, this.height)
}
img.src = `sprites/${images[i]}`;
}
});
const SQUARE = 100;
const images = [
"https://via.placeholder.com/100x100?text=Image1",
"https://via.placeholder.com/100x100?text=Image2",
"https://via.placeholder.com/100x100?text=Image3"
];
const players = [
{ nick: "Fred", x: 10, y: 20 },
{ nick: "Joe", x: 20, y: 40 },
{ nick: "Sam", x: 30, y: 50 }
];
players.forEach((player, i) => {
if (player.nick != null) {
let img = new Image(SQUARE, SQUARE)
img.onload = function() {
console.log(i,player.nick,`ctx.drawImage(img, LEFT_LINE ${player.x} * SQUARE, UPPER_LINE + ${player.y} * SQUARE, ${this.width}, ${this.height})`)
}
img.src = `${images[i]}`;
}
});
You could do a for loop
function drawPlayers() {
for (let i = 0; i < players.length; i++) {
if (players[i].nick != null) {
let playerImg = new Image(SQUARE, SQUARE)
playerImg.onload = function() {
ctx.drawImage(
playerImg,
LEFT_LINE + players[i].x * SQUARE,
UPPER_LINE + players[i].y * SQUARE,
this.width,
this.height
)
}
// if the image is fixed
playerImg.src = 'sprites/player1.png'
// else
// playerImg.src = `sprites/player${i + 1}.png`
}
}
}
function drawPlayers() {
players.forEach((player, idx) => {
if (player.nick != null) {
// uncomment following comment block and delete this comment
/*
var img = new Image(SQUARE, SQUARE)
img.onload = () => {
ctx.drawImage(img, LEFT_LINE + player.x * SQUARE, UPPER_LINE + player.y * SQUARE, this.width, this.height)
};
img.src = "sprites/player"+(idx+1)+".png";
*/
console.log(idx, player.nick, "sprites/player"+(idx+1)+".png");
}
});
}
var players=[{nick:"abe"},{},{nick:"chuck"},{nick:"dick"}];
drawPlayers();
Another variant:
for(let p of players){
if(p.nick){
let playerImg = new Image(SQUARE,SQUARE);
playerImg.onload = function() {
ctx.drawImage(player1Img, LEFT_LINE + p.x*SQUARE, UPPER_LINE + p.y*SQUARE, this.width, this.height)
}
playerImg.src = "sprites/player1.png"
}
}
Another feature, I learned recently:
for(let p of players){
if(!p.nick) continue;
let playerImg = new Image(SQUARE,SQUARE);
playerImg.onload = function() {
ctx.drawImage(player1Img, LEFT_LINE + p.x*SQUARE, UPPER_LINE + p.y*SQUARE, this.width, this.height)
}
playerImg.src = "sprites/player1.png"
}

how to fill particles inside rectangle?

I'm looking to draw a rectangle basically text but just for clearing insight I'm working it with rectangle with small particles inside rectangle the basic I idea I got from https://yalantis.com/ but in my attempt I'm stuck here with solid filled rectangle with a color I have specified for particles. Please help me.. :)
Thanks here is my code:
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Off Screen Canvas</title>
<script>
function createOffscreenCanvas() {
var offScreenCanvas = document.createElement('canvas');
offScreenCanvas.width = '1360';
offScreenCanvas.height = '400';
var context = offScreenCanvas.getContext("2d");
var W=200;
var H=200;
particleCount = 200;
particles = []; //this is an array which will hold our particles Object/Class
function Particle() {
this.x = Math.random() * W;
this.y = Math.random() * H;
this.direction ={"x": -1 + Math.random()*2, "y": -1 + Math.random()*2};
this.vx = 2 * Math.random() + 4 ;
this.vy = 2 * Math.random() + 4;
this.radius = .9 * Math.random() + 1;
this.move = function(){
this.x += this.vx * this.direction.x;
this.y += this.vy * this.direction.y;
};
this.changeDirection = function(axis){
this.direction[axis] *= -1;
};
this.draw = function() {
context.beginPath();
context.fillStyle = "#0097a7";
context.arc(this.x, this.y, this.radius, 0, Math.PI * 2, false);
context.fill();
};
this.boundaryCheck = function(){
if(this.x >= W){
this.x = W;
this.changeDirection("x");
}
else if(this.x <= 0){
this.x = 0;
this.changeDirection("x");
}
if(this.y >= H){
this.y = H;
this.changeDirection("y");
}
else if(this.y <= 0){
this.y = 0;
this.changeDirection("y");
}
};
}
function createParticles(){
for (var i = particleCount-1; i >= 0; i--) {
p = new Particle();
particles.push(p);
}
}// end createParticles
function drawParticles(){
for (var i = particleCount-1; i >= 0; i--){
p = particles[i];
p.draw();
}
} //end drawParticles
function updateParticles(){
for(var i = particles.length - 1; i >=0; i--){
p = particles[i];
p.move();
p.boundaryCheck();
}
}//end updateParticle
createParticles();
var part=drawParticles();
context.fillStyle=part;
context.fillRect(W-190, H-190, W, H);
context.fill();
return offScreenCanvas;
}
function copyToOnScreen(offScreenCanvas) {
var onScreenContext=document.getElementById('onScreen').getContext('2d');
var offScreenContext = offScreenCanvas.getContext('2d');
var image=offScreenContext.getImageData(10,10,200,200);
onScreenContext.putImageData(image,offScreenCanvas.width/2,offScreenCanvas.height/4);
}
function main() {
copyToOnScreen(createOffscreenCanvas());
}
</script>
<style>
canvas {
border: 1px solid red;
}
</style>
</head>
<body onload="main()">
<canvas id="onScreen" width="1360" height="400"></canvas>
</body>
</html>
I see you have not found what you are looking for yet. Below is something quick to get you on your way. There is a whole range of stuff being used from canvas,mouse,particles, etc most of which is without comments. There is no load balancing or compliance testing and because it uses babel to be compatible with IE11 I have no clue how it runs on those browsers.
I will add to this answer some other time but for now I am a little over it.
const textList = ["1","2","3","Testing","text","to","particles"];
var textPos = 0;
function createParticles(text){
createTextMap(
text, // text to display
40, // font size
"Arial", // font
{ // style fot rendering font
fillStyle : "#6AF",
strokeStyle : "#F80",
lineWidth : 2,
lineJoin : "round",
},{ // bounding box to find a best fit for
top : 0,
left : 0,
width : canvas.width,
height : canvas.height,
}
)
}
// This function starts the animations
var started = false;
function startIt(){
started = true;
const next = ()=>{
var text = textList[(textPos++ ) % textList.length];
particles.mouseFX.dist = canvas.height / 8;
createParticles(text);
setTimeout(moveOut,text.length * 100 + 3000);
}
const moveOut = ()=>{
particles.moveOut();
setTimeout(next,2000);
}
setTimeout(next,0);
}
function setStyle(ctx,style){
Object.keys(style).forEach(key => ctx[key] = style[key]);
}
// the following function create the particles from text using a canvas
// the canvas used is dsplayed on the main canvas top left fro referance.
var tCan = createImage(100, 100); // canvas used to draw text
function createTextMap(text,size,font,style,fit){
// function to conver to colour hex value
const hex = (v)=> (v < 16 ? "0" : "") + v.toString(16);
// set up font so we can find the size.
tCan.ctx.font = size + "px " + font;
// get size of text
var width = Math.ceil(tCan.ctx.measureText(text).width + size);
// resize the canvas to fit the text
tCan.width = width;
tCan.height = Math.ceil(size *1.2);
// c is alias for context
var c = tCan.ctx;
// set up font
c.font = size + "px " + font;
c.textAlign = "center";
c.textBaseline = "middle";
// set style
setStyle(c,style);
// only do stroke and fill if they are set in styles object
if(style.strokeStyle){
c.strokeText(text, width / 2, tCan.height / 2);
}
if(style.fillStyle){
c.fillText(text, width / 2, tCan.height/ 2);
}
// prep the particles
particles.empty();
// get the pixel data
var data = c.getImageData(0,0,width,tCan.height).data;
var x,y,ind,rgb,a;
// find pixels with alpha > 128
for(y = 0; y < tCan.height; y += 1){
for(x = 0; x < width; x += 1){
ind = (y * width + x) << 2; // << 2 is equiv to * 4
if(data[ind + 3] > 128){ // is alpha above half
rgb = `#${hex(data[ind ++])}${hex(data[ind ++])}${hex(data[ind ++])}`;
// add the particle
particles.add(Vec(x, y), Vec(x, y), rgb);
}
}
}
// scale the particles to fit bounding box
var scale = Math.min(fit.width / width, fit.height / tCan.height);
particles.each(p=>{
p.home.x = ((fit.left + fit.width) / 2) + (p.home.x - (width / 2)) * scale;
p.home.y = ((fit.top + fit.height) / 2) + (p.home.y - (tCan.height / 2)) * scale;
})
.findCenter() // get center used to move particles on and off of screen
.moveOffscreen() // moves particles off the screen
.moveIn(); // set the particles to move into view.
}
// vector object a quick copy from other code.
function Vec(x,y){ // because I dont like typing in new
return new _Vec(x,y);
}
function _Vec(x = 0,y = 0){
this.x = x;
this.y = y;
return this;
}
_Vec.prototype = {
setAs(vec){
this.x = vec.x;
this.y = vec.y;
},
toString(){
return `vec : { x : ${this.x}, y : ${this.y} );`
}
}
// basic particle
const particle = {
pos : null,
delta : null,
home : null,
col : "black",
}
// array of particles
const particles = {
items : [], // actual array of particles
mouseFX : { // mouse FX
power : 20,
dist : 100,
curve : 3, // polynomial power
on : true,
},
fx : {
speed : 0.4,
drag : 0.15,
size : 4,
jiggle : 8,
},
// direction 1 move in -1 move out
direction : 1,
moveOut(){this.direction = -1; return this},
moveIn(){this.direction = 1; return this},
length : 0, // Dont touch this from outside particles.
each(callback){ // custom iteration
for(var i = 0; i < this.length; i++){
callback(this.items[i],i);
}
return this;
},
empty(){ // empty but dont dereference
this.length = 0;
return this;
},
deRef(){ // call to clear memory
this.items.length = 0;
this.length = 0;
},
add(pos,home,col){ // adds a particle
var p;
if(this.length < this.items.length){
p = this.items[this.length++];
// p.pos.setAs(pos);
p.home.setAs(home);
p.delta.x = 0;
p.delta.y = 0;
p.col = col;
}else{
this.items.push(
Object.assign(
{},
particle,
{
pos,
home,
col,
delta : Vec()
}
)
);
this.length = this.items.length
}
return this;
},
draw(){ // draws all
var p, size, sizeh;
sizeh = (size = this.fx.size) / 2;
for(var i = 0; i < this.length; i++){
p = this.items[i];
ctx.fillStyle = p.col;
ctx.fillRect(p.pos.x - sizeh, p.pos.y - sizeh, size, size);
}
},
update(){ // update all particles
var p,x,y,d;
var mP = this.mouseFX.power;
var mD = this.mouseFX.dist;
var mC = this.mouseFX.curve;
var fxJ = this.fx.jiggle;
var fxD = this.fx.drag;
var fxS = this.fx.speed;
for(var i = 0; i < this.length; i++){
p = this.items[i];
p.delta.x += (p.home.x - p.pos.x ) * fxS + (Math.random() - 0.5) * fxJ;
p.delta.y += (p.home.y - p.pos.y ) * fxS + (Math.random() - 0.5) * fxJ;
p.delta.x *= fxD;
p.delta.y *= fxD;
p.pos.x += p.delta.x * this.direction;
p.pos.y += p.delta.y * this.direction;
if(this.mouseFX.on){
x = p.pos.x - mouse.x;
y = p.pos.y - mouse.y;
d = Math.sqrt(x * x + y * y);
if(d < mD){
x /= d;
y /= d;
d /= mD;
d = (1-Math.pow(d,mC)) * mP;
p.pos.x += x * d;
p.pos.y += y * d;
}
}
}
return this;
},
findCenter(){ // find the center of particles maybe could do without
var x,y;
y = x = 0;
this.each(p => {
x += p.home.x;
y += p.home.y;
});
this.center = Vec(x / this.length, y / this.length);
return this;
},
moveOffscreen(){ // move start pos offscreen
var dist,x,y;
dist = Math.sqrt(this.center.x * this.center.x + this.center.y * this.center.y);
this.each(p => {
var d;
x = p.home.x - this.center.x;
y = p.home.y - this.center.y;
d = Math.max(0.0001,Math.sqrt(x * x + y * y)); // max to make sure no zeros
p.pos.x = p.home.x + (x / d) * dist;
p.pos.y = p.home.y + (y / d) * dist;
});
return this;
},
}
function onResize(){ // called from boilerplate
if(!started){
startIt();
}
}
/** SimpleFullCanvasMouse.js begin **/
// the following globals are available
// w, h, cw, ch, width height centerWidth centerHeight of canvas
// canvas, ctx, mouse, globalTime
//MAIN animation loop
function display() { // call once per frame
ctx.setTransform(1, 0, 0, 1, 0, 0); // reset transform
ctx.globalAlpha = 1; // reset alpha
ctx.clearRect(0, 0, w, h);
if(tCan){
// ctx.drawImage(tCan,0,0);
}
particles.update();
particles.draw();
}
/******************************************************************************
The code from here down is generic full page mouse and canvas boiler plate
code. As I do many examples which all require the same mouse and canvas
functionality I have created this code to keep a consistent interface. The
Code may or may not be part of the answer.
This code may or may not have ES6 only sections so will require a transpiler
such as babel.js to run on legacy browsers.
*****************************************************************************/
// V2.0 ES6 version for Stackoverflow and Groover QuickRun
var w, h, cw, ch, canvas, ctx, mouse, globalTime = 0;
// You can declare onResize (Note the capital R) as a callback that is also
// called once at start up. Warning on first call canvas may not be at full
// size.
;(function(){
const RESIZE_DEBOUNCE_TIME = 100;
var resizeTimeoutHandle;
var firstRun = true;
function createCanvas () {
var c,cs;
cs = (c = document.createElement("canvas")).style;
cs.position = "absolute";
cs.top = cs.left = "0px";
cs.zIndex = 1000;
document.body.appendChild(c);
return c;
}
function resizeCanvas () {
if (canvas === undefined) { canvas = createCanvas() }
canvas.width = innerWidth;
canvas.height = innerHeight;
ctx = canvas.getContext("2d");
if (typeof setGlobals === "function") { setGlobals() }
if (typeof onResize === "function") {
clearTimeout(resizeTimeoutHandle);
if (firstRun) { onResize() }
else { resizeTimeoutHandle = setTimeout(onResize, RESIZE_DEBOUNCE_TIME) }
firstRun = false;
}
}
function setGlobals () {
cw = (w = canvas.width) / 2;
ch = (h = canvas.height) / 2;
}
mouse = (function () {
function preventDefault(e) { e.preventDefault() }
var m; // alias for mouse
var mouse = {
x : 0, y : 0, w : 0, // mouse position and wheel
alt : false, shift : false, ctrl : false, // mouse modifiers
buttonRaw : 0,
over : false, // true if mouse over the element
buttonOnMasks : [0b1, 0b10, 0b100], // mouse button on masks
buttonOffMasks : [0b110, 0b101, 0b011], // mouse button off masks
active : false,
bounds : null,
eventNames : "mousemove,mousedown,mouseup,mouseout,mouseover,mousewheel,DOMMouseScroll".split(","),
event(e) {
var t = e.type;
m.bounds = m.element.getBoundingClientRect();
m.x = e.pageX - m.bounds.left - scrollX;
m.y = e.pageY - m.bounds.top - scrollY;
m.alt = e.altKey;
m.shift = e.shiftKey;
m.ctrl = e.ctrlKey;
if (t === "mousedown") { m.buttonRaw |= m.buttonOnMasks[e.which - 1] }
else if (t === "mouseup") { m.buttonRaw &= m.buttonOffMasks[e.which - 1] }
else if (t === "mouseout") { m.over = false }
else if (t === "mouseover") { m.over = true }
else if (t === "mousewheel") {m.w = e.wheelDelta }
else if (t === "DOMMouseScroll") { m.w = -e.detail }
if (m.callbacks) { m.callbacks.forEach(c => c(e)) }
if ((m.buttonRaw & 2) && m.crashRecover !== null) {
if (typeof m.crashRecover === "function") { setTimeout(m.crashRecover, 0) }
}
e.preventDefault();
},
addCallback(callback) {
if (typeof callback === "function") {
if (m.callbacks === undefined) { m.callbacks = [callback] }
else { m.callbacks.push(callback) }
}
},
start(element) {
if (m.element !== undefined) { m.remove() }
m.element = element === undefined ? document : element;
m.eventNames.forEach(name => document.addEventListener(name, mouse.event) );
document.addEventListener("contextmenu", preventDefault, false);
m.active = true;
},
remove() {
if (m.element !== undefined) {
m.eventNames.forEach(name => document.removeEventListener(name, mouse.event) );
document.removeEventListener("contextmenu", preventDefault);
m.element = m.callbacks = undefined;
m.active = false;
}
}
}
m = mouse;
return mouse;
})();
function done() { // Clean up. Used where the IDE is on the same page.
window.removeEventListener("resize", resizeCanvas)
mouse.remove();
document.body.removeChild(canvas);
canvas = ctx = mouse = undefined;
}
function update(timer) { // Main update loop
if(ctx === undefined){ return }
globalTime = timer;
display(); // call demo code
requestAnimationFrame(update);
}
setTimeout(function(){
canvas = createCanvas();
mouse.start(canvas, true);
resizeCanvas();
if(typeof Groover !== "undefined" && Groover.ide){ mouse.crashRecover = done }; // Requires Ace.js and GrooverDev.js. Prevents
window.addEventListener("resize", resizeCanvas);
requestAnimationFrame(update);
},0);
})();
/** SimpleFullCanvasMouse.js end **/
/** CreateImage.js begin **/
// creates a blank image with 2d context
function createImage(w,h){var i=document.createElement("canvas");i.width=w;i.height=h;i.ctx=i.getContext("2d");return i;}
/** CreateImage.js end **/
canvas {
background : black;
}
well after all the attempts like hell I finally got my answer thanks to moƔois answer to my post using particle slider. here is the code. Thanks everyone for your help :)

Limiting a rotated object within boundary with snap SVG

I've managed to setup a FIDDLE where I gave an example how to bind an element within svg boundary. It's working fine when dragging a normal element(without rotation). But when I apply this to a rotated object, the problem arises:
var s = Snap("#svgout");
var ROOM_WIDTH = 400;
var ROOM_HEIGHT = 200;
var SVG_BOUNDARY = s.rect(0, 0, ROOM_WIDTH, ROOM_HEIGHT);
SVG_BOUNDARY.attr({
"stroke": "#FF0000",
"fill": "#FFFFFF",
id: "room-svg-boundary"
});
var BEFORE_ROTATION_GETBBOX = [];
s.attr({
viewBox: "0 0 " + ROOM_WIDTH + " " + ROOM_HEIGHT
});
(function() {
Snap.plugin(function(Snap, Element, Paper, global) {
Element.prototype.limitDragging = function(params) {
this.data('minx', params.minx);
this.data('miny', params.miny);
this.data('maxx', params.maxx);
this.data('maxy', params.maxy);
this.data('x', params.x);
this.data('y', params.y);
this.data('ibb', this.getBBox());
this.data('ot', this.transform().local);
this.drag(limitMoveDrag, limitStartDrag);
return this;
};
function limitMoveDrag(dx, dy, posx, posy, ev) {
var tdx, tdy;
var sInvMatrix = this.transform().globalMatrix.invert();
sInvMatrix.e = sInvMatrix.f = 0;
tdx = sInvMatrix.x(dx, dy);
tdy = sInvMatrix.y(dx, dy);
this.data('x', +this.data('ox') + tdx);
this.data('y', +this.data('oy') + tdy);
if (this.data('x') > this.data('maxx') - this.data('ibb').width) {
this.data('x', this.data('maxx') - this.data('ibb').width)
};
if (this.data('y') > this.data('maxy') - this.data('ibb').height) {
this.data('y', this.data('maxy') - this.data('ibb').height)
};
if (this.data('x') < this.data('minx')) {
this.data('x', this.data('minx'))
};
if (this.data('y') < this.data('miny')) {
this.data('y', this.data('miny'))
};
this.transform(this.data('ot') + "t" + [this.data('x'), this.data('y')]);
};
function limitStartDrag(x, y, ev) {
this.data('ox', this.data('x'));
this.data('oy', this.data('y'));
};
});
})();
var SETUP_DRAG_MOVEMENT = function(ELEM, disable) {
if (disable != undefined && disable == true) {
ELEM.undrag();
} else {
var RECT_BOUNDARY = s.getBBox();
var ELEM_BOX = ELEM.getBBox();
var min_x = -ELEM_BOX.cx + ELEM_BOX.width / 2;
var max_x = RECT_BOUNDARY.x2 - ELEM_BOX.x2 + ELEM_BOX.width;
var min_y = -ELEM_BOX.cy + ELEM_BOX.height / 2;
var max_y = RECT_BOUNDARY.y2 - ELEM_BOX.y2 + ELEM_BOX.height;
ELEM.limitDragging({
x: 0,
y: 0,
minx: min_x,
miny: min_y,
maxx: max_x,
maxy: max_y
});
}
}
var SETUP_DRAG_MOVEMENT_ROTATED = function(ELEM, disable) {
if (disable != undefined && disable == true) {
BEFORE_ROTATION_GETBBOX[ELEM.node.id] = ELEM.getBBox();
ELEM.undrag();
} else {
var RECT_BOUNDARY = s.getBBox();
console.log(RECT_BOUNDARY);
var ELEM_BOX = (BEFORE_ROTATION_GETBBOX[ELEM.node.id] != undefined && typeof BEFORE_ROTATION_GETBBOX[ELEM.node.id] == "object") ? BEFORE_ROTATION_GETBBOX[ELEM.node.id] : ELEM.getBBox();
var min_x = -ELEM_BOX.x;
var max_x = RECT_BOUNDARY.x2 - ELEM_BOX.x2 + ELEM_BOX.width;
var min_y = -ELEM_BOX.y;
var max_y = RECT_BOUNDARY.y2 - ELEM_BOX.y2 + ELEM_BOX.height;
ELEM.limitDragging({
x: 0,
y: 0,
minx: min_x,
miny: min_y,
maxx: max_x,
maxy: max_y
});
}
}
var DBLCLICK_HANDLER = function(ELEM) {
SETUP_DRAG_MOVEMENT(THIS_RECT, true);
var THIS_ELEM_BB = ELEM.getBBox();
var transformProp = new Snap.Matrix();
transformProp.rotate(45, THIS_ELEM_BB.cx, THIS_ELEM_BB.cy);
transformProp.add(ELEM.matrix);
ELEM.transform(transformProp);
SETUP_DRAG_MOVEMENT_ROTATED(THIS_RECT, false);
}
var myCircle = s.circle(380, 20, 20).attr({
fill: 'blue'
});
var THIS_CIRCLE_LABEL = s.paper.text(376, 25, "1").attr({
fill: "#FFFFFF"
});
var THIS_CIRCLE = s.group(myCircle, THIS_CIRCLE_LABEL);
THIS_CIRCLE.attr({
id: "THIS_CIRCLE"
});
SETUP_DRAG_MOVEMENT_ROTATED(THIS_CIRCLE, false);
var myRect = s.rect(0, 0, 30, 30).attr({
fill: 'green'
});
var THIS_RECT_LABEL = s.paper.text(11, 19, "2").attr({
fill: "#FFFFFF"
});
var THIS_RECT = s.group(myRect, THIS_RECT_LABEL);
THIS_RECT.attr({
id: "THIS_RECT"
});
SETUP_DRAG_MOVEMENT_ROTATED(THIS_RECT, false);
THIS_RECT.node.addEventListener("dblclick", function() {
DBLCLICK_HANDLER(THIS_RECT);
}, false);
<script src="http://snapsvg.io/assets/js/snap.svg-min.js"></script>
<p>Double click on the rectangle to rotate it and then try to drag. When you drag without rotating, it's perfect (The drag boundary). But while dragging a rotated object, then the problem arises..</p>
<svg id="svgout" height="400" width="600"></svg>
How do I solve this one?
As that includes some of my old code, thought I would do an answer....
Originally that doesn't take into account existing transforms easier. I wrote some updated code that would do this...
The main bits that are different are the getInversePoint() function, which gets the inverse transformation to the screen. Also I've changed the order of transformations, so the element is always panned first.
Example
Element.prototype.getInversePoint = function( x, y ) {
var pt = this.paper.node.createSVGPoint();
pt.x = x; pt.y = y;
return pt.matrixTransform( this.paper.node.getScreenCTM().inverse());
}
Element.prototype.limitDrag = function( params ) {
this.data('dragParams', params );
this.data('x', params.x); this.data('y', params.y);
this.drag( limitMoveDrag, limitStartDrag );
return this;
};
function limitMoveDrag( xxdx, xxdy, ax, ay ) {
var tdx, tdy;
var params = this.data('dragParams');
var pt = this.getInversePoint( ax, ay );
var dx = pt.x - this.data('op').x;
var dy = pt.y - this.data('op').y;
var ibb = this.data('ibb');
if( ibb.x + ibb.width + +dx > params.maxx )
{ dx = params.maxx - (ibb.x + ibb.width) };
if( ibb.y + ibb.height + +dy > params.maxy )
{ dy = params.maxy - (ibb.y + ibb.height) };
if( ibb.x + +dx < params.minx ) { dx = params.minx - ibb.x; };
if( ibb.y + +dy < params.miny ) { dy = params.miny - ibb.y; };
this.transform( "t" + [ dx, dy ] + this.data('ot').toTransformString());
};
function limitStartDrag( x, y, ev ) {
this.data('ibb', this.getBBox());
this.data('op', this.getInversePoint( x, y ));
this.data('ot', this.transform().localMatrix);
};

How can I do a colour based hit test for a certain image on a web page?

I need to know when my mouse pointer is over a certain image, and while in that image, it goes over a very specific colour. Is this possible and how can I do it?
Just wrote this :
Basically, it does what #nepeo told you to do.
+ it cleans up the canvas and reset the original image after calculations.
+ I also added a customized cursor that you can disable.
Usage : Set your own callback function in colorPicker.callback, then attach the colorPicker.init function on the mouseover event of desired image.
N.B : You will have to host the images on your own server or to convert them to base64 in order to use this script.
var colorPicker = function() {};
//Settings
colorPicker.radius = 1, //square px
colorPicker.customCursor = true;
colorPicker.cursorColor = '#FFF';
//the fomatting for color return : "hex" || "rgba" || "array"
// !! hex is upperCase and returns "transparent" if opacity == 0; rgba is 'rgba(r,g,b,a)'; array is '[r,g,b,a]'
colorPicker.colorFormat = "hex";
//What to do with that color? Edit this to whatever you want
colorPicker.callback = function (color) {
var res = document.getElementById('ColorPickerResult');
res.style.backgroundColor = color;
res.style.color = invertHex(color);
res.innerHTML = color;
//Here I'm searching for some Hex color
if (color == '#FC771F') {
res.innerHTML = '!!! Found some orange !!!';
}
}
//What to do when we leave the image (Additionally to reset the original image)
colorPicker.callbackOut = function(){
var res = document.getElementById('ColorPickerResult');
res.innerHTML = '';
}
//END Settings
//This is optional
colorPicker.setCursor = function (canvas) {
if (!colorPicker.setCursor) return;
var can = document.createElement('canvas');
can.width = colorPicker.radius;
can.height = colorPicker.radius;
var ctx = can.getContext('2d');
ctx.strokeStyle = colorPicker.cursorColor;
ctx.rect(0, 0, colorPicker.radius, colorPicker.radius);
ctx.stroke();
canvas.style.cursor = 'url("' + can.toDataURL("image/png") + '"),default';
}
colorPicker.Init = function () {
var img = this;
var can = document.createElement('canvas');
can.id = 'ColorPicker';
can.width = img.width;
can.height = img.height;
can.ori = img;
can.oridisp = img.style.display;
var ctx = can.getContext('2d');
ctx.drawImage(img, 0, 0);
can.addEventListener('mousemove', colorPicker.pick);
can.addEventListener('mouseout', colorPicker.out);
colorPicker.setCursor(can);
img.parentNode.insertBefore(can, img);
img.style.display = 'none';
};
colorPicker.pick = function (evt) {
var rect = this.getBoundingClientRect();
ctx = this.getContext('2d'),
imageData = ctx.getImageData(evt.clientX - rect.left, evt.clientY - rect.top, colorPicker.radius, colorPicker.radius);
data = imageData.data;
r = 0, g = 0, b = 0, a = 0;
for (i = 0; i < data.length; i++) {
r += data[i];
g += data[++i];
b += data[++i];
a += data[++i];
}
var p = data.length / 4;
var mR = function (i) {
return Math.round(i);
};
r = mR(r/p);
g = mR(g/p);
b = mR(b/p);
a = (mR((a/p)/255 * 100)/100).toFixed(2);
if(colorPicker.colorFormat === "hex"){
var color = colorPicker.toHex(r,g,b,a);
}
else if(colorPicker.colorFormat === "rgba"){
var color = 'rgba('+r+', '+g+', '+b+', '+a+')';
}
else if(colorPicker.colorFormat === "array"){
var color = [r, g, b, a];
}
colorPicker.callback(color);
}
colorPicker.out = function () {
this.ori.style.display = this.oridisp;
this.parentNode.removeChild(this);
colorPicker.callbackOut();
}
//toHex function originally posted by http://stackoverflow.com/users/10474/felipec in http://stackoverflow.com/a/19765382/3702797
colorPicker.toHex= function(r,g,b,a){
if(a=="0.00") return "transparent";
var rgb = b | (g << 8) | (r << 16);
return '#' + (0x1000000 + rgb).toString(16).slice(1).toUpperCase()
}
// END colorPicker \\
// Just an example of external function beeing called
function invertHex(c){
if(c==="transparent") return "#000000";
c = c.replace('#', '');
var reqHex = "#";
for(var i=0;i<6;i++){
reqHex = reqHex + (15-parseInt(c[i],16)).toString(16);
}
return reqHex;
}
//Attach the function to whatever images you want
document.getElementsByTagName('img')[0].addEventListener('mouseover', colorPicker.Init);
body {
background: #175;
}
<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAO4AAABDCAYAAACbbDkSAAAKQWlDQ1BJQ0MgUHJvZmlsZQAASA2dlndUU9kWh8+9N73QEiIgJfQaegkg0jtIFQRRiUmAUAKGhCZ2RAVGFBEpVmRUwAFHhyJjRRQLg4Ji1wnyEFDGwVFEReXdjGsJ7601896a/cdZ39nnt9fZZ+9917oAUPyCBMJ0WAGANKFYFO7rwVwSE8vE9wIYEAEOWAHA4WZmBEf4RALU/L09mZmoSMaz9u4ugGS72yy/UCZz1v9/kSI3QyQGAApF1TY8fiYX5QKUU7PFGTL/BMr0lSkyhjEyFqEJoqwi48SvbPan5iu7yZiXJuShGlnOGbw0noy7UN6aJeGjjAShXJgl4GejfAdlvVRJmgDl9yjT0/icTAAwFJlfzOcmoWyJMkUUGe6J8gIACJTEObxyDov5OWieAHimZ+SKBIlJYqYR15hp5ejIZvrxs1P5YjErlMNN4Yh4TM/0tAyOMBeAr2+WRQElWW2ZaJHtrRzt7VnW5mj5v9nfHn5T/T3IevtV8Sbsz55BjJ5Z32zsrC+9FgD2JFqbHbO+lVUAtG0GQOXhrE/vIADyBQC03pzzHoZsXpLE4gwnC4vs7GxzAZ9rLivoN/ufgm/Kv4Y595nL7vtWO6YXP4EjSRUzZUXlpqemS0TMzAwOl89k/fcQ/+PAOWnNycMsnJ/AF/GF6FVR6JQJhIlou4U8gViQLmQKhH/V4X8YNicHGX6daxRodV8AfYU5ULhJB8hvPQBDIwMkbj96An3rWxAxCsi+vGitka9zjzJ6/uf6Hwtcim7hTEEiU+b2DI9kciWiLBmj34RswQISkAd0oAo0gS4wAixgDRyAM3AD3iAAhIBIEAOWAy5IAmlABLJBPtgACkEx2AF2g2pwANSBetAEToI2cAZcBFfADXALDIBHQAqGwUswAd6BaQiC8BAVokGqkBakD5lC1hAbWgh5Q0FQOBQDxUOJkBCSQPnQJqgYKoOqoUNQPfQjdBq6CF2D+qAH0CA0Bv0BfYQRmALTYQ3YALaA2bA7HAhHwsvgRHgVnAcXwNvhSrgWPg63whfhG/AALIVfwpMIQMgIA9FGWAgb8URCkFgkAREha5EipAKpRZqQDqQbuY1IkXHkAwaHoWGYGBbGGeOHWYzhYlZh1mJKMNWYY5hWTBfmNmYQM4H5gqVi1bGmWCesP3YJNhGbjS3EVmCPYFuwl7ED2GHsOxwOx8AZ4hxwfrgYXDJuNa4Etw/XjLuA68MN4SbxeLwq3hTvgg/Bc/BifCG+Cn8cfx7fjx/GvyeQCVoEa4IPIZYgJGwkVBAaCOcI/YQRwjRRgahPdCKGEHnEXGIpsY7YQbxJHCZOkxRJhiQXUiQpmbSBVElqIl0mPSa9IZPJOmRHchhZQF5PriSfIF8lD5I/UJQoJhRPShxFQtlOOUq5QHlAeUOlUg2obtRYqpi6nVpPvUR9Sn0vR5Mzl/OX48mtk6uRa5Xrl3slT5TXl3eXXy6fJ18hf0r+pvy4AlHBQMFTgaOwVqFG4bTCPYVJRZqilWKIYppiiWKD4jXFUSW8koGStxJPqUDpsNIlpSEaQtOledK4tE20Otpl2jAdRzek+9OT6cX0H+i99AllJWVb5SjlHOUa5bPKUgbCMGD4M1IZpYyTjLuMj/M05rnP48/bNq9pXv+8KZX5Km4qfJUilWaVAZWPqkxVb9UU1Z2qbapP1DBqJmphatlq+9Uuq43Pp893ns+dXzT/5PyH6rC6iXq4+mr1w+o96pMamhq+GhkaVRqXNMY1GZpumsma5ZrnNMe0aFoLtQRa5VrntV4wlZnuzFRmJbOLOaGtru2nLdE+pN2rPa1jqLNYZ6NOs84TXZIuWzdBt1y3U3dCT0svWC9fr1HvoT5Rn62fpL9Hv1t/ysDQINpgi0GbwaihiqG/YZ5ho+FjI6qRq9Eqo1qjO8Y4Y7ZxivE+41smsImdSZJJjclNU9jU3lRgus+0zwxr5mgmNKs1u8eisNxZWaxG1qA5wzzIfKN5m/krCz2LWIudFt0WXyztLFMt6ywfWSlZBVhttOqw+sPaxJprXWN9x4Zq42Ozzqbd5rWtqS3fdr/tfTuaXbDdFrtOu8/2DvYi+yb7MQc9h3iHvQ732HR2KLuEfdUR6+jhuM7xjOMHJ3snsdNJp9+dWc4pzg3OowsMF/AX1C0YctFx4bgccpEuZC6MX3hwodRV25XjWuv6zE3Xjed2xG3E3dg92f24+ysPSw+RR4vHlKeT5xrPC16Il69XkVevt5L3Yu9q76c+Oj6JPo0+E752vqt9L/hh/QL9dvrd89fw5/rX+08EOASsCegKpARGBFYHPgsyCRIFdQTDwQHBu4IfL9JfJFzUFgJC/EN2hTwJNQxdFfpzGC4sNKwm7Hm4VXh+eHcELWJFREPEu0iPyNLIR4uNFksWd0bJR8VF1UdNRXtFl0VLl1gsWbPkRoxajCCmPRYfGxV7JHZyqffS3UuH4+ziCuPuLjNclrPs2nK15anLz66QX8FZcSoeGx8d3xD/iRPCqeVMrvRfuXflBNeTu4f7kufGK+eN8V34ZfyRBJeEsoTRRJfEXYljSa5JFUnjAk9BteB1sl/ygeSplJCUoykzqdGpzWmEtPi000IlYYqwK10zPSe9L8M0ozBDuspp1e5VE6JA0ZFMKHNZZruYjv5M9UiMJJslg1kLs2qy3mdHZZ/KUcwR5vTkmuRuyx3J88n7fjVmNXd1Z752/ob8wTXuaw6thdauXNu5Tnddwbrh9b7rj20gbUjZ8MtGy41lG99uit7UUaBRsL5gaLPv5sZCuUJR4b0tzlsObMVsFWzt3WazrWrblyJe0fViy+KK4k8l3JLr31l9V/ndzPaE7b2l9qX7d+B2CHfc3em681iZYlle2dCu4F2t5czyovK3u1fsvlZhW3FgD2mPZI+0MqiyvUqvakfVp+qk6oEaj5rmvep7t+2d2sfb17/fbX/TAY0DxQc+HhQcvH/I91BrrUFtxWHc4azDz+ui6rq/Z39ff0TtSPGRz0eFR6XHwo911TvU1zeoN5Q2wo2SxrHjccdv/eD1Q3sTq+lQM6O5+AQ4ITnx4sf4H++eDDzZeYp9qukn/Z/2ttBailqh1tzWibakNml7THvf6YDTnR3OHS0/m/989Iz2mZqzymdLz5HOFZybOZ93fvJCxoXxi4kXhzpXdD66tOTSna6wrt7LgZevXvG5cqnbvfv8VZerZ645XTt9nX297Yb9jdYeu56WX+x+aem172296XCz/ZbjrY6+BX3n+l37L972un3ljv+dGwOLBvruLr57/17cPel93v3RB6kPXj/Mejj9aP1j7OOiJwpPKp6qP6391fjXZqm99Oyg12DPs4hnj4a4Qy//lfmvT8MFz6nPK0a0RupHrUfPjPmM3Xqx9MXwy4yX0+OFvyn+tveV0auffnf7vWdiycTwa9HrmT9K3qi+OfrW9m3nZOjk03dp76anit6rvj/2gf2h+2P0x5Hp7E/4T5WfjT93fAn88ngmbWbm3/eE8/syOll+AAAACXBIWXMAAAsTAAALEwEAmpwYAAABy2lUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iWE1QIENvcmUgNS40LjAiPgogICA8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPgogICAgICA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIgogICAgICAgICAgICB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iCiAgICAgICAgICAgIHhtbG5zOnRpZmY9Imh0dHA6Ly9ucy5hZG9iZS5jb20vdGlmZi8xLjAvIj4KICAgICAgICAgPHhtcDpDcmVhdG9yVG9vbD5BZG9iZSBJbWFnZVJlYWR5PC94bXA6Q3JlYXRvclRvb2w+CiAgICAgICAgIDx0aWZmOk9yaWVudGF0aW9uPjE8L3RpZmY6T3JpZW50YXRpb24+CiAgICAgIDwvcmRmOkRlc2NyaXB0aW9uPgogICA8L3JkZjpSREY+CjwveDp4bXBtZXRhPgopLs09AAAVE0lEQVR4Ae2dz28cR3bHu3tIS0AOAYEYuY+BxDlEh3CvCxgB/Rc49CF7pxEnCBDAu6KzB8GHQKS8QLBA4kC6Zw9i/BdoEATYq3jRHnYRwDzkFuTALHKhl5zpfD/FeqWq6u6ZIaWhRE01MOzqqlevXn3rvXr1q5t19RZe7U/f323b6mkiWlsdNw//5wdJXHkoCKwpAs1N1fvi0Xu77cNqa6nypu1Jh66uxu3+7y+Xv5O5RBQE3i0EVm647cO744tHd57VVf101ty9vxx85xjuaUYro90cZ3HlsSCwlgis1HCnj+7uzUbV87qqdhy6dXu//dnm9iKk64PfnlZt1fG64rUw7yLeJb0g8C4gsDLDvTTQ9nFVtcnwdjZt0rnrEIp113Crti4edwivEr9WCKzMcOsvzo+F5JMOmpqrTh/dkUHPv9qqIn9y1W1bPG6CSHlYVwRWZrgA2ky/3+8b8ipp7/zru5fD5wHkm1nTMdyqLh53AK4SvWYIrNRw6y+r01lTf9aHaTNrHy9YZe7MccVnq93/wzJc7gO0xK0VAis1XJDc/PHZRHPTww6qGjLPRncOOvEh4oxV5dx4mS8Xww0YlcC6IrBywwXY0f2z/aqqu0NfDZnZ3+0D/3JlubufOxtNi+H2AVbi1gqBGzFcEG2aae+Qua6awSFzWze5x9UidVMWqNZKRUtl+xC4McN1q8x9Q2ZtF01Hd/q3iOpZx0vX7ax43L6WLHFrhcC1DffF13+y8+LhnyZ7tIuQGxoyc0CDwxp5/mY66nrcut4uRx9zpMrzuiFwLcN98Y9/NK6r9lm9cf7di0d/3DtHHQKymVafar6bH2eE/IDjkVm+ruFqZbmq7l6pw8h4lseCwK1H4FqGW01Hthq8Vdf10199/eGzFz/7cKm5Z/3lGcaoxar8ard0pDEZMtcH/w1t13hHs6XKyksozwWBdwWBKxsuQ2SdYMq9rOKq5y8effgYb7wInNFPzp7oZNSkS9duTw/vWqdwmdz2rCy3ZUuoi12JWScErmy4GiKnhhWhVdfVXn3RPJdxL3wLaDT9vn/InL2I0NbdbSTNiYvHjXAvwfVD4MqG21Y1w9webxnA28K4NXyWBx6e/3Kqqq1mvVtEs9no5VnmuutxdYxyoVcP0pRAQeAdREDO63oXRql3bA8qnYCax0Ee80ibr4f3vvhNZ2uHfP6Fg86KMqetWIVu9/9gu23q51kZp/Xsdx+4QxpZQnksCKwDAtc2XMBx20EbF3vysAyN56706lM0T6rp5v69L3+VrChzXnnW3Hne1wE0zewH7P/O/v59TYmT66SeNR/7xaskoTwUBNYBgVcyXAPILUhppbln0cpILu96Ob5tKrxv8rofbwo1bfssJeapPm2mZx/M/u9955H9G0NaZT47Ld62i1aJWR8EXovhGlxuxfly8WrR4tFEc+XDez/+dZgr9w6ZNVxuZmeHzIetjHIvCBQE5NJWAYL2dPe0PcTq8+Lh8+bs8N7f/afbq50e3vnucshcH3O22b+MvwoRC8+CwK1GYCWGCyJu/js6P2CLaAFCWl123veQz93MpqPdy6ORC3KV5ILAGiOw0HB/+c0n46m8Z93Wx9Omnvz550e9q8NDGHKiynvfuV+8UP7j//29P/v4h5//ogyLh8As8QUBj8BCw/2Pb/5it2rb+CjiifZRJ3WjD5RrP/eHn3/bPZLYA++i7SO2je598WsdyihXQaAgsAiBxYb7T5881rxzcLjLR93kUY8reeNR1R7PM+Q520en7cXmB/lW0SLhS3pBYF0RWGy4//zJdwJn7iGLCDyGucfas5UhV5ON6o4MuTv0zbeP2rr6LN8iiniWYEGgIJAhMNdw//2b3e2mneWnljIWcx+dIWt+POmbH7N9pGH47r2f/Kb36ONcziWxILDGCMw13F9+85dbF9X329VM/4mgrnZEjOedu8WzAEvmw8daaZ5cZX68gGdJLgisHQJzDTdHw60wV7UMud3R8HZbmRcdtMhZJM/MjzfqO2UlOUGlPBQEFiNwJcPN2WHIM312RnNatnow4mXnwsbq5KO//vYDeyj3gkBBYDkEXslw4yIYVp9X5+OR88atGfL8YbVePPjob74t89sIyM3Ny3+Kdn7e+x8LI8oSnIPA1mg0QgdN/06n0ynHa1lzGQtji6+EM3FLbWmK7q256q+++ofkzZsHD376Wow5nh9rTos35hcAcwjU9acfff5veu2vqlYlhyvnFv1pmoZVfP23lXpfyuawuUXiv3FRhR9vqiXbl8ISw/0Y4WTQj9vof1Ap7VBpyUsvb7wSSwiwMUTzrw//aqva1P+jPR+pRzo7/dGX/0LPtPTlt4Ho5dyLBBjytPrdTjQ/Ho+q98JLBkszLoQFgQEE+ox2gDREy4hTZxJS3u7AoOFWo83delY9rkZT1WDz9BeHf3uqlWWM91Qu+WTW8qXGmeJ05ysV3OcYuTdkPIjzIhhy3x7vDcDFMIovbDAfp7ctXu0GQL+BIsbynrsyxBso6s0XMWy49EQa4/pL4ZfDXKCpdVwqvFykJWYdg9Q4pNfIT2XkmkNg5PrPBPWlsf/Xb90czrO/8duYnlYNfeMFlwJXg8DGxsZ4Npsl3pNhsLywO1uvDhqnk6SvRpKb4TpsuFWjSl6r95pj5OLnjbxt3uMfgfV8pvVmKl5KebcQUEec7GjIaJnXPtHv3aqor82g4TZ1O76W2S4NkzxvuW4CAbyMeRo31Rko1GgseVH7xPTzaJct38rlPsTbeFl5do/zripsMnGn3HllG63JsgztMjSB36DhMrzVt6Q0tHUg5oIYg+vfmRO/ngvZtmyJ3y/vw7uPv6ONis2fB/MsyT9inQT7ZHzVLQh42pXLbdshOyLAExntqTzTseb4R8Ipfj1zrLj8u2FHA/P/LRaB5NFiDzfBu5kw3DV01f6++/72MuWHrOKtd7hf8lb4ifeeu7rHOxPgh4zHfpgcy+P4qU7kcdhcXFxcdyEUbMCRn+kLPPlRb/iGtqRMPSffHRcNW56dNspw7MXb45iskovf/qDh/uj+zxnG7rvVZf7lx+Z0S+eK9dMQ2v3jrWZLXtlVRJ55rFF1PEQ2RRGLgavvs6sDpEPREUhjVcaVKTA0/2ZO7cA0YAENZearHG5+63nu+UbhkaFVvKc8Fq89UxbjL3rXaBiA5lQoa2g0zzO+UaY15FbGQ1/5aJ5kBhTnHQwrH4aDEuu/IDaHGQ9nhJIPRcsvMAKrXcr28lMf6rClPI4nmbzCdxbu1IG5/KKFzF3wsrDuDmfxvkr5lp11B9onyKEEFpycwcZlKp64beE76StLtNT1gDy+Lm47SHFLX95o7otH3imYflM+ncOhdQzC4kT4xvLTiW1buhWe4ygeJNEJJAbu6xb4iY4O93TQcOHC5beBEmaXKd2/vUau/8anee0YI3cGTq+FkTev5nEFEIC6noiG0Q/lQ04UEKD57YjuSJWnEwJs+ykYLmuEEOEbjEaHl+sIPH9oUCzHX422o/j9vFE8IwwIHg70SEZ4UuaO5KLhr7SyLfo95eeHXLnROqOxMr0cQ7c9YVNJBvun4xhpUBDxwPCQM2l7ZI4ZUi/VP3hvX+c+o42zEab8Ld82eVp49nKE5zigsikXZV+mvDjrwnCsA/OIJR+6cCB6pwfqRE+EwYmPd1lVR+RLPL6MO5FZ9NsYc9YJ08bbSgsiKLyc4YYcSwSuYuRLsBskAVSBYcMHFiBQuqBg1ptRaaWZN6AnxKOi3E8FAEppeZOylGarzifiQW8aFNPnR3npOODBENOBqbtdwYCUH7kox3rTLckPf4xvW+nWqEF+Y5LfJTfeh/K4GFpZ3VyEDMHxdA/+jy/fPCpKFl97wmqCsogXQ2iG0tTJXXreUXzsdUnLFc7qxeEG5EvSVb5e87z8qL3CKGEsw66wmAx0fF6Ky5vyWsdsbYPMbnFT5Vr9guzk8nkILsQWouiic7X2DdHiBx/KcjJYgmgTPdAz+hDqSb2N1t8ZWSQGSbzvFGNdo5zABxq1MSO9aoOH23apMm4OocozFDaPEarhey0AANC40eKw0XfixPMJSqw7PGio+CKeXpU4POpYypcMhbwCu8aSjLlHxkPBE0PZFa+k04kLisN0VirLGe1AvVGGZB9Tzydq6H28ALxUHjySfyHjO0A6NCeT7rHhgXNiuMqfKKF4MqIRmbusM7VnOhfaxzBORiEQiR95Em9EfHbR8VknxRx7zz+7ein8KVgqj3VqGC3tFH9RBRkSw87KCI+0p+qUGIwSraN0fJBBcU4Pyah6BD1QGsP3JE0k8HPy6k7HkOCoOC6wD/qgOiXGTXuaE5lruF9lxyEd69f458H1jlcCvjVA3Dv1SWYK05dG3GC6Gj1W2E5+pU8ErPNQNFpEgGzWaEdzvAmKZcoYZe8G5RVRJOcB1HjmaRLZ/SjDcHFMRJsMpamTlAqFMfmgQ3byMd04Ul2C4XrlcmkQqr4YPkF3IYt1CopIvIPSqF9stOShI2FqED6FlJfhGEd/KMPjZPU9FRb5NqKlRTldcCg+p0uexT8xKsnAaC2uCzIcejwC5j7fBONSWjJc1jOjP2e4OY5WeA8WoS2gUTr67urUWKZbdA+NoYrEBvMmquBkkRyh8TAgk0sNNNf4lxSYgwXOs3sFQmkDBsZDNAkW0FrvbDTc8Qbxs8LI7uSHnnxxOkrmn6GxsIuKFQnFjPMpHJQsjmc0pDIS+fFwMU0cjsuI41cZlnwJlgMyUIfEcUT5SEtwFI+4jgmOcV0ivImO8zCKCOXdRsOlQqZ8u6ooQ5YEaAje1BUbUOSNriuOzZWtfnjoRCEixqHz8HGJcRidjLOTX52N5WUEYdhaFlOyZHiH8amuccdkPCwfC2/P+n4qI6HNn43BG7wn8kmOXiwld45lnC/BUXiZEdKxW5gqHikt5gPebG8yTA78wFseOxjuBjlv26UKHNEzAYB+9+VF2B4B3PjHECvMF65RR4wGEPmZ4SRsVHZfvAPby5PQX/HB7ZdSxyifzQd7FSmiWzoo/kE5yKQ6s25AOe5SulMkj7dFc0fZgsLlWHi+Ce84cxZeli7L9tY9hnpgZMIsLPZ5fNyesMJBcEZA6gBpT4e50mhvVtvjdoceow1430rDVQXofT4TMMzVWJChFwO0AJzCbAVh0Nd5PQ6Aef2rzzDF+kYu6sbBeRoVT8uK8Zg6qVHzOd5rE4ihrOqez8+sA4vLib1tHF/ClwhYxxYMULgmOKpt3XRG3hV9Dp2l2pi2D/k8oMHb8jzXcB9cb/HIl7PyG5VFofk5o2XIJ6XG2Hg2gz5Q/AkKqbhlrjA8BVj9bDso93LQsa2UG3dOt0yZHZqIr9vnVWNSJxp3V/XJTz6RPy837sRIdxcYCTd7dKuvwibPi1GGFVqFwTIoEp2JeCR4gpVoYr4TyUzbLLxUfvAkC4nfLoIc4xxHhssBN4XdKNGqILzA8JT6x52lsIQu6JXHOxl6zzVcK+AW3AEMABDVFIrhtDMsKRk9ncVDM3hJsTkZxP7qqRSPrZSl8hlD8qHA+tGo/PLGNNKFd/EKhzPUIbFF5RpUYYwqOUZn5UZMe8v3HVtE1g2q/qyY4+GdYuoeKx8ZwCQ3tryeW1fFrivJG4tJ6iJsgxHFEimeeX8cleRbhKP0i2Ey+W1twYbLeXnmvUNZTQi9ewFAdMo1BHxflSPFdj1hH828OBZ/MCJopPy5ws/LmqfZvqHFw9N5MAxJvOMtnSpfdMLoMHTLHN2TfIrvKIWPG+ywVL/OMFlKmtAjI3vPUblxkEMoQ2kx3ZsKJ3WREJxqytuS6VlehzxfH7auTsIwWfVXWyUeNa64ysn5VrfVcM2bxPXrC5vHSHrCiNClR89XCdLb5j0j+WksA5oedF4ZffnhkSz9uwj9kXGwAukaWGXfz5SJfVgr17JwrNDRQSvlSD7bAlGfUvjMvYqUK5wVpDsdVlK+eB/4DoZ6ggOHFHYU91Qd5GOfFrFYeRA9SHRBMu/4TsRkdKeTYklUD6ZgoS7IrR8fYwiX+DBCS+pP4hC+Pj7IwugEbAPDKKCyOm2xEaW74FcrPnSRl3eNZzcHVT5WXZMDBjEvwBU4rpeMhiSQABYAkUaPmaw8i5bNdgB3K4AYi2jyCxk4EJHHu2fx4AA/K97upJB4sHkfN4p5Qwy799hlL2NFwktlu60ClcGQ2U4HUS9kDZ5B5WMsnDJyQzCFkwtFGagf5YQDJnEm8UQ5g8LFabSH8sWHKygfhYeeHwYQOjLxIs11SDGfFYeRP3hK2ki/x5KdYt25doxIck0Un9Ap/QA6xUObXxxG6RgufPrwFx8bJgc+4ouBJm1FG/Xx7Rhu4PKWBuQ5OJBgikuvDVixMqEYYRFAFZ9oGJkD6hRcQOGFmAe7/OJLR8BCgWs0xaNYNF7grzhWepPFgxwq3/AMazFuPAzyTmgE3e2cqjMweImOBus1hpy3nuGB/O5csnjbsUlnAFIIPEfS+D083KKUys47lJjU5l3J0FrlxUccY3q+mIjCH0q+eGELRadNgsFaJpW/bJ0tyyvf6agkY9CPIYaio4NM9q6HaFUPO83WIfGYJKv0ok+GyZZJ5XWMXNjluuvIb53hAoSM9zO8jSplXhPlTy6UQul2ljlREBrPFFw0KLptu7hjbXGjKR3eOX/48Z7ooAGLhzvvLDq3jaM7IwDd3PDJ3fUnP8tr8XPvqntYqBIhRkLjOo9O5yMFQD63qq5750LRVP/B0YplEB/kC4aLwgn/eORgpOHeU++QFgeWlSHO85rCrIjvq26uU53Dk9HIvnDi1U7aubfjUXyvjsV8RUP7oGfu8s+JTpLQZ+Qqv+OZoe18npXIt+F6sHgritMl5n0xPAesQHFzPYEelHlOfRjKYvzkpUHjYTELKJwRZoXZge5506B4SDwzSs2QvXeYpDQuNyxWXviYjM6r01CXJC//iqfzllbGy5Q0pLo72YgdKH9euRhfR3HSEi6fTB6eJD+eojPf6sunuIAfYepu+Hl5e2UwTI3nQN0sOdxjPHxk3p6B1gdMf2hb1y4D9TM6N/WJ67GojaIC3bTLnuflY74tnIKRixadXKqtjH+5FwQKAgWBgkBBoCBQECgIFAQKAgWBgkBBoCBQECgIFAQKAgWBgkBBoCBQECgIFAQKAgWBgkBBoCBQECgIFAQKAgWBdxOB/wcP4cIU+D70agAAAABJRU5ErkJggg==" />
<span id="ColorPickerResult"></span>
Here I made an attempt. In this example the script searches for the color #FF0000, as passed in the options object. http://jsfiddle.net/2sw3pzs4/
var ColorChecker = function( options ) {
var canvas, ctx, output;
this.init = function() {
canvas = document.getElementById('canvas');
output = document.getElementById('output');
ctx = canvas.getContext("2d");
color = this.hexToRGB(options.searchedColor);
this.drawOnCanvas();
canvas.addEventListener('mousemove', function(e) {
if(e.offsetX) {
mouseX = e.offsetX;
mouseY = e.offsetY;
}
else if(e.layerX) {
mouseX = e.layerX;
mouseY = e.layerY;
}
var c = ctx.getImageData(mouseX, mouseY, 1, 1).data;
var foundColor = [c[0], c[1], c [2]];
var is_identical = foundColor.join() === color.join();
var message = is_identical == true ? 'red found' : 'not found';
output.innerHTML = message;
});
}
this.drawOnCanvas = function() {
ctx.fillStyle = "#FF0000";
ctx.fillRect(0,0, 20, 20);
}
this.hexToRGB = function( hex ) {
var r = parseInt((this.cutHex(hex)).substring(0,2),16);
var g = parseInt((this.cutHex(hex)).substring(2,4),16);
var b = parseInt((this.cutHex(hex)).substring(4,6),16);
return [r,g,b];
}
this.cutHex = function( hex ) {
return hex.replace("#",'');
}
this.init();
}
var colorChecker = new ColorChecker({
searchedColor: "#FF0000",
});
If you want to use an image just use putImageData() to draw the image on the canvas. You can use the function drawOnCanvas in my code to draw whatever you want inside the canvas, or resize it or other stuff.
Use a canvas instead of the image, resize the canvas to the size of the image and draw the image into the canvas.
Then you can get the pixel location of the cursor using the canvas.onmousemove event. Canvas may have something in it's api for querying the colour at a location(can't remember at this moment) but otherwise you can use getImageData to get the rgba data for every pixel and do a look up during the event. Ta da!

Categories

Resources