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/
Related
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;
HTML:
<img src="http://lorempixel.com/100/100/">
<img src="http://lorempixel.com/100/100/">
<img src="http://lorempixel.com/100/100/">
<img src="http://lorempixel.com/100/100/">
<canvas id="canvas" width="0" height="0"></canvas>
Javascript:
var images = document.getElementsByTagName('img');
var canvas = document.getElementById('canvas');
for (var i = 0; i < images.length; i++) {
canvas.getContext('2d').drawImage(images[i], canvas.width, canvas.height);
canvas.height = canvas.height + images[i].height;
canvas.width = images[i].width;
}
Here's the fiddle:
https://jsfiddle.net/083bapwz/29/
Why is the canvas not visible or I guess, not even getting drawn? I want it to be drawn one after another, first on top, others followed in bottom.
A couple things.
First, changing the canvas width/height dimensions resets all existing canvas state. It is a hackier (and less supported) form of clearRect.
Take the following snippet for example:
var images = document.getElementsByTagName('img');
var canvas = document.getElementById('canvas');
var canvas2 = document.getElementById('canvas2');
var canvas3 = document.getElementById('canvas3');
var ctx1 = canvas.getContext('2d');
var ctx2 = canvas2.getContext('2d');
var ctx3 = canvas3.getContext('2d');
// wont draw
ctx1.moveTo(0, 0);
ctx1.lineTo(100, 100);
ctx1.stroke();
canvas.width = 300;
// wont draw
ctx2.moveTo(0, 0);
ctx2.lineTo(50, 50);
ctx2.stroke();
canvas2.height = 100;
// will draw
ctx3.moveTo(0, 0);
ctx3.lineTo(100, 100);
ctx3.stroke();
#canvas{border: 1px solid red;}
#canvas2{border: 1px solid blue;}
#canvas3{border: 1px solid green;}
<canvas id="canvas" width="200" height="200"></canvas>
<canvas id="canvas2" width="200" height="200"></canvas>
<canvas id="canvas3" width="200" height="200"></canvas>
In other words, don't resize the canvas since the last image would be the only one to draw.
Second, you are telling the image to draw at the (x, y) position of the canvas.width and canvas.height. This mean you will be drawing the image here:
You need to specify the (top, left) x/y values for the image drawing.
Hope this helps.
EDIT:
Possible solution could be the following demo:
var images = document.getElementsByTagName('img');
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
var imageArray = Array.from(images);
// add all image heights together
var canvasHeight = imageArray.reduce(function (acc, img) {
acc += img.height;
return acc;
}, 0);
// just use first image as the width for this example
var canvasWidth = imageArray[0].width;
// set all canvas state prior to draws
canvas.height = canvasHeight;
canvas.width = canvasWidth;
var top = 0;
for (var i = 0; i < imageArray.length; i++) {
var image = imageArray[i];
// use x of 0 to draw on left most of canvas
canvas.getContext('2d').drawImage(image, 0, top);
top += image.height;
}
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>
following the w3c school explanation of canvas, I understand creating shapes...
<script>
var canvas = document.getElementById('myCanvas');
var context = canvas.getContext('2d');
var centerX = canvas.width / 2;
var centerY = canvas.height / 2;
var radius = 20;
context.beginPath();
context.arc(centerX, centerY, radius, 0, 2 * Math.PI, false);
context.fillStyle = 'green';
context.fill();
context.lineWidth = 5;
context.strokeStyle = '#003300';
context.stroke();
</script>
This will make a green circle where my canvas is.
<canvas id="myCanvas"></canvas>
However - I want to apply that "circle" to multiple places on the page, and doing this by ID would be ridiculous.
How does one apply a context (as defined above) to multiple canvas'?? I' assume using class, this seems the logical way.
<canvas class="redDot"></canvas>
<canvas class="redDot"></canvas>
<canvas class="redDot"></canvas>
<canvas class="greenDot"></canvas>
<canvas class="greenDot"></canvas>
<canvas class="blueDot"></canvas>
<canvas class="blueDot"></canvas>
<canvas class="blueDot"></canvas>
You would have to iterate through each Element to apply the changes. I.E:
var dots = document.getElementsByClassName('dots');
for (var i=0;i<dots.length;i++){
var canvas = dots[i];
var context = canvas.getContext('2d');
// Draw circles here
}
Ideally, you would only have one canvas element which you can draw multiple circles
var canvas = document.getElementById('myOneAndOnlyCanvas');
// Using CSS and layering can make background
var context = canvas.getContext('2d');
dot('red',50,50);
dot('blue',100,50);
//etc..
function dot(color,x,y){
context.beginPath();
context.arc(y, y, radius, 0, 2 * Math.PI, false);
context.fillStyle = color;
context.fill();
context.lineWidth = 5;
context.strokeStyle = '#003300';
context.stroke();
}
But if that doesn't fit your use case what about using an SVG object?
Since you mentioned w3 schools: http://www.w3schools.com/svg/
But ideally check out: http://www.w3.org/Graphics/SVG/
Mind, Dom Heavy pages can seriously hurt load times. Depending on what you want to do it might be wiser just to use an image (eg. a large cluster of dots).
I have defined the two functions to render a circle and a triangle. Very straight forward stuff.
function circle(offset, size){
var color = $("#color option:selected").val();
var canvas = document.getElementById("canvas");
var context = canvas.getContext("2d");
radius = size * 1;
context.beginPath();
context.arc(offset, 2, radius, 0, 2 * Math.PI, false);
context.fillStyle = color;
context.fill();
}
function triangle(offset, size){
var color = $("#color option:selected").val();
var canvas = document.getElementById("canvas");
var context = canvas.getContext("2d");
var width = size * 6;
var height = size * 5;
var padding = 0;
// Draw a path
context.beginPath();
context.moveTo(offset + width/2, padding);
context.lineTo(offset + width, height + padding);
context.lineTo(offset, height + padding);
context.closePath();
// Fill the path
context.fillStyle = color;
context.fill();
}
I am have added the canvas to my page with:
<canvas id="canvas"></canvas>
For some reason I can see the circle and square a not rendering correctly. See attached screen shots.
I can almost guarantee that it is because you are setting the width and height of the Canvas using CSS width and height and not the <canvas> html attributes.
You need to define the width/height either in the canvas tag:<canvas width="500" height="500">
or in code:
var canvas = document.getElementById("canvas");
canvas.width = 500;
canvas.height = 500;
And not by CSS. If you did this:
<canvas style="width: 500px; height: 500px;">
Then you would have a 300x150 canvas (the default size) that was scaled/warped to be 500x500, which is almost certainly what you're getting.
(I wrote the above freehand so there might be a typo, but you get the idea)