How to execute a function on mouse click on rectangle HTML5 Canvas - html

I'm looking for a simple way to execute a function when someone clicks on a rectangle inside an HTML5 Canvas. I would like to do it in a way that doesn't require any special libraries. Any suggestions?

Here's a no-library way which involves:
Listening for mousedown events:
var canvas=document.getElementById("canvas");
canvas.onmousedown=handleMousedown;
Testing if the clicked mouse position is inside the rectangle:
var rect={x:100,y:100,w:75,h:40};
// mx & my are the mouse coordinates
if(mx>=rect.x && mx<=rect.x+rect.w && my>=rect.y && my<=rect.y+rect.h){
alert("clicked in rect");
}
Here's example code and a Demo:
var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
var BB,BBoffsetX,BBoffsetY;
setBB();
var rect={x:100,y:100,w:75,h:40};
ctx.fillRect(rect.x,rect.y,rect.w,rect.h);
canvas.onmousedown=handleMousedown;
function handleMousedown(e){
e.preventDefault();
e.stopPropagation();
var mx=e.clientX-BBoffsetX;
var my=e.clientY-BBoffsetY;
if(mx>=rect.x && mx<=rect.x+rect.w && my>=rect.y && my<=rect.y+rect.h){
alert("clicked in rect");
}
}
function setBB(){
BB=canvas.getBoundingClientRect();
BBoffsetX=BB.left;
BBoffsetY=BB.top;
}
body{ background-color: ivory; }
canvas{border:1px solid red;}
<h4>Click in the rect for an alert</h4>
<canvas id="canvas" width=300 height=300></canvas>

Related

How can I use html5 canvas to straighten & crop an image? [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 7 years ago.
Improve this question
How can I use html5 canvas to rotate imageas shown below?
From before:
To after:
Normally I wouldn't answer a "request to write code", but I had the code you need laying around.
I offer it here without further explanation or annotation:
var canvas1a=document.createElement("canvas");
var ctx1a=canvas1a.getContext("2d");
var canvas2=document.getElementById("canvas2");
var ctx2=canvas2.getContext("2d");
var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
function reOffset(){
var BB=canvas.getBoundingClientRect();
offsetX=BB.left;
offsetY=BB.top;
}
var offsetX,offsetY;
reOffset();
window.onscroll=function(e){ reOffset(); }
window.onresize=function(e){ reOffset(); }
var canvas1=document.getElementById("canvas1");
var ctx1=canvas1.getContext("2d");
function reOffset1(){
var BB=canvas1.getBoundingClientRect();
offsetX1=BB.left;
offsetY1=BB.top;
}
var offsetX1,offsetY1;
reOffset1();
window.onscroll=function(e){ reOffset1(); }
window.onresize=function(e){ reOffset1(); }
var topLeft,topRight,bottomRight,bottomLeft;
var startX,startY,mouseX,mouseY;
var isDown=false;
var img=new Image();
img.onload=start;
img.src="https://dl.dropboxusercontent.com/u/139992952/multple/tilted.jpg";
function start(){
canvas.width=img.width;
canvas.height=img.height;
ctx.drawImage(img,0,0);
//
$("#canvas").on('mousedown',handleMouseDown);
}
function handleMouseDown(e){
e.preventDefault();
e.stopPropagation();
//
mX=parseInt(e.clientX-offsetX);
mY=parseInt(e.clientY-offsetY);
//
if(!topLeft){
topLeft={x:mX,y:mY};
drawMarker(topLeft);
}else if(!topRight){
topRight={x:mX,y:mY};
drawMarker(topRight);
}else{
$("#canvas").off('mousedown',handleMouseDown);
//
bottomRight={x:mX,y:mY};
drawMarker(bottomRight);
//
var dx=topRight.x-topLeft.x;
var dy=topRight.y-topLeft.y;
var angle=Math.atan2(dy,dx);
var width=Math.sqrt(dx*dx+dy*dy);
dx=bottomRight.x-topRight.x;
dy=bottomRight.y-topRight.y;
var height=Math.sqrt(dx*dx+dy*dy);
//
canvas1a.width=canvas1.width=width;
canvas1a.height=canvas1.height=height;
ctx1a.rotate(-angle);
ctx1a.drawImage(img,-topLeft.x,-topLeft.y);
ctx1.strokeStyle='red';
ctx1.drawImage(canvas1a,0,0);
//
$("#canvas1").mousedown(function(e){handleMouseDown1(e);});
$("#canvas1").mousemove(function(e){handleMouseMove1(e);});
$("#canvas1").mouseup(function(e){handleMouseUpOut1(e);});
$("#canvas1").mouseout(function(e){handleMouseUpOut1(e);});
}
}
function handleMouseDown1(e){
// tell the browser we're handling this event
e.preventDefault();
e.stopPropagation();
//
startX=parseInt(e.clientX-offsetX1);
startY=parseInt(e.clientY-offsetY1);
// set drag flag
isDown=true;
}
function handleMouseUpOut1(e){
if(!isDown){return;}
// tell the browser we're handling this event
e.preventDefault();
e.stopPropagation();
//
mouseX=parseInt(e.clientX-offsetX1);
mouseY=parseInt(e.clientY-offsetY1);
// clear drag flag
isDown=false;
//
var w=mouseX-startX;
var h=mouseY-startY;
canvas2.width=w;
canvas2.height=h;
ctx2.drawImage(canvas1a,startX,startY,w,h,0,0,w,h);
}
function handleMouseMove1(e){
if(!isDown){return;}
// tell the browser we're handling this event
e.preventDefault();
e.stopPropagation();
mouseX=parseInt(e.clientX-offsetX1);
mouseY=parseInt(e.clientY-offsetY1);
ctx1.drawImage(canvas1a,0,0);
ctx1.strokeRect(startX,startY,mouseX-startX,mouseY-startY);
}
function drawMarker(pt){
ctx.beginPath();
ctx.arc(pt.x,pt.y,3,0,Math.PI*2);
ctx.closePath();
ctx.fillStyle='red';
ctx.fill();
}
body {
background-color: ivory;
}
canvas {
border: 1px solid red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<h4>First the topLeft corner<br>then click topRight corner<br>then click bottomRight corner</h4>
<canvas id="canvas" width=300 height=300></canvas><br>
<h4>Drag to clip a part of the image</h4>
<canvas id="canvas1" width=300 height=300></canvas>
<h4>Straightened & clipped image</h4>
<canvas id="canvas2" width=300 height=300></canvas>

Enable and disable mouse events for canvas using Fabric.js

I am using Fabric.js to draw rectangles on a canvas. After drawing a rectangle, I want to disable all events on that object. I have tried to do it using canvas.__eventListeners["mouse:down"] = []; but then after the object selection is cleared, the canvas can't apply any events.
<html lang="en" >
<head>
<meta charset="utf-8" />
<title>HTML5 canvas - Image color picker | Script Tutorials</title>
<link href="index.css" rel="stylesheet" type="text/css" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/1.1.0/fabric.all.min.js" ></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
</head>
<body>
<div class="container">
<div class="column1">
<canvas id="panel" width="700" height="350"></canvas>
</div>
<div style="clear:both;"></div>
<div id="log"></div>
</div>
</body>
<script>
(function() {
var canvas = new fabric.Canvas('panel');
var clicks=0;
var x1=0;var y1=0;
var rect;
canvas.on('mouse:down', function(e){
//check if you clicked on an object that exists canvas
if(e.target == undefined){
if (clicks == 0) {
var pointer=canvas.getPointer(event.e);
console.log(pointer);
x1 = pointer.x;
y1 =pointer.y;
console.log("Start Pointer " +x1 ,y1);
clicks++;
}
else
{
var endpointer=canvas.getPointer();
console.log(endpointer);
var endx=endpointer.x;
var endy=endpointer.y;
console.log("Endpointer " +endx ,endy);
console.log("x and y"+x1,y1);
var newwidth=endpointer.x- x1;
var newheight=endpointer.y - y1;
rect=new fabric.Rect({
left:x1,
top: y1,
originX :'left',
originY :'top',
width:newwidth,
height:newheight,
selectable: true,
evented:false,
fill:'red',
opacity :0.3
});
canvas.add(rect);
//console.log(rect.setWidth(pointer2.x- x1 ));
//console.log(rect.setHeight( pointer2.y - y1));
canvas.renderAll();
clicks=0;
}
}
else
{
//canvas.getActiveObject().remove();
canvas.__eventListeners["mouse:down"] = [];
}
});
canvas.on('object:moving',function(){
var bound=rect.getBoundingRect();
console.log(bound.left,bound.top,bound.width,bound.height);
});
canvas.on('object:scaling',function(){
var bound=rect.getBoundingRect();
console.log(bound.left,bound.top,bound.width,bound.height);
});
canvas.on('object:selected',function(e){
document.onkeydown = function(e) {
if (e.keyCode === 27||e.button==3) {
e.preventDefault();
canvas.getActiveObject().remove();
}
}
});
fabric.Image.fromURL('fedex.jpg', function (img) {
canvas.add(img.set({
width: 700,
height:350,
left: 350,
top: 175,
selectable: false,
}));
});
})();
</script>
With the method canvas.off('mouse:down', eventHandler) event handlers registered using canvas.on('mouse:down', eventHandler) can be removed. Be sure to pass the same function into both calls (e.g. by assigning the handler to a variable).
This method is available on all Observables in fabric (see API doc: http://fabricjs.com/docs/fabric.Observable.html#off)
What is the final answer? We're basing our decision to mousedown on or mousedown off, based on the event - if it has a target. I came up with this solution (a 2nd mousedown handler), but it didn't work.
canvas.on('mouse:down', function (e) {
// canvas click, not object click; so create the obj
if (e.target === undefined) {
canvas.on('mouse:down', eventHandler);
}
else {
// an object was clicked, so don't create the obj again
canvas.off('mouse:down', eventHandler);
}
});
Where eventHandler is the function that handles object creation.

HTML5 Canvas - Context Sensitive Menu

I'm drawing a number of rectangles on an HTML5 canvas and want to be able to right click on the boxes and get a context sensitive menu displayed. The menu should be specific to the type of box being clicked on and be totally user specified, i.e. it should not include Reload, Save As, Print etc...
Can any one give me any pointers?
Thanks,
Paul
You can addEventListener for context menu to handle right-mouse requests:
// listen for contextmenu requests
canvas.addEventListener('contextmenu', handleContextmenu, false);
Then in the handler, you check each of your rects for hits:
function handleContextmenu(e){
// get mouse position relative to the canvas
var x=parseInt(e.clientX-offsetX);
var y=parseInt(e.clientY-offsetY);
// check each rect for hits
for(var i=0;i<rects.length;i++){
var rect=rects[i];
var rectRight=rect.x+rect.width;
var rectBottom=rect.y+rect.height;
// if this rect is hit, display an alert
if(x>=rect.x && x<=rectRight && y>=rect.y && y<=rectBottom ){
alert("Context menu request on the "+rect.color+" rectangle.");
}
}
// prevents the usual context from popping up
e.preventDefault()
return(false);
}
Here is working code (no jsFiddle because no right-clicking in X-Domain iframes):
<!doctype html>
<html>
<head>
<link rel="stylesheet" type="text/css" media="all" href="css/reset.css" /> <!-- reset css -->
<script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script>
<style>
body{ background-color: ivory; }
canvas{border:1px solid red;}
</style>
<script>
$(function(){
var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
var canvasOffset=$("#canvas").offset();
var offsetX=canvasOffset.left;
var offsetY=canvasOffset.top;
var rects=[];
rects.push({x:50,y:50,width:50,height:50,color:"red"});
rects.push({x:150,y:100,width:75,height:75,color:"blue"});
ctx.clearRect(0,0,canvas.width,canvas.height);
for(var i=0;i<rects.length;i++){
var rect=rects[i];
ctx.beginPath();
ctx.fillStyle=rect.color;
ctx.rect(rect.x,rect.y,rect.width,rect.height);
ctx.fill();
}
// listen for contextmenu requests
canvas.addEventListener('contextmenu', handleMouseDown, false);
function handleMouseDown(e){
// get mouse position relative to the canvas
var x=parseInt(e.clientX-offsetX);
var y=parseInt(e.clientY-offsetY);
// check each rect for hits
for(var i=0;i<rects.length;i++){
var rect=rects[i];
var rectRight=rect.x+rect.width;
var rectBottom=rect.y+rect.height;
// check each rect for hits
if(x>=rect.x && x<=rectRight && y>=rect.y && y<=rectBottom ){
alert("Context menu request on the "+rect.color+" rectangle.");
}
}
// prevents the usual context from popping up
e.preventDefault()
return(false);
}
}); // end $(function(){});
</script>
</head>
<body>
<canvas id="canvas" width=300 height=300></canvas>
</body>
</html>

How to print a canvas element?

I have a canvas element on my page. I draw an image over it and some data that the user entered. On a press of a button I want to send the canvas to printer, to print it on paper. I tried to use this plug-in: jQuery.printElement, like that:
the button code:
PRINT
'print_voucher()' function:
function print_voucher()
{
$("#canvas_voucher").printElement();
}
canvas_voucher is the ID of my canvas element. It printed the page, but didn't print the canvas. I tried to use it like that as well:
$("#canvas_voucher img").printElement();
But that didn't even start the printer.
So how can I do that? How can I print the content of the canvas?
**EDIT**
Here's the code that creates my canvas and tries to create an image with it:
function create_voucher(visitor_name, visitor_identity_num, unique_number)
{
var canvas = $("#canvas_voucher")[0];
if (canvas.getContext)
{
var ctx = canvas.getContext('2d');
// Draw image
var img = new Image();
img.src = 'https://someurl.com/image.jpg';
img.onload = function(){
ctx.drawImage(img,0,0);
ctx.fillStyle="#CCC";
ctx.font="bold 20px Arial";
ctx.fillText(visitor_name, 750, 270);
ctx.fillText(visitor_identity_num, 750, 295);
ctx.font="bold 25px Arial";
ctx.fillText(unique_number, 620, 325);
}
var voucher = canvas.toDataURL("image/png");
$("#voucher_img").attr("src", voucher);
} else {
alert('You need Safari or Firefox 1.5+ to see this.');
}
}
This will convert the canvas to a .png image URL and open it in a new browser window
The Print Dialog is triggered to let the user print the page.
function print_voucher(){
var win=window.open();
win.document.write("<br><img src='"+canvas.toDataURL()+"'/>");
win.print();
win.location.reload();
}
Here is example code:
<style>
body{ background-color: ivory; }
canvas{border:1px solid red;}
</style>
<script>
$(function(){
var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
ctx.fillStyle="gold";
ctx.strokeStyle="blue";
ctx.lineWidth=5;
ctx.rect(50,50,100,100);
ctx.fill();
ctx.stroke();
function print_voucher(){
var win=window.open();
win.document.write("<br><img src='"+canvas.toDataURL()+"'/>");
win.print();
win.location.reload();
}
$("#printVoucher").click(function(){ print_voucher(); });
}); // end $(function(){});
</script>
</head>
<body>
<canvas id="canvas" width=300 height=300></canvas><br>
<button id="printVoucher">Print</button>
</body>
</html>
Found the problem and fixed it.
Apparently it was a security issue at this line:
img.src = 'https://someurl.com/image.jpg';
Once it was pointing out to a server, it was considered as a potential security threat. So I changed it to:
img.src = 'images/image.jpg';
After that I created a function to make an image from the canvas and called it within the 'img.onload' part:
...
img.onload = function(){
ctx.drawImage(img,0,0);
ctx.fillStyle="#CCC";
ctx.font="bold 20px Arial";
ctx.fillText(visitor_name, 750, 270);
ctx.fillText(visitor_identity_num, 750, 295);
ctx.font="bold 25px Arial";
ctx.fillText(unique_number, 620, 325);
draw_voucher_img();
...
function draw_voucher_img()
{
var canvas = $("#canvas_voucher")[0];
var voucher = canvas.toDataURL();
$("#voucher_img").attr("src", voucher);
}
Now it worked!

Changing the default value of canvas elements color

I have a question related to HTML5 canvas.
I am developing a game that requires the users to draw an image on the canvas.
The tools contain Text and Rectangle tools etc...
The color default value of the Text and Rectangle tools is black. So I have added more colors so the user can change the color of the font and the rectangle.
The problem is that: in the first time of using the tool, when the color is clicked the font's color remains black but if the user uses the text tool again, the font's color changed according to the selected color and the same with the rectangle, it is filled with black color first then when the user draws another rectangle. the color changed from black to the selected color.
How can I change the default value from the beginning???
Edited::
ok her is my code:
<html>
<head>
<meta charset="utf-8">
<style type="text/css">
#clr div{
cursor:pointer;
cursor:hand;
width:20px;
height:20px;
float:left;
margin-right:10px;
}
#clr2 font{
cursor:pointer;
cursor:hand;
margin-top:100px;
margin-right:10px;
}
#clr3 font{
cursor:pointer;
cursor:hand;
margin-top:100px;
margin-right:10px;
}
</style>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js" type="text/javascript" ></script>
<script type="text/javascript">
// Drawing options
var tool;
var tool_default = '';
function drawLine(){
// Get the tool select input.
var tool_select = document.getElementById('dtool');
if (!tool_select) {
alert('Error: failed to get the dtool element!');
return;
}
tool_select.addEventListener('change', ev_tool_change, false);
// Activate the default tool.
if (tools[tool_default]) {
tool = new tools[tool_default]();
tool_select.value = tool_default;
}
// Attach the mousedown, mousemove and mouseup event listeners.
layer3.addEventListener('mousedown', ev_canvas, false);
layer3.addEventListener('mousemove', ev_canvas, false);
layer3.addEventListener('mouseup', ev_canvas, false);
}
// The general-purpose event handler. This function just determines the mouse
// position relative to the canvas element.
function ev_canvas (ev) {
if (ev.layerX || ev.layerX == 0) { // Firefox
ev._x = ev.layerX;
ev._y = ev.layerY;
}
// Call the event handler of the tool.
var func = tool[ev.type];
if (func) {
func(ev);
}
}
// The event handler for any changes made to the tool selector.
function ev_tool_change (ev) {
if (tools[this.value]) {
tool = new tools[this.value]();
}
}
// This object holds the implementation of each drawing tool.
var tools = {};
// The drawing pencil.
//Draw Rectangle
tools.rectangle = function () {
var tool = this;
this.started = false;
this.mousedown = function (ev) {
tool.started = true;
tool.x0 = ev._x;
tool.y0 = ev._y;
context3.fillStyle="";
};
this.mousemove = function (ev) {
if (!tool.started) {
return;
}
var x = Math.min(ev._x, tool.x0),
y = Math.min(ev._y, tool.y0),
w = Math.abs(ev._x - tool.x0),
h = Math.abs(ev._y - tool.y0);
context3.clearRect(0, 0, layer3.width, layer3.height);
if (!w || !h) {
return;
}
$("#clr div").click(function(){
context3.fillStyle = $(this).css("background-color");
});
context3.fillRect(x, y, w, h);
};
this.mouseup = function (ev) {
if (tool.started) {
tool.mousemove(ev);
tool.started = false;
img_update();
}
};
};
<canvas class="canvas3" id="layer3" width="500" height="200" style="border:1px solid"> </canvas>
<p><label> Drawing tool: <select id="dtool" onClick="drawLine()">
<option value="pencil">Pencil</option>
<option value="rectangle">Rectangle</option>
</select></label></p>
<div id="clr">
<p> </p>
<div style="background-color:white;"> </div>
<div style="background-color:red;"> </div>
<div style="background-color:green;"> </div>
<div style="background-color:orange;"> </div>
<div style="background-color:brown;"> </div>
<div style="background-color:#d2232a;"> </div>
</div>
</div>
<script type="text/javascript">
layer3 = document.getElementById("layer3");
context3 = layer3.getContext("2d");
</script>
</body>
</html>
You have to set the fillStyle before you call drawText, and it sounds like you are setting it afterwards.
Edit: In short it is happening because:
$("#clr div").click(function(){
context3.fillStyle = $(this).css("background-color");
});
Is put inside your mousemove. This means that this never gets to be attached until a mouseMove happens.
Instead, put the above code at the top level and not inside of your mousemove