HTML Canvas z-index on click - javascript

HTML5 canvas, on click button z-index canvas overlay.
Default, Red big circle over overlay and and skyblue circles behind the overlay. On click 'button' skyblue circle should come over overlay and big circle should go behind.
Fiddle Demo

Put your draw-all-orbits and draw-all-bodies code in reusable functions
function drawAllOrbits(){
ctx.strokeStyle='black';
for(var i=0;i<orbits.length;i++){
drawOrbit(orbits[i]);
}
}
function drawAllBodies(){
for(var i=0;i<circles.length;i++){
drawOrbitingCircle(circles[i]);
}
}
Give your button an id
<button id='theButton'>Click</button>
Listen for click events on the button.
$('#theButton').on('click',function(){ ... });
When clicked, clear the canvas and redraw the scene in your desired order.
$('#theButton').on('click',function(){
ctx.clearRect(0,0,cw,ch);
circle();
ovarlay();
drawAllOrbits();
drawAllBodies();
});
Example code and a Demo:
// vars for canvas
var canvas= document.getElementById('canvas'),
ctx= canvas.getContext('2d'),
cw=canvas.width,
ch=canvas.height,
cx=cw/2,
cy=ch/2;
// vars for orbits & circle-bodies
var circleRadius=12;
var orbits=[80,130];
var circleCountByOrbit=[5,8];
var circles=[];
// flag to indicate which scene to display
var highlightTomato=true;
// calc semi-random orbiting bodies
for(var o=0;o<orbits.length;o++){
var count=circleCountByOrbit[o];
var sweep=Math.PI*2/count;
for(var c=0;c<count;c++){
var midAngle=(sweep*c)+sweep/2;
var randomOffset=Math.random()*0.50-1;
var angle=midAngle+sweep*randomOffset;
circles.push({orbitIndex:o, angle:angle});
}
}
// draw the initial scene
drawHighlightedTomato();
// listen for button click and toggle the scene
$('#theButton').on('click',function(){
ctx.clearRect(0,0,cw,ch);
highlightTomato=!highlightTomato;
if(highlightTomato){
drawHighlightedTomato();
}else{
drawHighlightedBodies();
}
});
///////////////////////////////
// functions to draw scenes
///////////////////////////////
function drawHighlightedTomato(){
drawAllOrbits();
drawAllBodies();
ovarlay();
circle();
}
function drawHighlightedBodies(){
circle();
ovarlay();
drawAllOrbits();
drawAllBodies();
}
function drawOrbit(radius){
ctx.beginPath();
ctx.arc(cx,cy,radius,0,Math.PI*2);
ctx.stroke();
}
function drawOrbitingCircle(circle){
var x=cx+orbits[circle.orbitIndex]*Math.cos(circle.angle);
var y=cy+orbits[circle.orbitIndex]*Math.sin(circle.angle);
ctx.beginPath();
ctx.arc(x,y,circleRadius,0,Math.PI*2);
ctx.fillStyle='#1bb0e7';
ctx.fill();
ctx.strokeStyle='white';
ctx.stroke();
}
function drawAllOrbits(){
ctx.strokeStyle='black';
for(var i=0;i<orbits.length;i++){
drawOrbit(orbits[i]);
}
}
function drawAllBodies(){
for(var i=0;i<circles.length;i++){
drawOrbitingCircle(circles[i]);
}
}
function circle(place){
ctx.beginPath();
ctx.arc(cx,cy,40,0,100);
ctx.fillStyle='tomato';
ctx.fill();
}
function ovarlay(backgroundOverlay){
ctx.beginPath();
ctx.rect(0, 0, cw, ch);
ctx.fillStyle='rgba(0,0,0,0.8)';
ctx.fill();
//ctx.zindex= 1;
}
body{ background-color:white; }
#canvas{border:1px solid red; margin:0 auto; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<button id=theButton>Toggle</button><br>
<canvas id="canvas" width="300" height="300"></canvas>

Related

Making different figures on canvas html5

I have a canvas but I don't know how to create other figure in the same canvas which overlay it, I have 2 buttons, one to puts images and then link it and make a figure and other to puts another image but in a different figure.
For example you have the button "a" and button "b". The button "a" puts images and make the figure linking the images. Now you want to start a new figure, you use the button "b", puts a image, and when you back to button "a" it must link the new image that buttons "b" has put before. I don't know If I'm explaining well.
I'll try to pass a variable to compare if you are using one button or another to use the same function to draw. the variable is nF, if nF=0 => button "a" if nF=1=>button "b"
Here is my code
function position(year, mon) { //that function puts the images in the html
$('#' + year + ' .' + mon).prepend('<img class="black_point" src="./images/circle.png"/>');
}
function draw(nF) {
var fN = nF;
var table = document.getElementById("table");
var images = table.getElementsByTagName("img");
var canvas = document.getElementById("miCanvas");
var ctx = canvas.getContext("2d");
var x, y; // Remember coordinates
canvas.width = table.offsetWidth;
canvas.height = table.offsetHeight;
function connect(image, index) { //this function link the images
var tabBcr = table.getBoundingClientRect();
var imgBcr = image.getBoundingClientRect();
x = imgBcr.left + (imgBcr.width / 2) - tabBcr.left;
y = imgBcr.top + (imgBcr.height / 2) - tabBcr.top;
index === 0 ? ctx.moveTo(x, y) : ctx.lineTo(x, y);
ctx.save(); //save the state I think
}
// new path here
ctx.beginPath();
for (var i = 0; i < images.length; i++) {
connect(images[i], i); // provide index so we can sep. move/line
}
if (fN == 1) {//This doesn't work :(
ctx.fillStyle = "orange";
ctx.globalCompositeOperation = "source-over";
ctx.fill();
cxt.restore();
} else {
// then at the end:
ctx.fill();
cxt.restore();
}
}
Since the original description in your question differs greatly from your newly added images, I offer this code as a learning starting point without explanation:
var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
var cw=canvas.width;
var ch=canvas.height;
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(); }
ctx.lineWidth=2;
var colors=['green','blue','gold','cyan'];
var figures=[];
var selectedFigure=-1;
var circles=[];
var selectedCircle=-1;
var connectors=[];
addFigure();
$('#new').attr('disabled',true);
$("#canvas").mousedown(function(e){handleMouseDown(e);});
$('#new').click(function(){
addFigure();
});
///// functions
function addFigure(){
figures.push({
circleCount:0,
color:randomColor(),
lastCX:0,
lastCY:0
});
selectedFigure=figures.length-1;
}
function addCircle(mx,my){
var figure=figures[selectedFigure];
var circle={
id:circles.length,
cx:mx,
cy:my,
radius:15,
figure:selectedFigure,
color:figure.color,
};
circles.push(circle);
if(figure.circleCount>0){
var connector={
figure:selectedFigure,
x0:figure.lastCX,
y0:figure.lastCY,
x1:mx,
y1:my,
}
connectors.push(connector);
}
figure.lastCX=mx;
figure.lastCY=my;
figure.circleCount++;
selectedCircle=circle.id;
$('#new').attr('disabled',false);
}
function drawAll(){
ctx.clearRect(0,0,cw,ch);
for(var i=0;i<connectors.length;i++){
drawConnector(connectors[i]);
}
for(var i=0;i<circles.length;i++){
drawCircle(circles[i]);
}
}
function drawCircle(circle){
var highlighted=(circle.figure==selectedFigure);
ctx.strokeStyle=(highlighted)?'red':'black';
ctx.lineWidth=(circle.id==selectedCircle)?6:2;
ctx.beginPath();
ctx.arc(circle.cx,circle.cy,circle.radius,0,Math.PI*2);
ctx.closePath();
ctx.fillStyle=circle.color;
ctx.fill();
ctx.stroke();
ctx.lineWidth=2;
}
function drawConnector(connector){
var highlighted=(connector.figure==selectedFigure);
ctx.strokeStyle=(highlighted)?'red':'lightgray';
ctx.beginPath();
ctx.moveTo(connector.x0,connector.y0);
ctx.lineTo(connector.x1,connector.y1);
ctx.stroke();
}
function handleMouseDown(e){
// tell the browser we're handling this event
e.preventDefault();
e.stopPropagation();
if(selectedFigure<0){return;}
var mouseX=parseInt(e.clientX-offsetX);
var mouseY=parseInt(e.clientY-offsetY);
var wasCircleClicked=false;;
for(var i=0;i<circles.length;i++){
var c=circles[i];
var dx=mouseX-c.cx;
var dy=mouseY-c.cy;
if(dx*dx+dy*dy<=c.radius*c.radius){
selectedFigure=c.figure;
selectedCircle=i;
var figure=figures[selectedFigure];
figure.lastCX=c.cx;
figure.lastCY=c.cy;
wasCircleClicked=true;
break;
}
}
if(!wasCircleClicked){
addCircle(mouseX,mouseY);
}
drawAll();
}
function randomColor(){
if(colors.length>0){
var color=colors[0];
colors.splice(0,1);
return(color);
}else{
return('#'+Math.floor(Math.random()*16777215).toString(16));
}
}
body{ background-color: white; }
#canvas{border:1px solid red; margin:0 auto; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<h4>Click on empty area to add a circle to the currently selected figure.<br><br>Click on a circle to select its figure.<br>Selected figures have a red stroke.<br>New circles will be connected to the last-clicked circle.</h4>
<button id=new>Add new figure</button><br>
<canvas id="canvas" width=400 height=300></canvas>
Here's a framework for displaying the people of different families.
var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
var cw=canvas.width;
var ch=canvas.height;
function reOffset(){
var BB=canvas.getBoundingClientRect();
offsetX=BB.left;
offsetY=BB.top;
}
var offsetX,offsetY;
reOffset();
window.onscroll=function(e){ reOffset(); }
// vars
var selectedFamily=0;
var nextFamily=0;
var families=[];
// set listeners
$("#canvas").mousedown(function(e){handleMouseDown(e);});
$(document).on('change','.fam',function(){
selectedFamily=this.value;
$('#focusFamily').text('Click canvas to add person to family#'+selectedFamily);
draw();
});
$('#addfamily').click(function(){ addFamily(); });
// add a first family
addFamily();
// functions
function addFamily(){
families.push({id:nextFamily,people:[]});
var id=nextFamily;
var input=$('<input type=radio />');
input.prop({
'value':nextFamily,
'id':'fam'+nextFamily,
'name':'fams',
'class':'fam',
'checked':'checked',
});
var label=$('<label>',{
'for':'fam'+nextFamily,
'html':'Work on Family#'+nextFamily,
});
$('#family').append('<br>').append(input).append(label);
selectedFamily=nextFamily;
nextFamily++;
draw();
}
function handleMouseDown(e){
// tell the browser we're handling this event
e.preventDefault();
e.stopPropagation();
mx=parseInt(e.clientX-offsetX);
my=parseInt(e.clientY-offsetY);
families[selectedFamily].people.push({x:mx,y:my});
draw();
}
function draw(){
ctx.clearRect(0,0,cw,ch);
var people=families[selectedFamily].people;
for(var i=0;i<people.length;i++){
var person=people[i];
ctx.beginPath();
ctx.arc(person.x,person.y,15,0,Math.PI*2);
ctx.closePath();
ctx.fill();
ctx.stroke()
}
}
body{ background-color: ivory; }
#container{
display:inline-block;
vertical-align:top;
border:1px solid blue;
padding:10px;
}
#canvas{border:1px solid red;}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<br>
<h4 id=focusFamily>Click canvas to add person to family#0</h4>
<canvas id="canvas" width=300 height=300></canvas>
<div id=container>
<button id=addfamily>Add Family</button>
<div id=family></div>
</div>

Stop a moving image in HTML5 Canvas

Im pretty new to the canvas element in HTML5.
What i want to do is move an image from the right hand side of the screen to the left, once it reaches the left i want it to begin again from the right hand side. I only want it to do this maybe 2/3 times and then stop.
I tried to add in a for loop so that it would limit the iterations but this was unsuccessful.
Any help at all would be appreciated.
Heres my code:
<canvas id="myCanvas" width="600" height="400"></canvas>
<script>
window.addEventListener('load', function () {
var
img = new Image,
ctx = document.getElementById('myCanvas').getContext('2d');
img.src = 'pies.png';
img.addEventListener('load', function () {
var interval = setInterval(function() {
var x = 650, y = 194;
return function () {
ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
ctx.drawImage(img, x, y);
x -= 1;
if (x < -500) {
x = 650;
}
};
}(), 1000/40);
}, false);
}, false);
</script>
One way is to specify a maximum number of leftward moves:
// allow leftward moves = 2 1/2 time the canvas width
// (plus an allowance for the image width)
var maxMoves = (canvas.width+image.width) *2.5;
Then just countdown maxMoves until zero. At zero, stop your animation:
var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
var cw=canvas.width;
var ch=canvas.height;
ctx.fillStyle='skyblue';
var currentX=cw;
var delay=16; // 16ms between moves
var continueAnimating=true;
var nextMoveTime,maxMoves;
var img=new Image();
img.onload=start;
img.src="https://dl.dropboxusercontent.com/u/139992952/multple/sun.png";
function start(){
maxMoves=(cw+img.width)*2.5;
nextMoveTime=performance.now();
requestAnimationFrame(animate);
}
function animate(currentTime){
if(continueAnimating){ requestAnimationFrame(animate); }
if(currentTime<nextMoveTime){return;}
nextMoveTime=currentTime+delay;
ctx.fillRect(0,0,cw,ch);
ctx.drawImage(img,currentX,50);
if(--currentX<-img.width){ currentX=cw; }
if(--maxMoves<0){continueAnimating=false;}
}
body{ background-color: ivory; padding:10px; }
#canvas{border:1px solid red;}
<p>Stop animating after 2 1/2 "sunrises"</p>
<canvas id="canvas" width=300 height=300></canvas>

faster method of copying image data

i have the following script
// copy image data to secondary canvas
var pixelData = contextSource.getImageData(x - (lineWidth/2), y - (lineWidth/2), lineWidth, lineWidth);
var tmpCanvas = document.createElement('canvas');
tmpCanvas.width = tmpCanvas.height = lineWidth;
var tmpContext = tmpCanvas.getContext('2d');
tmpContext.putImageData(pixelData, 0, 0);
contextDest.save();
contextDest.arc(x, y, (lineWidth/2), 0, 2*Math.PI);
contextDest.clip();
contextDest.drawImage(tmpCanvas, x - (lineWidth/2), y - (lineWidth/2));
contextDest.restore();
the script is sampling image data from canvas source when mouse is moving over the source, then copy it to destination. the script is working good, but a bit slow. here is the result when i move the mouse pointer a bit faster.
is there any faster method than mine? please help
#Banana has a good point.
Instead of drawing just the mouse positions, try connecting the positions into a single continuous line..
If you want the rounded effect in your illustration, you can set:
context.lineCap='round';
context.lineJoin='round';
As to masking faster...
A much faster way of masking your image is to:
draw your single line on the second canvas.
Use compositing to make all new draws be visible only where existing pixels are opaque. This compositing is 'source-in' and is set using: context.globalCompositeOperation='source-in'
Draw your image onto the second canvas. The image will show only where the line was.
Using compositing is much faster because compositing is hardware accelerated and is optimized by the browser.
That compositing code might look like this:
function draw(){
// clear the second canvas
ctx1.clearRect(0,0,cw,ch);
// draw your continuous line
ctx1.beginPath();
ctx1.moveTo(points[0].x,points[0].y);
for(var i=1;i<points.length;i++){
p=points[i];
ctx1.lineTo(p.x,p.y);
}
ctx1.stroke();
// set compositing so new draws only appear in
// existing opaque pixels
ctx1.globalCompositeOperation='source-in';
// draw the image
// the image will only be visible in the exising line
ctx1.drawImage(img,0,0);
// be tidy! return compositing to its default mode
ctx1.globalCompositeOperation='source-over';
}
Here's an example and Demo:
var canvas1=document.getElementById("canvas1");
var ctx1=canvas1.getContext("2d");
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 scrollX=$canvas.scrollLeft();
var scrollY=$canvas.scrollTop();
var isDown=false;
var startX;
var startY;
var points=[];
var cw,ch;
var img=new Image();
img.onload=start;
img.src="https://dl.dropboxusercontent.com/u/139992952/stackoverflow/tempHouse%201.jpg";
function start(){
cw=canvas.width=canvas1.width=img.width;
ch=canvas.height=canvas1.height=img.height;
ctx1.lineCap = "round";
ctx1.lineJoin = "round";
ctx1.lineWidth=20;
ctx.drawImage(img,0,0);
$("#canvas").mousedown(function(e){handleMouseDown(e);});
$("#canvas").mousemove(function(e){handleMouseMove(e);});
$("#canvas").mouseup(function(e){handleMouseUp(e);});
$("#canvas").mouseout(function(e){handleMouseOut(e);});
}
function draw(){
// clear the second canvas
ctx1.clearRect(0,0,cw,ch);
// draw your continuous line
ctx1.beginPath();
ctx1.moveTo(points[0].x,points[0].y);
for(var i=1;i<points.length;i++){
p=points[i];
ctx1.lineTo(p.x,p.y);
}
ctx1.stroke();
// set compositing so new draws only appear in
// existing opaque pixels
ctx1.globalCompositeOperation='source-in';
// draw the image
// the image will only be visible in the exising line
ctx1.drawImage(img,0,0);
// be tidy! return compositing to its default mode
ctx1.globalCompositeOperation='source-over';
}
function handleMouseDown(e){
e.preventDefault();
e.stopPropagation();
mouseX=parseInt(e.clientX-offsetX);
mouseY=parseInt(e.clientY-offsetY);
points.length=0;
points.push({x:mouseX,y:mouseY});
isDown=true;
}
function handleMouseUp(e){
e.preventDefault();
e.stopPropagation();
isDown=false;
draw();
}
function handleMouseOut(e){
e.preventDefault();
e.stopPropagation();
mouseX=parseInt(e.clientX-offsetX);
mouseY=parseInt(e.clientY-offsetY);
points.push({x:mouseX,y:mouseY});
isDown=false;
draw();
}
function handleMouseMove(e){
if(!isDown){return;}
e.preventDefault();
e.stopPropagation();
mouseX=parseInt(e.clientX-offsetX);
mouseY=parseInt(e.clientY-offsetY);
points.push({x:mouseX,y:mouseY});
draw();
}
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>
<canvas id="canvas" width=300 height=300></canvas><br>
<canvas id="canvas1" width=300 height=300></canvas>

Moving canvas shapes with mouse

After pressing a button, I'd like to draw a circle at the tip of the mouse pointer on a canvas and then place it when the user clicks again. Here's what I've got so far:
$("#button").click(function(e){
var canvas = document.getElementById('MyCanvas');
var context = canvas.getContext('2d');
canvas.addEventListener('mousemove', function(evt) {
var mousePos = getMousePos(canvas, evt);
var message = 'Mouse position: ' + mousePos.x + ',' + mousePos.y;
console.log(message);
var nodehandle = document.getElementById('circle');
if(mousePos.x && mousePos.y) {
nodehandle.x = mousePos.x;
nodehandle.y = mousePos.y;
flag = 1;
}
}, false);
});
function getMousePos(canvas, evt) {
var rect = canvas.getBoundingClientRect();
return {
x: evt.clientX - rect.left,
y: evt.clientY - rect.top
};
}
My problem is that when I draw a circle like this:
function drawCircle(mouseX, mouseY){
var c = document.getElementById("grid");
var ctx = c.getContext("2d");
ctx.beginPath();
ctx.arc(95,50,5,0,2*Math.PI);
ctx.stroke();
}
I don't know how to select that circle (the getElementById('circle') returns null even if I add ctx.id='circle' to the drawCircle function). I'm also going to need to erase and redraw the circle each time the mouse moves, and I'm sure there's a nice way to do that but I'm not aware of it.
Anything you draw on the canvas--like circles, are just like dried paint on the canvas.
Your circles cannot be selected or moved like html elements.
To move a circle you must clear the canvas and redraw the circle at a different location.
It's convenient to store info about the circle in an object.
var circle1 = { centerX:100, centerY=100, radius=20 }
And you can draw circle1 using that info:
ctx.beginPath();
ctx.arc(circle1.centerX, circle1.centerY, circle1.radius, 0,Math.PI*2);
ctx.closePath();
ctx.fill();
For more than 1 circle you can create a circles array and put each circle object into that array
var circles=[];
circles.push(circle1);
Then to "move" a circle, just change the object's centerX/centerY to the mouse position and redraw all the circles on the canvas.
circle1.centerX=mouseX;
circle1.centerY=mouseY;
// Clear the canvas and redraw all circles
// The "moved" circle will be redrawn at its new position
function drawAll(){
ctx.clearRect(0,0,canvas.width,canvas.height);
for(var i=0;i<circles.length;i++){
var c=circles[i];
ctx.beginPath();
ctx.arc(c.centerX,c.centerY,c.radius,0,Math.PI*2);
ctx.closePath();
ctx.fillStyle=c.color;
ctx.fill();
}
}
You can use Html radio buttons to determine which action a mouse-click will do:
Create a new circle at the mouse position, or
Select the circle under the mouse position, or
"Move" the currently selected circle
Here's example code and a Demo: http://jsfiddle.net/m1erickson/CEB7T/
<!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(){
// get references to the canvas and its context
var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
var $canvas=$("#canvas");
// get the canvas position on the page
// used to get mouse position
var canvasOffset=$canvas.offset();
var offsetX=canvasOffset.left;
var offsetY=canvasOffset.top;
var scrollX=$canvas.scrollLeft();
var scrollY=$canvas.scrollTop();
ctx.lineWidth=3;
// save info about each circle in an object
var circles=[];
var selectedCircle=-1;
// the html radio buttons indicating what action to do upon mousedown
var $create=$("#rCreate")[0];
var $select=$("#rSelect")[0];
var $move=$("#rMove")[0];
// draw all circles[]
function drawAll(){
ctx.clearRect(0,0,canvas.width,canvas.height);
for(var i=0;i<circles.length;i++){
var c=circles[i];
ctx.beginPath();
ctx.arc(c.cx,c.cy,c.radius,0,Math.PI*2);
ctx.closePath();
ctx.fillStyle=c.color;
ctx.fill();
// if this is the selected circle, highlight it
if(selectedCircle==i){
ctx.strokeStyle="red";
ctx.stroke();
}
}
}
function handleMouseDown(e){
e.preventDefault();
mouseX=parseInt(e.clientX-offsetX);
mouseY=parseInt(e.clientY-offsetY);
if($create.checked){
// create a new circle a the mouse position and select it
circles.push({cx:mouseX,cy:mouseY,radius:10,color:randomColor()});
selectedCircle=circles.length-1;
}
if($select.checked){
// unselect any selected circle
selectedCircle=-1;
// iterate circles[] and select a circle under the mouse
for(var i=0;i<circles.length;i++){
var c=circles[i];
var dx=mouseX-c.cx;
var dy=mouseY-c.cy;
var rr=c.radius*c.radius;
if(dx*dx+dy*dy<rr){ selectedCircle=i; }
}
}
if($move.checked && selectedCircle>=0){
// move the selected circle to the mouse position
var c=circles[selectedCircle];
c.cx=mouseX;
c.cy=mouseY;
}
// redraw all circles
drawAll();
}
// return a random color
function randomColor(){
return('#'+Math.floor(Math.random()*16777215).toString(16));
}
// handle mousedown events
$("#canvas").mousedown(function(e){handleMouseDown(e);});
}); // end $(function(){});
</script>
</head>
<body>
<input type="radio" name="grp1" id="rCreate" checked>Click will create a new circle.<br>
<input type="radio" name="grp1" id="rSelect">Click will select an existing circle.<br>
<input type="radio" name="grp1" id="rMove">Click will move selected circle.<br>
<canvas id="canvas" width=300 height=300></canvas>
</body>
</html>

undo the selected shape on the canvas

I would like to a particular shape on the canvas.
I have implemented a canvas on which we can draw shapes like rectangle, circle, line, ellipse and so on using mouse events.
I have created a drop down list with all the shapes that I am drawing on the canvas.
The drop down list consists of shapes like circle, rectangle, parallelogram, ellipse, circle...
Now what I want is, for example, think that I have drawn 2 rectangles and 2 circles. When I select circle shape from the drop down list and click undo button it should undo only the circles and if I select the rectangle shape from the drop down list and click on undo button it should undo only the rectangle shapes not the other shapes
the code that i am using for undo in the canvas is :
function cPush()
{
canvas = document.getElementById("drawingCanvas");
context = canvas.getContext("2d");
cStep++;
if (cStep < cPushArray.length)
{
cPushArray.length = cStep;
}
cPushArray.push(document.getElementById('drawingCanvas').toDataURL());
}
function cUndo()
{
canvas = document.getElementById("drawingCanvas");
context = canvas.getContext("2d");
context.clearRect(0,0,canvas.width, canvas.height);
if (cStep > 0)
{
cStep--;
var canvasPic = new Image();
canvasPic.src = cPushArray[cStep];
context.drawImage(canvasPic, 0, 0);
}
}
How to "undo" (remove a specified shape and redraw the remaining shapes)
Demo: http://jsfiddle.net/m1erickson/9pTJ2/
Create an array to hold all your shape definitions:
var drawings=[];
Add shapes to the array:
function addShape(shapename,color){
drawings.push({
shape:shapename,
color:color
});
drawAll();
}
To "undo", remove all elements of a specified shape from the array:
function undoShape(shapename){
var i=drawings.length-1;
while(i>=0){
if(drawings[i].shape==shapename){
drawings.splice(i,1);
}
i--;
}
drawAll();
}
Here is code:
[ props to #enhzflep for suggesting the method ]
<!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");
ctx.lineWidth=1;
var shapeWidth=30;
var shapeHeight=30;
var spacer=5;
var drawings=[];
function addShape(shapename,color){
drawings.push({
shape:shapename,
color:color
});
drawAll();
}
function undoShape(shapename){
var i=drawings.length-1;
while(i>=0){
if(drawings[i].shape==shapename){
drawings.splice(i,1);
}
i--;
}
drawAll();
}
function drawAll(){
ctx.clearRect(0,0,canvas.width,canvas.height);
for(var i=0;i<drawings.length;i++){
var drawing=drawings[i];
var x=i*shapeWidth;
var y=50;
switch(drawing.shape){
case "rectangle":
drawRectangle(x,y,drawing.color);
break;
case "circle":
drawCircle(x,y,drawing.color);
break;
}
}
}
function drawContainer(x,y){
ctx.strokeStyle="lightgray";
ctx.strokeRect(x,y,shapeWidth,shapeHeight);
}
function drawRectangle(x,y,color){
drawContainer(x,y);
ctx.fillStyle=color;
ctx.fillRect(x+spacer,y+spacer,shapeWidth-2*spacer,shapeHeight-2*spacer);
}
function drawCircle(x,y,color){
drawContainer(x,y);
ctx.beginPath();
ctx.arc(x+shapeWidth/2,y+shapeHeight/2,shapeWidth/2-spacer,0,Math.PI*2);
ctx.closePath();
ctx.fillStyle=color;
ctx.fill();
}
function randomColor(){
return('#'+Math.floor(Math.random()*16777215).toString(16));
}
$("#rect").click(function(){
addShape("rectangle",randomColor());
});
$("#circle").click(function(){
addShape("circle",randomColor());
});
$("#norect").click(function(){
undoShape("rectangle");
});
$("#nocircle").click(function(){
undoShape("circle");
});
}); // end $(function(){});
</script>
</head>
<body>
<button id="rect">Add Rect</button>
<button id="circle">Add Circle</button>
<button id="norect">Erase Rects</button>
<button id="nocircle">Erase Circles</button>
<canvas id="tools" width=300 height=40></canvas><br>
<canvas id="erasers" width=300 height=40></canvas><br>
<canvas id="canvas" width=300 height=300></canvas>
</body>
</html>

Categories

Resources