Cannot cut multiple shapes from canvas - html

I am trying to cut certain pattern from file based canvas and i need multiple geometrical shapes used.
For that, i am drawing shapes on that canvas using globalCompositeOperation set to XOR.
$( document ).ready(function() {
var ctx = document.getElementById('canvas').getContext('2d');
var img = new Image();
img.src = 'http://cimsec.org/wp-content/uploads/2014/01/adriatic-sea-horizon-igor-voljc.jpg';
var width = img.naturalWidth/2; // this will be 300
var height = img.naturalHeight/2; // this will be 400
document.getElementById('canvas').width = width;
document.getElementById('canvas').height = height;
img.onload = function() {
ctx.drawImage(img, 0,0, width, height);
}
ctx.globalCompositeOperation = "xor";
function circle(x, y, radius)
{
ctx.arc(x, y, radius, 0, 2 * Math.PI, false);
ctx.fill();
}
var iks = width/2;
var sr = width/5;
var igrek = (sr);
circle(iks,igrek,sr);
var igrek2 = 3.5*sr;
circle(iks,igrek2,sr);
});
.lw { font-size: 60px; }
body {background-color:blue}
<!DOCTYPE html>
<html>
<head>
<script type="text/javascript" src="http://code.jquery.com/jquery-latest.min.js"></script>
<title>HTML5, CSS3 and JavaScript demo</title>
</head>
<body>
<!-- Start your code here -->
<canvas id="canvas"></canvas>
<!-- End your code here -->
</body>
</html>
Unfortunetly, it does not work correctly if i try cut more than one shape. On example on litewave only second shape is cut correctly, first one only has its perimeter cut.
Ultimately i plan to have ths shape cut from image, white area on this jpg example shoudl be transparent:
http://www.detroitbodyproducts.com/media/wysiwyg/hide.jpg
Is there any better way to do this?

You need to call ctx.beginPath(); first, or else it doesn't work:
$( document ).ready(function() {
var ctx = document.getElementById('canvas').getContext('2d');
var img = new Image();
img.src = 'http://cimsec.org/wp-content/uploads/2014/01/adriatic-sea-horizon-igor-voljc.jpg';
var width = img.naturalWidth/2; // this will be 300
var height = img.naturalHeight/2; // this will be 400
document.getElementById('canvas').width = width;
document.getElementById('canvas').height = height;
img.onload = function() {
ctx.drawImage(img, 0,0, width, height);
}
ctx.globalCompositeOperation = "xor";
function circle(x, y, radius)
{
ctx.beginPath();
ctx.arc(x, y, radius, 0, 2 * Math.PI, false);
ctx.fill();
}
var iks = width/2;
var sr = width/5;
var igrek = (sr);
circle(iks,igrek,sr);
var igrek2 = 3.5*sr;
circle(iks,igrek2,sr);
});
.lw { font-size: 60px; }
body {background-color:blue}
<!DOCTYPE html>
<html>
<head>
<script type="text/javascript" src="http://code.jquery.com/jquery-latest.min.js"></script>
<title>HTML5, CSS3 and JavaScript demo</title>
</head>
<body>
<!-- Start your code here -->
<canvas id="canvas"></canvas>
<!-- End your code here -->
</body>
</html>

Related

How to draw a square on canvas

I'm trying to draw squares at the corners of a canvas. The top ones work but I should be able to draw the third square which I have partially drawn.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"/>
<script type="application/javascript">
function getRandomInt(max) {
return Math.floor(Math.random() * max);
}
var t = getRandomInt(10);
function draw() {
function getRandomInt(max) {
return Math.floor(Math.random() * max);
}
var t = getRandomInt(10);
const canvas = document.getElementById('canvas');
if (canvas.getContext) {
const ctx = canvas.getContext('2d');
setInterval(myTimer, t*100);
function myTimer() {
var i = 0;
var x = window.innerWidth;
var y = window.innerHeight;
y = y + 100;
//draw crosshair
console.log("x = "+ x);
console.log("y = "+ y);
console.log("i = "+ i);
ctx.beginPath();
var crosshairlength = 20;
var lengthxminus = crosshairlength;
var lengthxplus = crosshairlength;
var lengthyminus = crosshairlength;
var lengthyplus = crosshairlength;
//horizontal line
ctx.moveTo((x/2)-lengthxminus, y/2);
ctx.lineTo((x/2)+lengthxplus, y/2);
//vertical line
ctx.moveTo(x/2, (y/2)-lengthyminus);
ctx.lineTo(x/2, (y/2)+lengthyplus);
var t = 10;
//top left
ctx.moveTo(0,0);
ctx.lineTo(t,0);
ctx.lineTo(t,t);
ctx.lineTo(0,t);
ctx.lineTo(0,0);
//top right
ctx.moveTo(x-t,0);
ctx.lineTo(x,0);
ctx.lineTo(x,t);
ctx.lineTo(x-t,t);
ctx.lineTo(x-t,0);
//bottom right
ctx.moveTo(x-t,y-t);
ctx.lineTo(x,y-t);
ctx.lineTo(x,y);
//bottom left
ctx.stroke();
}
i++;
}
}
</script>
</head>
<body onload="draw();">
<canvas id="canvas" width="1846" height="768"></canvas>
</body>
</html>
Either the canvas is the not the size of the viewport or I am misunderstanding the coordinate system which I believe has the positive y-axis going down and the origin is in the top left.
window.innerWidth and window.innerHeight represent the width and height of the viewport. Your <canvas> width and height are set by its width and height attributes.
If you want the canvas to be the size of the viewport, change these attributes, though changing these attributes come with great side-effects like reassigning a new pixel buffer, and clearing all the properties of the attached context, so it's better to do so only when really needed:
if (canvas.width !== x) {
canvas.width = x;
}
if (canvas.height !== y) {
canvas.height = y;
}
And if you wanted to use the size of the canvas rather than the one of the viewport, then you want
function myTimer() {
var i = 0;
var x = canvas.width;
var y = canvas.height;

Wrapping a text around an image in a Canvas

Is it possible to wrap a text around an image inside an HTML 5 Canvas? For example using some Javascript framework? I looked into KineticJS, but couldn't find something useful.
Edit:
It seems my question is unclear. I'm looking for something lke this :
http://www.monkeydoit.com/images/panda2.gif
You can wrap text around an image (rectangle) using canvas transforms (translate+rotate)
For example, this is how you rotate the canvas and draw text down the right side of your image:
// save the untransformed state of the context
ctx.save();
// translate to the top-right corner of the image
// ( x/y properties have been added to the standard img element )
ctx.translate(image.x+image.width,image.y);
// rotate the canvas 90 degrees (PI/2 radians)
ctx.rotate(Math.PI/2);
// the canvas is now properly moved and rotated
// so we can just draw the text at [0,0]
ctx.fillText(subtext,0,0);
// restore the context to its untransformed state
ctx.restore();
This calculates how many words fit on a side using context.measureText:
var end=0;
var subtext="";
while(ctx.measureText(text.split(" ",end+1).join(" ")).width<=length)
{
subtext=text.split(" ",end+1).join(" ");
end++;
}
An interesting enhancement would be to draw text around a rectangle with rounded corners.
Here is code and a Fiddle: http://jsfiddle.net/m1erickson/U2hE3/
<!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; padding:10px; }
canvas{border:1px solid red;}
</style>
<script>
$(function(){
var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
var rect={x:40,y:40,width:150,height:120};
var text="This is some text that wraps on the outside of a rectangle.";
var font="14px Verdana";
drawTextAroundRect(rect,text,7,font);
function drawTextAtAngle(text,length,x,y,radians){
// if text is empty then return
if(text.length==0){return;}
var end=0;
var subtext="";
if(ctx.measureText(text).width<=length){
// all the text fits
subtext=text;
}else{
// calc how many words will fit on this length
while(ctx.measureText(text.split(" ",end+1).join(" ")).width<=length)
{
subtext=text.split(" ",end+1).join(" ");
end++;
}
}
// draw the text at the appropriate angle
ctx.save();
ctx.translate(x,y);
ctx.rotate(radians);
ctx.fillText(subtext,0,0);
ctx.restore();
// return any text that didn't fit for further processing
if(end==text.length){
return("");
}else{
return(text.substr(subtext.length));
}
}
function drawTextAroundRect(rect,text,textPadding,font){
// set the font
ctx.font=font;
// top
text=drawTextAtAngle(text,rect.width,rect.x,rect.y-textPadding,0);
// right
text=drawTextAtAngle(text,rect.height,rect.x+rect.width+textPadding,rect.y,Math.PI/2);
// bottom
text=drawTextAtAngle(text,rect.width,rect.x+rect.width,rect.y+rect.height+textPadding,Math.PI);
// left
text=drawTextAtAngle(text,rect.height,rect.x-textPadding,rect.y+rect.height,Math.PI*1.5);
// draw the rect (just for illustration)
ctx.beginPath();
ctx.rect(rect.x,rect.y,rect.width,rect.height);
ctx.stroke();
}
}); // end $(function(){});
</script>
</head>
<body>
<canvas id="canvas" width=300 height=250></canvas>
</body>
</html>
[ Add more word-wrap code given questioners clarification ]
You can use context.measureText to get the width of text and use that to wrap text around an image.
Given text width you can build a word-wrap by advancing to the next line when text exceeds your desired width.
In the case of wrapping around a picture, you will have 2 desired widths—shorter while the text might run into the image and longer after that.
Here is code and a Fiddle: http://jsfiddle.net/m1erickson/XM5Yp/
<!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 maxWidth = 350;
var lineHeight = 25;
var x = (canvas.width - maxWidth) / 2;
var y = 60;
var text = "'Twas the night before Christmas, when all through the house. Not a creature was stirring, not even a mouse. The stockings were hung by the chimney with care in hopes that St. Nicholas soon would be there.";
ctx.font = '16pt Calibri';
ctx.fillStyle = '#333';
var imgWidth;
var imgHeight;
var img=new Image();
img.onload=function(){
imgWidth=img.width;
imgHeight=img.height;
ctx.drawImage(img,canvas.width-img.width,0)
wrapText(text, x, y, maxWidth, lineHeight);
}
img.src="https://dl.dropboxusercontent.com/u/139992952/stackoverflow/house204-1.jpg";
function wrapText(text, x, y, maxWidth, lineHeight) {
var words = text.split(' ');
var line = '';
var maxLineWidth=y>imgHeight+10?maxWidth:maxWidth-imgWidth;
for(var n = 0; n < words.length; n++) {
var testLine = line + words[n] + ' ';
var metrics = ctx.measureText(testLine);
var testWidth = metrics.width;
if(testWidth > maxLineWidth) {
ctx.fillText(line, x, y);
line = words[n] + ' ';
y += lineHeight;
maxLineWidth= y>imgHeight+10?maxWidth:maxWidth-imgWidth;
}
else {
line = testLine;
}
}
ctx.fillText(line, x, y);
}
}); // end $(function(){});
</script>
</head>
<body>
<canvas id="canvas" width=400 height=325></canvas>
</body>
</html>

HTML5 Canvas image flashes and script does not wait for image to be downloaded

I am using Firefox 19.0.2 on Ubuntu Linux.
I'm learning HTML5 but find that the following code's image
flashes repeatedly. Furthermore, I would like for the image
to finish downloading before the script stars:
<!DOCTYPE html>
<html lang="en">
<head>
<meta encoding="UTF-8" />
<title>Hello Canvas</title>
<script type="text/javascript">
window.onload = drawCanvas;
function canvasSupportEnabled() {
return !!document.createElement('canvas').getContext;
}
var Debugger = function() { };
Debugger.log = function(message) {
try {
console.log(message);
} catch (exception) {
return;
}
}
var x = 0;
var y = 0;
function drawCanvas() {
if (!canvasSupportEnabled())
return;
var theCanvas = document.getElementById("myCanvas");
var context = theCanvas.getContext("2d");
context.fillStyle = "#ffffaa";
context.fillRect(0, 0, 500, 300);
context.fillStyle = "#000000";
context.font = "20px Sans-Serif";
context.textBaseLine = "top";
context.fillText("Hello World!", 195, 80);
context.strokeStyle = "#000000";
context.strokeRect(x, y, 490, 290);
var platypus = new Image();
platypus.onload = function() {
context.drawImage(platypus, x, y);
}
platypus.src = "http://www.wildwatch.com.au/uploads/Platypus/PLATYPUSweb1.jpg"
window.setTimeout(drawCanvas, 200);
x = x + 5;
y = y + 5;
}
</script>
</head>
<body>
<h1>Hello Canvas.</h1>
<canvas id="myCanvas" width="500" height="300">Your browser does not support HTML5 canvas.</c
</body>
</html>
How can I solve these two problems. Do I need to double-buffer and how can I do it?
How do I detect an onload event for the images to finish being downloaded?
Thanks.
This will load the image first then create and draw the canvas.
<!DOCTYPE html>
<html lang="en">
<head>
<meta encoding="UTF-8" />
<title>Hello Canvas</title>
<script type="text/javascript">
window.onload = drawCanvas;
function canvasSupportEnabled() {
return !!document.createElement('canvas').getContext;
}
var x = 0;
var y = 0;
function drawCanvas() {
if (!canvasSupportEnabled())
return;
var platypus = new Image();
platypus.onload = function () {
var theCanvas = document.getElementById("myCanvas");
var context = theCanvas.getContext("2d");
context.fillStyle = "#ffffaa";
context.fillRect(0, 0, 500, 300);
context.fillStyle = "#000000";
context.font = "20px Sans-Serif";
context.textBaseLine = "top";
context.fillText("Hello World!", 195, 80);
context.strokeStyle = "#000000";
context.strokeRect(x, y, 490, 290);
context.drawImage(this, x, y);
}
platypus.src = "http://www.wildwatch.com.au/uploads/Platypus/PLATYPUSweb1.jpg"
}
</script>
</head>
<body>
<h1>Hello Canvas.</h1>
<canvas id="myCanvas" width="500" height="300">Your browser does not support HTML5 canvas.</canvas>
</body>
</html>
I suspect the issue is the setTimeout call. The first run of the drawCanvas function causes the image to start loading. Once the image is loaded, it'll draw on the canvas, but the subsequent drawCanvas calls caused by the timeout will cause the whole canvas to get filled with the rect you're drawing and thus making the image disappear.
The onload callback will not fire again due to the image already having been loaded.
The simplest way to fix it would be to use a preloader for the images. Basically instead of using your current window.onload handler, use another function which loads your images and stores them in some variables. Once it has finished loading the images, have it call drawCanvas which you would modify to use one of the stored images instead.
The following did it for me.
<!DOCTYPE html>
<html lang="en">
<head>
<meta encoding="UTF-8" />
<title>Hello Canvas</title>
<script type="text/javascript">
window.onload = drawCanvas;
function canvasSupportEnabled() {
return !!document.createElement('canvas').getContext;
}
var x = 0;
var y = 0;
function drawCanvas() {
if (!canvasSupportEnabled())
return;
var platypus = new Image();
platypus.onload = function () {
var theCanvas = document.getElementById("myCanvas");
var context = theCanvas.getContext("2d");
context.fillStyle = "#ffffaa";
context.fillRect(0, 0, 500, 300);
context.fillStyle = "#000000";
context.font = "20px Sans-Serif";
context.textBaseLine = "top";
context.fillText("Hello World!", 195, 80);
context.strokeStyle = "#000000";
context.strokeRect(x, y, 490, 290);
context.drawImage(this, x, y);
}
x = x + 5;
y = y + 5;
setTimeout(drawCanvas, 200);
platypus.src = "http://www.wildwatch.com.au/uploads/Platypus/PLATYPUSweb1.jpg"
}
</script>
</head>
<body>
<h1>Hello Canvas.</h1>
<canvas id="myCanvas" width="500" height="300">Your browser does not support HTML5 canvas.</
</body>
</html>

Drag and Drop functionality inside canvas using HTML5

Hello all can we place drag and drop functionality inside canvas using html5??
My actual requirement is to drag the image into textbox that should be done inside the canvas...
please share your ideas..The following link i used to learn drag and drop but it should be done inside the canvas..
http://www.w3schools.com/html5/tryit.asp?filename=tryhtml5_draganddrop
You can learn more in this tutorial: http://html5.litten.com/how-to-drag-and-drop-on-an-html5-canvas/
From your limited description in your question, it sounds like you drag items over the canvas and this tutorial is likely the best match.
This is the actual code you can paste into file and open in HTML5 compliant browser and it will work:
<!doctype html>
<html>
<head>
<meta charset="UTF-8" />
<title>Canvas Drag and Drop Test</title>
</head>
<body>
<section>
<div>
<canvas id="canvas" width="400" height="300">
This text is displayed if your browser does not support HTML5 Canvas.
</canvas>
</div>
<script type="text/javascript">
var canvas;
var ctx;
var x = 75;
var y = 50;
var WIDTH = 400;
var HEIGHT = 300;
var dragok = false;
function rect(x,y,w,h) {
ctx.beginPath();
ctx.rect(x,y,w,h);
ctx.closePath();
ctx.fill();
}
function clear() {
ctx.clearRect(0, 0, WIDTH, HEIGHT);
}
function init() {
canvas = document.getElementById("canvas");
ctx = canvas.getContext("2d");
return setInterval(draw, 10);
}
function draw() {
clear();
ctx.fillStyle = "#FAF7F8";
rect(0,0,WIDTH,HEIGHT);
ctx.fillStyle = "#444444";
rect(x - 15, y - 15, 30, 30);
}
function myMove(e){
if (dragok){
x = e.pageX - canvas.offsetLeft;
y = e.pageY - canvas.offsetTop;
}
}
function myDown(e){
if (e.pageX < x + 15 + canvas.offsetLeft && e.pageX > x - 15 +
canvas.offsetLeft && e.pageY < y + 15 + canvas.offsetTop &&
e.pageY > y -15 + canvas.offsetTop){
x = e.pageX - canvas.offsetLeft;
y = e.pageY - canvas.offsetTop;
dragok = true;
canvas.onmousemove = myMove;
}
}
function myUp(){
dragok = false;
canvas.onmousemove = null;
}
init();
canvas.onmousedown = myDown;
canvas.onmouseup = myUp;
</script>
</section>
</body>
</html>

HTML Canvas; Given two Xs and two Ys, Center Text within

I am making a series of rectangles. This is not the entire script, this code will actually be within a function with parameters for x and y coordinates and parameters for height and width. This function will be used to create multiple rectangles. My question is that I need to center the text within rectangles of x,y,width and height ... and the text will vary in length.
<!DOCTYPE html>
<html lang="en">
<body>
<canvas id="myCanvas" width="400" height="350">
Your browser does not support the canvas element.
</canvas>
<script type="text/javascript">
var x = 10;
var y = 10;
var width = 180;
var height = 75;
var c = document.getElementById("myCanvas");
ctx = c.getContext("2d");
ctx.lineWidth = 5;
ctx.strokeStyle="black";
ctx.strokeRect(x,y,width,height);
ctx.textBaseline = 'top';
ctx.font = '20px Sans-Serif';
ctx.fillStyle = 'blue';
ctx.fillText ("hello", 30, 50);
</script>
</body>
</html>
You can use the measureText method of your context to calculate the position of your text before drawing it.
to center vertically use this:
context.textBaseline = "middle";
y_pos = text_area_height / 2;
Use the textAlign property:
context.textAlign = 'center';
http://www.html5canvastutorials.com/tutorials/html5-canvas-text-align/