Tutorial on isPointinPath not copying to my computer - javascript

I found this helpful tutorial
http://www.rgraph.net/blog/2013/february/an-example-of-the-html5-canvas-ispointinpath-function.html
i copied it into my own text editor and nothing happens when I open it. I changed it by adding a declaration
<!DOCTYPE html>
<html lang="en">
<head>
<title>exampleMouseOver</title>
</head>
<script>
window.onload = function (e)
{
var canvas = document.getElementById('cvs');
var context = canvas.getContext('2d');
// Draw the rectangle
context.beginPath();
context.rect(50,50,100,100);
context.fill();
context.fillStyle = 'red';
// Draw the circle
context.beginPath();
context.arc(450,175, 50, 0,2 * Math.PI, false);
context.fill();
context.fillStyle = 'green';
// Draw the shape
context.beginPath();
context.moveTo(250,100);
context.lineTo(350,175);
context.lineTo(325,215);
context.lineTo(185,195);
context.fill();
canvas.onmousemove = function (e)
{
var canvas = e.target;
var context = canvas.getContext('2d');
// This gets the mouse coordinates (relative to the canvas)
var mouseXY = RGraph.getMouseXY(e);
var mouseX = mouseXY[0];
var mouseY = mouseXY[1];
// Replay the rectangle path (no need to fill() it) and test it
context.beginPath();
context.rect(50,50,100,100);
if (context.isPointInPath(mouseX, mouseY)) {
canvas.style.cursor = 'pointer';
return;
}
///////////////////////////////////////////////////////////////
// Replay the circle path (no need to fill() it) and test it
context.beginPath();
context.arc(450,175, 50, 0,2 * Math.PI, false);
if (context.isPointInPath(mouseX, mouseY)) {
canvas.style.cursor = 'pointer';
return;
}
///////////////////////////////////////////////////////////////
// Replay the irregular shape path (no need to fill() it) and test it
context.beginPath();
context.moveTo(250,100);
context.lineTo(350,175);
context.lineTo(325,215);
context.lineTo(185,195);
if (context.isPointInPath(mouseX, mouseY)) {
canvas.style.cursor = 'pointer';
return;
}
///////////////////////////////////////////////////////////////
// Return the cursor to the default style
canvas.style.cursor = 'default';
}
}
</script>
</html>

You'll need a body element and a canvas element. Also your script element needs to be inside either your head element or your body element.
The following is what the sample was using, but did not include in their sample code:
<body>
<canvas id="cvs" width="600" height="250" style="border: 1px solid gray; cursor: pointer;">[No canvas support]</canvas>
</body>
Edit: Additionally the code is calling "RGraph.getMouseXY(e)", which is in a library file that you are not referencing. You can either add a reference to that library or get the mouse position yourself.
If you want to use other parts of the RGraph library, for drawing charts, you should add the library. To add the library you should follow the instructions on the RGraph site related to downloading and starting with RGraph (http://www.rgraph.net/docs/starting-with-rgraph.html).
If this was just a sample that happened to do what you wanted to do, you should get the mouse position yourself. You can do this by changing these lines:
var mouseXY = RGraph.getMouseXY(e);
var mouseX = mouseXY[0];
var mouseY = mouseXY[1];
to these:
var mouseX = e.clientX - canvas.getBoundingClientRect().left;
var mouseY = e.clientY - canvas.getBoundingClientRect().top;
This may not be the most robust solution, but it should suffice for your purposes. Essentially you are getting the mouse position in the window, then subtracting the top-left of the canvas in the window, so that you are left with the mouse position in the canvas.

Related

HTML Canvas: ctx.stroke restroke behaviour with transparent colors

I am working on a sketch tool with html canvas.
I am using a common algorithm for this, that uses the mousedown, mousemove, mouseup events.
mousedown
I beginPath(), and moveTo(// the mouse coordinates).
mousemove
I draw lineTo(// the mouse coordinates), and then stoke(// the line to render it)
mouseup
I do nothing, // closePath()
And I noticed that, calling the stroke method without first calling closePath or beginPath, will redraw or restroke all previous paths or lines, which makes them appear thicker than the define color.
without a transparent color its is barely noticeable, but the colors do appear thicker than they should be.
but with color with transparency|alpha e.g. rgba(). The most recent path or line respects the color's transparency, but all previous line due to the redraw, the transparent colored line overlap and that causes previous lines to get thicker in sequence or succession.
is there a way to avoid|prevent this behavior. thank in advance.
sample is below, try drawing really fast!
var cvs = document.querySelector("canvas");
cvs.width = cvs.parentElement.clientWidth;
var colorInput = document.querySelector("input");
var ctx = cvs.getContext("2d");
ctx.strokeStyle = "rgba(0, 0, 0, 0.4)"
ctx.lineWidth = 20;
onDraw(cvs, {
penDown: function(e) {
var x = e.pageX - this.offsetLeft;
var y = e.pageY - this.offsetTop;
ctx.strokeStyle = colorInput.value;
ctx.beginPath();
ctx.moveTo(x, y);
},
penMove: function(e) {
var x = e.pageX - this.offsetLeft;
var y = e.pageY - this.offsetTop;
ctx.lineTo(x, y);
ctx.stroke();
},
penUp: function() {
// ctx.closePath;
}
});
function onDraw(node, drawHandler, beginHandler, endHandler, outOfBoundHandler, sticky) {
var mouseDown = false, mouseOut = false;
if( typeof drawHandler === "object" ) {
var drawEvents = drawHandler;
drawHandler = get(drawEvents.penMove);
beginHandler = get(drawEvents.penDown);
endHandler = get(drawEvents.penUp);
outOfBoundHandler = get(drawEvents.penOff);
sticky = drawEvents.sticky;
}
function get(name) {
return typeof name === "string" ? drawEvents[ name ] : name;
}
node.addEventListener('mousedown', function(e) {
mouseDown = true;
beginHandler&&beginHandler.call(this, e);
});
node.addEventListener('mousemove', function(e) {
mouseDown&&drawHandler&&drawHandler.call(this, e);
});
node.addEventListener('mouseup', function(e) {
mouseDown = false;
endHandler&&endHandler.call(this, e);
});
node.addEventListener('mouseout', function(e) {
mouseDown&&outOfBoundHandler&&outOfBoundHandler.call(this, e);
if( !sticky ) {
mouseDown = false;
}
});
}
.wrapper { border: 1px solid #aaa }
<div class="wrapper">
<canvas border="1" width="600" hieght="400">Canvas is not supported</canvas>
<input type="text" value="rgba(0, 0, 0, 0.3)" placeholder="rgba(#, #, #, #)">
</div>
If no Path argument is passed to stroke and fill methods they will use the path currently being declared with the context's drawing methods.
const ctx = c.getContext('2d');
// starts Path declaration
ctx.moveTo(20, 20);
ctx.lineTo(30, 80);
ctx.stroke(); // first rendering
setTimeout(() => {
ctx.clearRect(0, 0, 300, 150); // even if we clear the canvas
ctx.lineTo(70, 20); // this will continue path declaration
setTimeout(() => {
ctx.stroke(); // and this will draw everything
}, 1000);
}, 1000);
<canvas id="c"></canvas>
The only ways to start a new path declaration (except for the first one) are to either reset the whole context (not good), or to use beginPath method.
const ctx = c.getContext('2d');
// starts Path declaration
ctx.moveTo(20, 20);
ctx.lineTo(30, 80);
ctx.stroke(); // first rendering
setTimeout(() => {
ctx.clearRect(0, 0, 300, 150);
ctx.beginPath(); // start a new Path declaration
ctx.moveTo(30, 80); // we need to move to the previous coords
ctx.lineTo(70, 20); // this will be alone
ctx.stroke(); // and this will draw only the new path
}, 1000);
<canvas id="c"></canvas>
About closePath, it's just a lineTo(last_point_in_current_path_declaration), and doesn't ends a path declaration in no way.
So for your problem, there are two strategies you can adopt :
keep only the last coordinates, and at every mousemove,
ctx.beginPath();
ctx.moveTo(lastX, lastY);
ctx.lineTo(nextX, nextY);
keep all your coordinates in an array and redraw everything every time
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.beginPath();
coords.forEach(pt => ctx.lineTo(pt.x, pt.y));
ctx.stroke();
Personally, I prefer the second one, which allows some undo - redo, and to e.g change your pen's style.

Image in canvas leaves a tiled trail when panned

I am trying to create a pannable image viewer which also allows magnification. If the zoom factor or the image size is such that the image no longer paints over the entire canvas then I wish to have the area of the canvas which does not contain the image painted with a specified background color.
My current implementation allows for zooming and panning but with the unwanted effect that the image leaves a tiled trail after it during a pan operation (much like the cards in windows Solitaire when you win a game). How do I clean up my canvas such that the image does not leave a trail and my background rectangle properly renders in my canvas?
To recreate the unwanted effect set magnification to some level at which you see the dark gray background show and then pan the image with the mouse (mouse down and drag).
Code snippet added below and Plnkr link for those who wish to muck about there.
http://plnkr.co/edit/Cl4T4d13AgPpaDFzhsq1
<!DOCTYPE html>
<html>
<head>
<style>
canvas{
border:solid 5px #333;
}
</style>
</head>
<body>
<button onclick="changeScale(0.10)">+</button>
<button onclick="changeScale(-0.10)">-</button>
<div id="container">
<canvas width="700" height="500" id ="canvas1"></canvas>
</div>
<script>
var canvas = document.getElementById('canvas1');
var context = canvas.getContext("2d");
var imageDimensions ={width:0,height:0};
var photo = new Image();
var isDown = false;
var startCoords = [];
var last = [0, 0];
var windowWidth = canvas.width;
var windowHeight = canvas.height;
var scale=1;
photo.addEventListener('load', eventPhotoLoaded , false);
photo.src = "http://www.html5rocks.com/static/images/cors_server_flowchart.png";
function eventPhotoLoaded(e) {
imageDimensions.width = photo.width;
imageDimensions.height = photo.height;
drawScreen();
}
function changeScale(delta){
scale += delta;
drawScreen();
}
function drawScreen(){
context.fillRect(0,0, windowWidth, windowHeight);
context.fillStyle="#333333";
context.drawImage(photo,0,0,imageDimensions.width*scale,imageDimensions.height*scale);
}
canvas.onmousedown = function(e) {
isDown = true;
startCoords = [
e.offsetX - last[0],
e.offsetY - last[1]
];
};
canvas.onmouseup = function(e) {
isDown = false;
last = [
e.offsetX - startCoords[0], // set last coordinates
e.offsetY - startCoords[1]
];
};
canvas.onmousemove = function(e)
{
if(!isDown) return;
var x = e.offsetX;
var y = e.offsetY;
context.setTransform(1, 0, 0, 1,
x - startCoords[0], y - startCoords[1]);
drawScreen();
}
</script>
</body>
</html>
You need to reset the transform.
Add context.setTransform(1,0,0,1,0,0); just before you clear the canvas and that will fix your problem. It sets the current transform to the default value. Then befor the image is draw set the transform for the image.
UPDATE:
When interacting with user input such as mouse or touch events it should be handled independently of rendering. The rendering will fire only once per frame and make visual changes for any mouse changes that happened during the previous refresh interval. No rendering is done if not needed.
Dont use save and restore if you don't need to.
var canvas = document.getElementById('canvas1');
var ctx = canvas.getContext("2d");
var photo = new Image();
var mouse = {}
mouse.lastY = mouse.lastX = mouse.y = mouse.x = 0;
mouse.down = false;
var changed = true;
var scale = 1;
var imageX = 0;
var imageY = 0;
photo.src = "http://www.html5rocks.com/static/images/cors_server_flowchart.png";
function changeScale(delta){
scale += delta;
changed = true;
}
// Turns mouse button of when moving out to prevent mouse button locking if you have other mouse event handlers.
function mouseEvents(event){ // do it all in one function
if(event.type === "mouseup" || event.type === "mouseout"){
mouse.down = false;
changed = true;
}else
if(event.type === "mousedown"){
mouse.down = true;
}
mouse.x = event.offsetX;
mouse.y = event.offsetY;
if(mouse.down) {
changed = true;
}
}
canvas.addEventListener("mousemove",mouseEvents);
canvas.addEventListener("mouseup",mouseEvents);
canvas.addEventListener("mouseout",mouseEvents);
canvas.addEventListener("mousedown",mouseEvents);
function update(){
requestAnimationFrame(update);
if(photo.complete && changed){
ctx.setTransform(1,0,0,1,0,0);
ctx.fillStyle="#333";
ctx.fillRect(0,0, canvas.width, canvas.height);
if(mouse.down){
imageX += mouse.x - mouse.lastX;
imageY += mouse.y - mouse.lastY;
}
ctx.setTransform(scale, 0, 0, scale, imageX,imageY);
ctx.drawImage(photo,0,0);
changed = false;
}
mouse.lastX = mouse.x
mouse.lastY = mouse.y
}
requestAnimationFrame(update);
canvas{
border:solid 5px #333;
}
<button onclick="changeScale(0.10)">+</button><button onclick="changeScale(-0.10)">-</button>
<canvas width="700" height="500" id ="canvas1"></canvas>
Nice Code ;)
You are seeing the 'tiled' effect in your demonstration because you are painting the scaled image to the canvas on top of itself each time the drawScreen() function is called while dragging. You can rectify this in two simple steps.
First, you need to clear the canvas between calls to drawScreen() and second, you need to use the canvas context.save() and context.restore() methods to cleanly reset the canvas transform matrix between calls to drawScreen().
Given your code as is stands:
Create a function to clear the canvas. e.g.
function clearCanvas() {
context.clearRect(0, 0, canvas.width, canvas.height);
}
In the canavs.onmousemove() function, call clearCanvas() and invoke context.save() before redefining the transform matrix...
canvas.onmousemove = function(e) {
if(!isDown) return;
var x = e.offsetX;
var y = e.offsetY;
/* !!! */
clearCanvas();
context.save();
context.setTransform(
1, 0, 0, 1,
x - startCoords[0], y - startCoords[1]
);
drawScreen();
}
... then conditionally invoke context.restore() at the end of drawScreen() ...
function drawScreen() {
context.fillRect(0,0, windowWidth, windowHeight);
context.fillStyle="#333333";
context.drawImage(photo,0,0,imageDimensions.width*scale,imageDimensions.height*scale);
/* !!! */
if (isDown) context.restore();
}
Additionally, you may want to call clearCanvas() before rescaling the image, and the canvas background could be styled with CSS rather than .fillRect() (in drawScreen()) - which could give a performance gain on low spec devices.
Edited in light of comments from Blindman67 below
See Also
Canvas.context.save : https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/save
Canvas.context.restore : https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/restore
requestAnimationFrame : https://developer.mozilla.org/en-US/docs/Web/API/Window/requestAnimationFrame
Paul Irish, requestAnimationFrame polyfill : http://www.paulirish.com/2011/requestanimationframe-for-smart-animating/
Call context.save to save the transformation matrix before you call context.fillRect.
Then whenever you need to draw your image, call context.restore to restore the matrix.
For example:
function drawScreen(){
context.save();
context.fillStyle="#333333";
context.fillRect(0,0, windowWidth, windowHeight);
context.restore();
context.drawImage(photo,0,0,imageDimensions.width*scale,imageDimensions.height*scale);
}
Also, to further optimize, you only need to set fillStyle once until you change the size of canvas.

Drawing and saving an image as JPEG in HTML Canvas

I am creating an app which allows user to draw a digit(using mouse) in Canvas. When they click on submit, the image should be saved as a JPEG and Clear should Erase the digit drawn in canvas. I am new to HTML5 Canvas. I saw some tutorials which created a canvas, but I am unable to save and clear canvas. Any help would really be appreciated. Thanks.
Here is my HTML:
<div style="padding-bottom: 20px;padding-left: 210px;">
<div class="btn-group" role="group" aria-label="...">
<button type="button" id="save" class="btn btn-default">Submit</button>
<button type="button" id="clear" class="btn btn-default">Clear</button>
</div></div>
</div>
Javascript within Script tag:
var clear = document.getElementById('clear');
clear.addEventListener('click', clearCanvas);
var clearCanvas = function(e) {
ctx.fillStyle = "white";
ctx.fillRect(0, 0, 500, 400);
ctx.clearRect(20, 20, 100, 50);
}
The tutorial you're using fails to mention a few key things:
The canvasInAPerfectWorldline isn't used: you can delete it.
You need jQuery: just add <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.js"></script/> in your <head> section.
You should wrap your javascript in the jQuery boilerplate, to ensure it gets executed after the rest to the document has loaded: $( document ).ready(function() { <your javascript here> });
The canvasWidth and canvasHeight variables are never set: add this line before the variables are used:var canvasWidth = 600; var cavasHeight = 400;
The variables mouseX and mouseY are never used: you can delete them (but take a look at the onClick() function two lines later to see what they would have been used for).
The finished result should look like this:
<!DOCTYPE html>
<html>
<head>
<title>HTML5 Create HTML5 Canvas JavaScript Drawing App Example</title>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.js"></script>
<style>canvas { border: 1px solid #ccc; }</style>
<script type="text/javascript">
$( document ).ready(function() {
var canvasWidth = 600; var cavasHeight = 400;
var canvasDiv = document.getElementById('canvasDiv');
canvas = document.createElement('canvas');
canvas.setAttribute('width', canvasWidth);
canvas.setAttribute('height', cavasHeight);
canvas.setAttribute('id', 'canvas');
canvasDiv.appendChild(canvas);
if(typeof G_vmlCanvasManager != 'undefined') {
canvas = G_vmlCanvasManager.initElement(canvas);
}
context = canvas.getContext("2d");
$('#canvas').mousedown(function(e){
paint = true;
addClick(e.pageX - this.offsetLeft, e.pageY - this.offsetTop);
redraw();
});
$('#canvas').mousemove(function(e){
if(paint){
addClick(e.pageX - this.offsetLeft, e.pageY - this.offsetTop, true);
redraw();
}
});
$('#canvas').mouseup(function(e){
paint = false;
});
$('#canvas').mouseleave(function(e){
paint = false;
});
$('#clear').click(function(){
clickX.length = 0;
clickY.length = 0;
clickDrag.length = 0;
redraw();
});
var clickX = new Array();
var clickY = new Array();
var clickDrag = new Array();
var paint;
function addClick(x, y, dragging)
{
clickX.push(x);
clickY.push(y);
clickDrag.push(dragging);
}
function redraw(){
context.clearRect(0, 0, context.canvas.width, context.canvas.height); // Clears the canvas
context.strokeStyle = "#df4b26";
context.lineJoin = "round";
context.lineWidth = 5;
for(var i=0; i < clickX.length; i++) {
context.beginPath();
if(clickDrag[i] && i){
context.moveTo(clickX[i-1], clickY[i-1]);
}else{
context.moveTo(clickX[i]-1, clickY[i]);
}
context.lineTo(clickX[i], clickY[i]);
context.closePath();
context.stroke();
}
}
});
</script>
</head>
<body>
<div id="canvasDiv"></div>
</body>
</html>
As for saving your canvas as a JPEG, that's more complicated. As markE has pointed out, there's a related question here which shows one way to do it.
EDIT: Adding a 'Clear' button:
Your 'drawing' is really just a series of pen movements stored in the clickX, clickY and clickDrag arrays. Each time redraw() is called, the drawing gets recreated from the arrays. So just drawing a white rectangle will only clear the screen until the next redraw(). Instead, you can clear the arrays by adding this to your javascript:
$('#clear').click(function(){
clickX.length = 0;
clickY.length = 0;
clickDrag.length = 0;
redraw();
});
(BTW by deleting the details of your original question, you make it hard for the next person to understand the context of the answers. You should either (a) add to your original question, or (b) ask a new question. Also you can upvote and/or accept any answers you find helpful. Thanks)
I think that's a duplicated question. See here
Can I get image from canvas element and use it in img src tag?
var image = new Image();
image.id = "pic"
image.src = canvas.toDataURL();
document.getElementById('image_for_crop').appendChild(image);

Canvas and events

Please help me to understand the events of the canvas.
Take for example two of the square. Each has its own area where you need to process such events:
Hover the square fills it with colour.
Click invokes filling the square third color and displays in a separate block, for example, the ID of the square.
Accordingly, it is possible to work with only one square. Click on the second square will reset the first square and output data from the second.
While moving the mouse in the area of one of the squares near the mouse, a pop-up window that displays the ID of the square.
And how can I make a link to a separate square? That is, to the user clicks a link that invokes the event, similar to a click on a separate square.
HTML code
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<script type="text/javascript" src="scripts/canvas.js"></script>
<script>
window.onload = function()
{
drawCanvas('mainCanvas');
};
</script>
</head>
<body style="margin: 0px;">
<canvas id="mainCanvas" width="300" height="200"></canvas>
<aside>ID of the square</aside>
</body>
</html>
JS code
function makeRect(x, y, w, h)
{
return { x: x, y: y, w: w, h: h };
}
function drawCanvas(canvasId)
{
//// General Declarations
var canvas = document.getElementById(canvasId);
var context = canvas.getContext('2d');
//// Color Declarations
var blackColor = 'rgba(0, 0, 0, 1)';
var whiteColor = 'rgba(255, 255, 255, 1)';
//// Frames
var frameOne = makeRect(64, 70, 50, 50);
var frameTwo = makeRect(194, 70, 50, 50);
//// RectangleOne Drawing
context.beginPath();
context.rect(frameOne.x, frameOne.y, 50, 50);
context.fillStyle = whiteColor;
context.fill();
context.strokeStyle = blackColor;
context.lineWidth = 1;
context.stroke();
//// RectangleTwo Drawing
context.beginPath();
context.rect(frameTwo.x, frameTwo.y, 50, 50);
context.fillStyle = whiteColor;
context.fill();
context.strokeStyle = blackColor;
context.lineWidth = 1;
context.stroke();
}
You ask a really broad question!
This will get you started:
About canvas rectangles
When you draw a rect on the canvas it becomes just “painted pixels” (like a painting of a rectangle on an artists canvas).
Nothing about the rect is “remembered” by canvas.
This means you can’t hit-test the rect to see if your mouse is hovering over that rect. The canvas doesn’t know anything about your rect.
Keeping track of rectangles
You must keep track of each rect’s properties yourself (x-coordinate, y-coordinate, width, height, color).
A convienient way to do this is creating a javascript object with the rect’s properties:
var rect1 = { x:30, y:30, width:50, height:25, color:"blue" };
Then use this rect1 object to draw the rect on your canvas
context.fillStyle=rect1.color;
context.fillRect( rect1.x, rect1.y, rect1.width, rect1.height );
Now you can always refer to rect1 to get the properties of your rectangle.
Mouse events
The canvas mouse events always relate to the canvas element itself, never to a rect drawn on the canvas.
Here’s how to listen to the mouse events on canvas:
// use jQuery to ask the browser to call `handleMouseMove` whenever the mouse is moved
$("#canvas").mousemove(function(e){handleMouseMove(e);});
// this is called every time your mouse moves
function handleMouseMove(e){
// get the mouses current X,Y position
// Note: offsetX/offsetY -- you must adjust for the offset of the canvas relative to the web page
mouseX=parseInt(e.clientX-offsetX);
mouseY=parseInt(e.clientY-offsetY);
}
Testing if the mouse is inside the rect
Remember that canvas knows nothing about your rect1, so use the rect1 object to “hit-test” whether the mouse is inside rect1:
if(
mouseX>=rect1.x &&
mouseX<=rect1.x+rect1.width &&
mouseY>=rect1.y &&
mouseY<=rect1.y+rect1.height
){
// the mouse is inside rect1
ctx.fillStyle="red";
ctx.fillRect(rect1.x,rect1.y,rect1.width,rect1.height);
}else{
// the mouse is not inside rect1
ctx.fillStyle=rect1.color;
ctx.fillRect(rect1.x,rect1.y,rect1.width,rect1.height);
}
This introduction should get you started coding…experiment for yourself!
Here’s a working demo: http://jsfiddle.net/m1erickson/tPjWX/
<!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 $canvas=$("#canvas");
var canvasOffset=$canvas.offset();
var offsetX=canvasOffset.left;
var offsetY=canvasOffset.top;
var rect1 = { x:30, y:30, width:50, height:25, color:"blue" };
ctx.fillStyle=rect1.color;
ctx.fillRect(rect1.x,rect1.y,rect1.width,rect1.height);
function handleMouseMove(e){
mouseX=parseInt(e.clientX-offsetX);
mouseY=parseInt(e.clientY-offsetY);
if(
mouseX>=rect1.x &&
mouseX<=rect1.x+rect1.width &&
mouseY>=rect1.y &&
mouseY<=rect1.y+rect1.height
){
ctx.fillStyle="red";
ctx.fillRect(rect1.x,rect1.y,rect1.width,rect1.height);
}else{
ctx.fillStyle=rect1.color;
ctx.fillRect(rect1.x,rect1.y,rect1.width,rect1.height);
}
}
$("#canvas").mousemove(function(e){handleMouseMove(e);});
}); // end $(function(){});
</script>
</head>
<body>
<canvas id="canvas" width=300 height=300></canvas>
</body>
</html>
Canvas is only an element.
You can catch event for all canvas not for squares, circle, line...
But you can hold the position of square , line, circle and check "if ( mouse's position in square position) and redraw canvas
Personally, you can try to use SVG and you can catch the events for individual element.

scale mouse coordinates on document relative to HTML5 canvas

I have a HTML5 canvas of a certain size on the page
<canvas id="canvas" width="200" height="100" style="border:1px solid #000000;">
Right now, the canvas is painted when the mouse is dragged over it (i.e. you click first(not necessarily inside the canvas) then start dragging the mouse over it without releasing) Script below;
$(function () {
var c = document.getElementById("canvas");
var context = c.getContext("2d");
var clickX = new Array();
var clickY = new Array();
var clickDrag = new Array();
var paint;
var $canvas=$("#canvas");
$(this).mousedown(function (e) {
paint = true;
addClick(e.pageX - $canvas[0].offsetLeft, e.pageY - $canvas[0].offsetTop);
redraw();
});
$(this).mousemove(function (e) {
if (paint) {
addClick(e.pageX - $canvas[0].offsetLeft, e.pageY - $canvas[0].offsetTop, true);
redraw();
}
});
$(this).mouseup(function (e) {
paint = false;
});
$(this).mouseleave(function (e) {
paint = false;
});
function addClick(x, y, dragging) {
clickX.push(x);
clickY.push(y);
clickDrag.push(dragging);
}
function redraw() {
context.clearRect(0, 0, context.canvas.width, context.canvas.height); // Clears the canvas
context.strokeStyle = "#000000";
context.lineJoin = "round";
context.lineWidth = 2;
for (var i = 0; i < clickX.length; i++) {
context.beginPath();
if (clickDrag[i] && i) {
context.moveTo(clickX[i - 1], clickY[i - 1]);
} else {
context.moveTo(clickX[i] - 1, clickY[i]);
}
context.lineTo(clickX[i], clickY[i]);
context.closePath();
context.stroke();
}
}
});
What I need now is a way to scale all the mouse coordinates on document during the document's mouse events to the relative coordinates inside the canvas.
so that no matter wherever you drag the mouse on the document it is drawn inside the canvas (in relatively small size of course). Any Idea how to achieve this?
http://jsfiddle.net/umwc5/3/
Why I need this?
It is for a signature application, When a user scribbles the signature using a tablet on a page(without seeing the page!) the entire signature is to be registered in a small canvas.
Update
The final working fiddle
The most important thing you were missing here was to multiply by the canvas/screen ratio.
First calculate the ratio:
var docToCanv = Math.min($canvas[0].width / $('body').width(), $canvas[0].height/$('body').height());
Then use it like this:
addClick(e.pageX*docToCanv, e.pageY*docToCanv);
Depending on the additional behavior you want, you may need to adjust the location a bit, but this should get you past the current issue you are having.
Demo

Categories

Resources