HTML5 Canvas merging to rectangles to form a new shape - javascript

I have a page that you will be able to draw squares on it. The squares will represent a room, so you have one square, then you make another over the first square and then two will join
It will looks like this
http://puu.sh/bllo7/95e2112d79.png
And functions like so http://jsfiddle.net/bLenxexL/
I need to figure out how get them squares to make another shape that will look like the image on the right of the picture above.
If this helps, the square info is stored in points in this format
[
{
start: {x: 312, y: 164},
end: {x: 734, y: 371}
},
{
start: {x: 696, y: 304},
end: {x: 1060, y: 561}
}
]
Any links to resources that will help me do this will be of much help thank you

You can use compositing to create a single stroke around your combined rectangles.
draw all your rectangles with strokes
set compositing to 'destination-out'. This causes new drawings to "erase" existing drawings where the two overlap.
fill all your rects. This erases all but the outline of the combined rectangles.
This works because strokes are drawn half-inside & half-outside the border of rectangles. When you erase the inside of the combined rectangles you are left with the half-outside strokes.
Example code and a Demo: http://jsfiddle.net/m1erickson/m5jg92wd/
<!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");
// draw all rects with strokes
ctx.strokeRect(20,20,100,200);
ctx.strokeRect(90,110,75,50);
// set compositing to erase existing drawings
// new drawings will erase existing drawings where the two overlap
ctx.globalCompositeOperation='destination-out';
// fill all rects
// This "erases" all but the outline stroke
ctx.fillRect(20,20,100,200);
ctx.fillRect(90,110,75,50);
// reset compositing to its default mode
ctx.globalCompositeOperation='source-over';
}); // end $(function(){});
</script>
</head>
<body>
<canvas id="canvas" width=300 height=300></canvas>
</body>
</html>

Related

Canvas aligning lines to linear-gradient color stops

I have been trying to create ticks between each division of my linear gradient, for some reason I can not get them to align properly with the gradient, the math is pretty simple yet it is still off by a few pixels in very big gradients.
My HTML:
<html>
<head>
<script type="text/javascript" src="https://code.jquery.com/jquery-2.1.1.min.js"></script>
<script type="text/javascript" src="canvas.js"></script>
<style type="text/css">
canvas {
border: 1px solid black;
}
</style>
</head>
<body>
<canvas id="canvas" width="1300" height="300"></canvas>
</body>
</html>
canvas.js:
$(document).ready(function() {
var canvas= $("canvas")[0];
var canvasWidth= $("canvas").innerWidth();
var canvasHeight= $("canvas").innerHeight();
var ctx = canvas.getContext("2d");
var size= [0, 0, canvasWidth, canvasHeight/2];
var grad = ctx.createLinearGradient(size[0],size[1],size[2],0);
ctx.lineWidth= 2;
grad.addColorStop(0, 'green');
grad.addColorStop(0.5, 'green');
grad.addColorStop(0.5, 'yellow');
grad.addColorStop(0.8, 'yellow');
grad.addColorStop(0.8, 'red');
grad.addColorStop(1, 'red');
ctx.fillStyle = grad;
ctx.fillRect(size[0], size[1], size[2], size[3]);
ctx.translate(0, canvasHeight/2);
ctx.strokeStyle= "black";
ctx.beginPath();
ctx.moveTo(canvasWidth*0.5, -6);
ctx.lineTo(canvasWidth*0.5, 6);
ctx.stroke();
ctx.beginPath();
ctx.moveTo(canvasWidth*0.8, -6);
ctx.lineTo(canvasWidth*0.8, 6);
ctx.stroke();
});
The code is also in a fiddle
As you can see I create 3 color sections using the createLinearGradient method, I add stops at 0.5 and 0.8, then I try to plot ticks at those same spaces. The ticks are dislocated to the left a few pixels and I have no idea why. This is only noticeable in big gradients, in small gradients (like 300px x 300px) the ticks appear to be in the right position.
Note: I have to use linear gradients, changing to simple colored rectangles is not an option. I want to be able to define gradients as well as solid colors sections with the same code (just changing the color stops).
This seems to be a webkit specific bug. The fiddle renders correctly in Firefox, IE11 and Opera 12 (presto engine). I filled a bug report to chromium.

HTML5 Canvas | Pattern to reveal overlayed line art based on pattern pixel color

I need to apply, via canvas element, a one color (black) bitmap image (line art) onto a 2 color (red and yellow) bitmap image (pattern) and have only the red pixels of that pattern be colored by the overlayed line art, kinda like an intersect. I saw this:
https://developer.mozilla.org/en/docs/Web/Guide/HTML/Canvas_tutorial/Compositing (see globalCompositeOperation > Darker method ) and wondered if that effect is what I need. Since that method no longer appears to be supported, is there a way to simulate such an effect? All images used for this only contain spot colors (100% red, 100% yellow, 100% black, 100% white). Any javascript code sample or hint(s) leading to a solution would be awesome. Thx for input.
If you can isolate just the red portion onto a separate image then you can use compositing to recolor where black intersects red.
Otherwise you can grab all the pixel colors on both images using context.getImageData.
Then you can change the red pixels to black where red & black intersect.
Example code and a Demo: http://jsfiddle.net/m1erickson/pcsmbr22/
<!doctype html>
<html>
<head>
<link rel="stylesheet" type="text/css" media="all" href="reset.css" /> <!-- reset css -->
<script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script>
<style>
body{ background-color: ivory; margin:20px; }
canvas{border:1px solid red;}
</style>
<script>
$(function(){
var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
var canvasB=document.getElementById("black");
var ctxB=canvasB.getContext("2d");
var canvasC=document.getElementById("color2");
var ctxC=canvasC.getContext("2d");
ctxB.fillRect(50,50,50,100);
ctxC.fillStyle='yellow';
ctxC.fillRect(75,50,50,50);
ctxC.fillStyle='red';
ctxC.fillRect(75,100,50,50);
var iDataB=ctxB.getImageData(0,0,canvasB.width,canvasB.height);
var dataB=iDataB.data;
var iDataC=ctxC.getImageData(0,0,canvasC.width,canvasC.height);
var dataC=iDataC.data;
// copy yellow-red onto results canvas
ctx.drawImage(canvasC,0,0);
var iData=ctx.getImageData(0,0,canvas.width,canvas.height);
var data=iData.data;
// copy black pixels when intersecting red pixels
for(var i=0;i<dataC.length;i+=4){
var isBlack=(dataB[i]==0 && dataB[i+1]==0 && dataB[i+2]==0 && dataB[i+3]==255);
var isRed=(dataC[i]==255 && dataC[i+1]==0 && dataC[i+2]==0 && dataC[i+3]==255);
if(isBlack && isRed){
data[i]=0;
data[i+1]=0;
data[i+2]=0;
data[i+3]=255;
}
}
ctx.putImageData(iData,0,0);
}); // end $(function(){});
</script>
</head>
<body>
<canvas id="black" width=200 height=200></canvas>
<canvas id="color2" width=200 height=200></canvas>
<canvas id="canvas" width=200 height=200></canvas>
</body>
</html>

confusion on drawImage() method coordinates

image coordinates always confuses me.so to test this i did a little example.i have an image which is 500x500.i have two canvas and i want to draw the image on the first canvas .the size of the canvas is 500x500.the canvas is 50 px from the top and 250 px from the left.the image is not drawn on the canvas.how i can i solve this & please correct me if i am doing any wrong here
there are eight co-ordinates in draw image function (which confuses me most)
1st=0,start_X of source image;
2nd=0,start_Y of source image;
3rd=500,destination_x of source image;
4th=500,destination_Y of source image;
5th=0,canvas_start_X ;
6th=0,canvas_start_Y;
7th=500,canvas_finish_X;
8th=500,canvas_finish_Y;
jsfiddle
code:
<html>
<head>
<style>
*{margin:0px;padding:0px;}
#mydiv{
width:100%;
height:100%;
background-color:black;
}
#mycanvas1{
width:500px;
height:500px;
background-color:white;
border:1px solid white;
margin-top:50px;
margin-left:250px;
}
</style>
</head>
<body>
<div id="mydiv">
<canvas id="mycanvas1"></canvas>
<canvas id="mycanvas2"></canvas>
</div>
<script >
function makeit(){
var canvas1=document.getElementById("mycanvas1");
var ctxbg=canvas1.getContext('2d');
var bgImage=new Image();
bgImage.src="bg.jpg";
alert(bgImage.width+" " +bgImage.height);
bgImage.addEventListener('load',drawBg,false);
function drawBg(){
ctxbg.drawImage(bgImage,0,0,500,0,0,,500,500);
}
}
window.onload=makeit;
</script>
</body>
If the most confusing way of drawing images to the canvas (in the 2d context) confuses you most why don't you try one of the less confusing ways?
ctx.drawImage(img,x,y);
or
ctx.drawImage(img,x,y,width,height);
You should also set your canvas width / height properties on the canvas element, not in the css. The css does not change the actual size of the canvas, the amount of pixels used, just the way it "looks", aka is rendered in the browser. You could display a 1x1 pixels sized canvas in 800x600 and it would still be 1 pixel in size.
What happened in your case is that without width / height properties specified it defaulted to 300x150 in size, so only rendering the top left corner of your image scaled up to 500x500 pixels via css.
That's how you want to set the dimensions.
<canvas id="mycanvas1" width="500" height="500"></canvas>
The 3rd & 4th numeric arguments specify the width and height of the area that is to be clipped from the original image. The 3rd and 4th arguments are used for clipping a subsection from the original image.
The 7th & 8th numeric arguments specify the width and height of the image to be drawn on the canvas. The 7th and 8th arguments are used for scaling the original image as it is drawn on the canvas.
Think of the extended drawImage like this:
drawImage(
sourceImage,
// clip a subsection of the original image
// starting at clipX,clipY
// with the clipped subsection being clipWidth and clipHeight in size
clipX,clipY,clipWidth,clipHeight,
// draw that clipped subsection on the canvas at canvasX,canvasY
// with optional scaling to scaledWidth,scaledHeight
// (no scaling if clipWidth==scaledWidth && clipHeight==scaledHeight)
canvasX,canvasY,scaledWidth,scaledHeight
);
So you can load and draw your image like this:
var bgImage=new Image();
bgImage.onload=function(){
ctxbg.drawImage(bgImage,0,0)
}
bgImage.src="bg.jpg";
Since your not clipping or scaling the original image as you draw it to canvas, there's no reason to use the extended version of drawImage. But the extended version of drawImage would still work if you specify no clipping and no scaling.
This code will draw the entire bgImage on the canvas (assuming the canvas is large enough to hold the full bgImage):
var bgImage=new Image();
bgImage.onload=function(){
ctxbg.drawImage(bgImage,0,0,bgImage.width,bgImage.height,0,0,bgImage.width,bgImage.height)
}
bgImage.src="bg.jpg";
Example code:
<!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>
#mydiv{
width:1000px;
height:1000px;
background-color:black;
}
#mycanvas1{
width:500px;
height:500px;
background-color:white;
border:1px solid white;
margin-top:50px;
margin-left:250px;
}
</style>
<script>
window.onload=function(){
var canvas1=document.getElementById("mycanvas1");
var ctx=canvas1.getContext("2d");
var ctxbg=canvas1.getContext('2d');
var bgImage=new Image();
bgImage.onload=function(){
var w=bgImage.width;
var h=bgImage.height;
ctxbg.drawImage(bgImage,0,0,w,h,0,0,w,h);
}
bgImage.src="https://dl.dropboxusercontent.com/u/139992952/multple/bgImage1.jpg";
};
</script>
</head>
<body>
<div id="mydiv">
<canvas id="mycanvas1" width=300 height=300></canvas>
</div>
</body>
</html>

Highlight area of image with canvas/JS

I am trying to alter an image by highlighting an area defined by coordinates.
I've been using two canvases, on top of each other. Now I don't know if this is the best way to do it in the first place. http://jsfiddle.net/9wJu8/
<canvas id='canvas'>Your browser does not support HTML5 canvas</canvas>
<canvas id='canvas2'>Your browser does not support HTML5 canvas</canvas>
Currently, I am using two images, but I wonder if there is any way to use masks on canvas.
Second of all, I'd like to save the output of the stacked canvases.
What #Ken said but I think some of his code example was accidentally omitted:
A Demo: http://jsfiddle.net/m1erickson/Spkhz/
<!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 cw=700;
var ch=438;
var img=new Image();
img.onload=start;
img.src="cat.jpg";
function start(){
canvas.width=cw;
canvas.height=ch;
// draw the image on the canvas
ctx.drawImage(img,0,0,cw,ch);
// darken the image with a 50% black fill
ctx.save();
ctx.globalAlpha=.50;
ctx.fillStyle="black";
ctx.fillRect(0,0,cw,ch);
ctx.restore();
// ctx.clip() the area to highlight
// and redraw the whole image
// (the image will draw only in the clipping region)
ctx.save();
ctx.beginPath();
ctx.clearRect(300,100,200,100);
ctx.rect(300,100,200,100);
ctx.clip();
ctx.drawImage(img,0,0,cw,ch);
ctx.restore();
}
}); // end $(function(){});
</script>
</head>
<body>
<canvas id="canvas" width=300 height=300></canvas>
</body>
</html>
You can use a single canvas for this:
➔ Draw complete image
➔ Draw a transparent black rectangle on top
➔ Use drawImage() with clipping settings
For example:
// draw full image
ctx.drawImage(img, 0, 0);
// cover with a darkened overlay
ctx.fillStyle = 'rgba(0,0,0, 0.5);
ctx.fillRect(0, 0, canvas.width, canvas.height);
// draw region of image
ctx.drawImage(img, x, y, w, h, x, y, w, h);
where x, y, w and h is the region you want to highlight.
To save out as an image just use toDataURL() on the canvas element.

Make an image via canvas

I am trying to make the next thing (I tried to do it via css: http://jsfiddle.net/kyfha/74/ but the users suggested me to do it via canvas). so I tried via canvas:
when the user overs all this shape, it will be changed to:
when the user overs out this shape, it will be changed to the image number 1.
if, in image number 2, he presses the small gray circle, the image will be changed to:
if he presses the small lightblue circle, it will be changed to image number 2.
I tried to make it via canvas, javascript and css and I got the shapes.
what I have to do is to put a lightBlue circle in the middle of the gray shape (it will be always there) and put a small green circle in the end of the blue shape.
the blue shape can be more longer, smaller or to the left side.
for example:
In addition, when the user presses the small circles, I have to put a line in the pressed small circle (for example, image 2 and 3).
I defined to canvas: canvas (the gray shape) and canvas2 (the blue shape inside the gray shape).
this is my jsfiddle:
http://jsfiddle.net/Ht6Ym/2250/
this is my html:
<div>
<canvas id="myCanvas" width="578" height="250" style="position: absolute;">
</canvas>
<canvas id="myCanvas2" width="578" height="250" style="position: absolute;">
</canvas>
</div>
Hello
Bye
any help appreciated!!
I'm not quite sure why, but I was intrigued with your design, So................
Here's some help drawing your canvas shapes entirely within canvas.
Demo: http://jsfiddle.net/m1erickson/c4upM/
To make any shape clickable, check out context.isPointInPath to do hit-testing. I leave the interactivity up to you.
Good luck with your project!
Code:
<!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 cx=150;
var cy=100;
var radius=75;
var linewidth=15;
var PI=Math.PI;
roundRect("Bye");
grayArc("gray");
blueArc("blue",PI*1.25,PI*1.5);
circleInArc("skyblue",PI*1.5);
lineThruArc("skyblue",PI*1.5);
circleInArc("lightgray",PI*1.25);
lineThruArc("lightgray",PI*1.25);
cy+=150;
lightblueCircle("Hello");
grayArc("gray");
blueArc("blue",PI*1.25,PI*1.5);
circleInArc("skyblue",PI*1.5);
lineThruArc("skyblue",PI*1.5);
circleInArc("lightgray",PI*1.25);
lineThruArc("lightgray",PI*1.25);
function grayArc(strokeColor){
ctx.beginPath();
ctx.arc(cx,cy,radius,Math.PI,Math.PI*2);
ctx.lineWidth=linewidth;
ctx.strokeStyle=strokeColor;
ctx.stroke();
}
function blueArc(strokeColor,radianStart,radianEnd){
ctx.beginPath();
ctx.arc(cx,cy,radius,radianStart,radianEnd);
ctx.lineWidth=linewidth;
ctx.strokeStyle=strokeColor;
ctx.stroke();
}
function circleInArc(fillColor,radianAngle){
var x=cx+radius*Math.cos(radianAngle);
var y=cy+radius*Math.sin(radianAngle);
ctx.beginPath();
ctx.arc(x,y,linewidth/2,0,Math.PI*2);
ctx.closePath();
ctx.fillStyle=fillColor;
ctx.fill();
}
function lineThruArc(strokeColor,radianAngle){
var length=40;
var x1=cx+(radius-length/2)*Math.cos(radianAngle);
var y1=cy+(radius-length/2)*Math.sin(radianAngle);
var x2=cx+(radius+length/2)*Math.cos(radianAngle);
var y2=cy+(radius+length/2)*Math.sin(radianAngle);
ctx.beginPath();
ctx.moveTo(x1,y1);
ctx.lineTo(x2,y2);
ctx.strokeStyle=strokeColor;
ctx.lineWidth=2;
ctx.stroke();
}
function lightblueCircle(text){
ctx.beginPath();
ctx.arc(cx,cy,radius-25,0,Math.PI*2);
ctx.closePath();
ctx.fillStyle="skyblue";
ctx.fill();
ctx.fillStyle="white";
ctx.font="18px verdana";
var halfWidth=ctx.measureText(text).width/2
ctx.fillText(text,cx-halfWidth,cy);
}
function roundRect(text){
var x=cx-radius+20;
var y=cy-25-5;
var width=radius*2-40;
var height=radius*.66;
var cornerRadius=15;
ctx.beginPath();
ctx.moveTo(x+cornerRadius,y);
ctx.lineTo(x+width-cornerRadius,y);
ctx.quadraticCurveTo(x+width,y,x+width,y+cornerRadius);
ctx.lineTo(x+width,y+height-cornerRadius);
ctx.quadraticCurveTo(x+width,y+height,x+width-cornerRadius,y+height);
ctx.lineTo(x+cornerRadius,y+height);
ctx.quadraticCurveTo(x,y+height,x,y+height-cornerRadius);
ctx.lineTo(x,y+cornerRadius);
ctx.quadraticCurveTo(x,y,x+cornerRadius,y);
ctx.closePath();
ctx.fillStyle="skyblue";
ctx.fill();
ctx.fillStyle="white";
ctx.font="18px verdana";
var halfWidth=ctx.measureText(text).width/2
ctx.fillText(text,cx-halfWidth,cy);
}
}); // end $(function(){});
</script>
</head>
<body>
<canvas id="canvas" width=300 height=325></canvas>
</body>
</html>

Categories

Resources