In a JS canvas, how can I place a text within a "box", Ora have it stay in a rectangle? I mean, I can place a text at x, y coordinate, but I'd like it to lay in a surround box x0, y0, x1, y1, so to have line breaks when the text is about to go out of the box, I can center it within the rectangle and possibly have the text scaled to fit as much as the box as possible.
Is there such a library to do so?
hope this will help you
<!DOCTYPE HTML>
<html>
<head>
<style>
body {
margin: 0px;
padding: 0px;
}
</style>
</head>
<body>
<canvas id="myCanvas" width="578" height="200"></canvas>
<script>
function wrapText(context, text, x, y, maxWidth, lineHeight) {
var words = text.split(' ');
var line = '';
for(var n = 0; n < words.length; n++) {
var testLine = line + words[n] + ' ';
var metrics = context.measureText(testLine);
var testWidth = metrics.width;
if (testWidth > maxWidth && n > 0) {
context.fillText(line, x, y);
line = words[n] + ' ';
y += lineHeight;
}
else {
line = testLine;
}
}
context.fillText(line, x, y);
}
var canvas = document.getElementById('myCanvas');
var context = canvas.getContext('2d');
var maxWidth = 400;
var lineHeight = 25;
var x = (canvas.width - maxWidth) / 2;
var y = 60;
var text = 'All the world \'s a stage, and all the men and women merely players. They have their exits and their entrances; And one man in his time plays many parts.';
context.font = '16pt Calibri';
context.fillStyle = '#333';
wrapText(context, text, x, y, maxWidth, lineHeight);
</script>
</body>
</html>
Related
I have this code which is a bouncing ball that I can move with a mouse and it is supposed to work like a slingshot. The problems are: By dragging the ball I change ball speed to mouse speed but it happens even when I click blank space. Also the speed I get from the mouse is somehow not the one with which i move my mouse. How do I change speed only when I hold the ball and calculate the speed of the whole mouse move?
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
</head>
<body>
<canvas id="myCanvas" width="800" height="800"></canvas>
<script>
var canvas = document.getElementById("myCanvas");
var ctx = canvas.getContext("2d");
var ballRadius = 30;
var x = canvas.width/2;
var y = canvas.height-30;
var dx = 0;
var dy = 0;
var w=myCanvas.width;
var h=myCanvas.height;
var isDrag=false;
var offset={x:0,y:0};
var totalX = 0;
var totalY = 0;
var moveX = 0;
var moveY = 0;
function drawBall() {
ctx.beginPath();
circle(x,y,ballRadius,'#c1153e');;
ctx.fillStyle = "red";
ctx.fill();
ctx.closePath();
}
function draw() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
drawBall();
if(x + dx > canvas.width-ballRadius || x + dx < ballRadius) {
dx = -dx;
}
if(y + dy > canvas.height-ballRadius || y + dy < ballRadius) {
dy = -dy;
}
x += dx;
y += dy;
}
setInterval(draw, 15);
function circle(x,y,ballRadius,color='black'){
ctx.clearRect(0,0,w,h)
ctx.fillStyle=color;
ctx.beginPath();
ctx.arc(x,y,ballRadius,0,2*Math.PI);
ctx.fill();
}
circle(x,y,ballRadius,'#c1153e');
myCanvas.onmousedown=function(e){
var m=get_mouse_coords(e);
circle(x,y,ballRadius,'green');
if ((x-m.x)*(x-m.x)+(y-m.y)*(y-m.y)<ballRadius*ballRadius){
isDrag=true;
circle(x,y,ballRadius,'red');
offset.x=x-m.x;
offset.y=y-m.y;
x=m.x+offset.x;
y=m.y+offset.y;
}
}
function get_mouse_coords(e){
var m={};
var rect=myCanvas.getBoundingClientRect();
m.x=e.clientX-rect.left;
m.y=e.clientY-rect.top;
//console.log(m);
return m;
}
myCanvas.onmousemove=function(e){
var m=get_mouse_coords(e);
if (isDrag) {
x=m.x;
y=m.y;
x=m.x+offset.x;
y=m.y+offset.y;
circle(x,y,ballRadius,'red');
}
}
myCanvas.onmouseup=function(e){
var m=get_mouse_coords(e);
isDrag=false;
dx=-totalX/300;
dy=-totalY/300;
circle(x,y,ballRadius);
}
var totalX = 0;
var totalY = 0;
var moveX = 0;
var moveY = 0;
document.addEventListener("mousemove", function(ev){
totalX += Math.abs(ev.movementX);
totalY += Math.abs(ev.movementY);
moveX += ev.movementX;
moveY += ev.movementY;
}, false);
setInterval(function(){
console.log(`Speed X: ${totalX}px/s, Y: ${totalY}px/s`);
console.log(`Movement X: ${moveX}px/s, Y: ${moveY}px/s`);
moveX = moveY = totalX = totalY = 0;
}, 10000);
</script>
</body>
</html>
From what I see, the event onmouseup is executed even if you clicked in blank space, you should probably check also that isDrag is true.
Secondly, I am not sure to understand what you want to do exactly, but should you not set the speed of your ball to zero when you click on it? Otherwise the ball is still moving even if your mouse isn't.
I have drawn a grid in html5 canvas using StrokeLineX and StrokeLineY. I want to highlight the particular square/rectangle when I click on it in the grid.
I have tried using math.floor to define an index for a space but as soon as the width or height increases it starts giving different answers. I have tried too many times before finally posting it here.
Here is the code.
var canvas = document.getElementById("myCanvas");
canvas.addEventListener('click', on_canvas_click, false);
var ctx = canvas.getContext("2d");
var tray_length = 800;
var tray_depth = 800;
var boxHeight = 50;
var boxWidth = 50;
var canvas_X = tray_length;
var canvas_Y = tray_depth;
var box_x_pixels = canvas_X/no_of_columns;
var box_y_pixels = canvas_Y/no_of_rows;
// Drawing the grid
for (var y = boxWidth; y < canvas_Y; y += boxWidth) {
strokeLineX(ctx, y);
}
for (var x = boxHeight; x < canvas_X; x += boxHeight) {
strokeLineY(ctx, x);
}
function strokeLineX(ctx, y) {
ctx.beginPath();
ctx.strokeStyle = 'green';
ctx.moveTo(0, y);
ctx.lineTo(canvas_X, y);
ctx.stroke();
ctx.closePath();
}
function strokeLineY(ctx, x) {
ctx.beginPath();
ctx.strokeStyle = 'red';
ctx.moveTo(x, 0);
ctx.lineTo(x, canvas_Y);
ctx.stroke();
ctx.closePath();
}
function on_canvas_click(ev) {
var x = ev.pageX - canvas.offsetLeft;
var y = ev.pageY - canvas.offsetTop;
console.log(x+":"+y);
var coordinateDisplay = "x=" + x + ", y=" + y;
if (y>= 0 && y <= y+boxHeight ) {
var indexOfX = Math.floor(x/boxWidth); //divide on width and round off
var indexOfY = Math.floor(y/boxHeight);
// alert('You clicked bar index: ' + indexOfX+"-"+indexOfY);
ctx.fillRect="green";
ctx.rect(x,y,box_x_pixels,box_y_pixels);
ctx.stroke();
console.log(indexOfX + "-" + indexOfY);
}
}
In on_canvas_click change the following:
Instead of
ctx.fillRect="green";
do:
ctx.fillStyle="green";
And instead of:
ctx.rect(x,y,box_x_pixels,box_y_pixels);
do:
ctx.fillRect(boxWidth*indexOfX, boxHeight*indexOfY, boxWidth, boxHeight);
... and you don't need:
ctx.stroke();
Here is a working snippet with those changes applied, but also with some simplifications which are unrelated to your problem:
Removal of unused variables;
Use of one function to draw lines, instead of two;
Use of canvas.width and canvas.height properties;
Drawing grid lines also on the outer grid boundaries
var canvas = document.getElementById("myCanvas");
var ctx = canvas.getContext("2d");
var boxHeight = 50;
var boxWidth = 50;
var canvas_X = canvas.width;
var canvas_Y = canvas.height;
canvas.addEventListener('click', on_canvas_click, false);
// Drawing the grid
for (var y = 0; y <= canvas_Y; y += boxWidth) {
strokeLine(ctx, 0, y, canvas_X, y, 'green');
}
for (var x = 0; x <= canvas_X; x += boxHeight) {
strokeLine(ctx, x, 0, x, canvas_Y, 'red');
}
function strokeLine(ctx, x0, y0, x1, y1, color) {
ctx.beginPath();
ctx.strokeStyle = color;
ctx.moveTo(x0, y0);
ctx.lineTo(x1, y1);
ctx.stroke();
ctx.closePath();
}
function on_canvas_click(ev) {
var x = ev.pageX - canvas.offsetLeft;
var y = ev.pageY - canvas.offsetTop;
if (y>= 0 && y <= y+boxHeight ) {
var indexOfX = Math.floor(x/boxWidth); //divide on width and round off
var indexOfY = Math.floor(y/boxHeight);
ctx.fillStyle="green";
ctx.fillRect(boxWidth*indexOfX, boxHeight*indexOfY, boxWidth, boxHeight);
}
}
<canvas id="myCanvas" width="600" height="200"></canvas>
I have this little script.
How can I center the text vertically? In another words, I need to bring out a variable from the function "wrapText" in order to use it to calculate the position of the text. Thanks a lot!
<canvas id="myCanvas" width="900" height="600" style="display:none;"></canvas>
<img id="canvasImg">
<script>
var canvas = document.getElementById("myCanvas");
var context = canvas.getContext("2d");
var imageObj = new Image();
imageObj.onload = function()
{
context.drawImage(imageObj, 0, 0);
}
imageObj.src = "img/imagea.jpg";
var myForm = document.getElementById('myForm');
myForm.addEventListener('submit', function(e)
{
var text = document.getElementById('area1').value;
if(text.lenght == 0)
{
alert("you forgot to put something");
}
function wrapText(context, text, x, y, maxWidth, lineHeight) {
var convtext = text.replace(/\n/g, ' |br| ');
var words = convtext.split(' ');
var line = '';
for(var n = 0; n < words.length; n++) {
var newline = false;
if (words[n].indexOf("|br|") > -1) newline = true;
var metrics = maxWidth;
var testWidth = maxWidth;
var testLine = line + words[n] + ' ';
if (context.measureText) {
metrics = context.measureText(testLine);
testWidth = metrics.width;
}
if ((testWidth > maxWidth && n > 0) || newline) {
context.fillText(line, x, y);
if (!newline) line = words[n] + ' ';
if (newline) line = "";
y += lineHeight;
} else {
line = testLine;
}
}
context.fillText(line, x, y);
}
var maxWidth = 500;
var lineHeight = 40;
var x = 100;
var y = 100;
context.font = "30pt HelveticaNeue-Light";
wrapText(context, text, x, y, maxWidth, lineHeight);
context.fillStyle = "#009bdc";
context.fillText("try", 100, 500);
var dataURL = canvas.toDataURL();
document.getElementById('canvasImg').src = dataURL;
e.preventDefault();
});
</script>
Here's how:
Modify wrapText to return the ending height value (so you can calculate the paragraph height).
Modify wrapText to optionally not draw (==optionally, not do fillText)
Run wrapText once in the no-draw mode to get the height of the wrapped paragraph.
Calculate a starting y that will produce a vertically centered paragraph: var centeringY = maxHeight/2 - paragraphHeight/2
Run wrapText again in the yes-draw mode using centeringY.
Example code and a Demo:
A paragraph of wrapped text that's vertically centered...
var canvas=document.getElementById("canvas");
var context=canvas.getContext("2d");
var cw=canvas.width;
var ch=canvas.height;
var maxWidth = 150;
var lineHeight = 20;
var x = 100;
var y = 100;
var text='It was the best of times, it was the worst of times, it was the age of wisdom, it was the age of foolishness, it was the epoch of belief, it was the epoch of incredulity, it was the season of Light, it was the season of Darkness.';
context.font='12px verdana';
var height=wrapTextVCentered(context,text,x,y,maxWidth,lineHeight,true);
var y=(canvas.height-height)/2;
wrapTextVCentered(context,text,x,y,maxWidth,lineHeight,false);
context.strokeStyle='green';
context.strokeRect(x,y,maxWidth,height);
function wrapTextVCentered(context,text,x,y,maxWidth,lineHeight,measureOnly){
var height=0;
var convtext = text.replace(/\n/g, ' |br| ');
var words = convtext.split(' ');
var line = '';
context.textBaseline='top';
for(var n = 0; n < words.length; n++){
var newline = false;
if (words[n].indexOf("|br|") > -1) newline = true;
var metrics = maxWidth;
var testWidth = maxWidth;
var testLine = line + words[n] + ' ';
if (context.measureText){
metrics = context.measureText(testLine);
testWidth = metrics.width;
}
if ((testWidth > maxWidth && n > 0) || newline){
if(!measureOnly){ context.fillText(line, x, y); }
if (!newline) line = words[n] + ' ';
if (newline) line = "";
y += lineHeight;
height += lineHeight;
} else {
line = testLine;
}
}
if(!measureOnly){ context.fillText(line, x, y); }
height += lineHeight;
return(height);
}
body{ background-color: ivory; }
#canvas{border:1px solid red; margin:0 auto; }
<h4>Vertically centered paragraph on canvas</h4>
<canvas id="canvas" width=350 height=350></canvas>
I am new to javascript so sorry if my mistake is obvious! I am trying to draw an ellipse using the canonical form equation.
<html>
<body>
<canvas id="myCanvas" width="400" height="400" style="border:1px solid #000000;">
</canvas>
<script language="javaScript">
var c=document.getElementById("myCanvas");
var ctx=c.getContext("2d");
var HEIGHT = ctx.height;
var WIDTH = ctx.width;
function transform(p){
return [ WIDTH/2 + p[0], HEIGHT/2 - p[1]];
}
var a = 70; //length parallel to x axis
var b = 30; //length parallel to y axis
var h = 150 - WIDTH/2; //when tranformed this gives the pixel 150
var k = -HEIGHT/2 - 100; //when transformed this gives pixel 100
function y(x){
return b*Math.sqrt(1 - Math.pow((x - h)/a, 2)) + k;
}
var dx = a/2/100 ; //each quadrant is broken into 100 segments
var pOld = [h - a/2, k]; //starting point
var pNew = [0,0];
var x1 = 0;
var x2 = 0;
var y1 = 0;
var y2 = 0;
var temp = [0,0];
for (var i = 0; i < 100; ++i){
pNew[0] = pOld[0] + dx;
pNew[1] = y(pNew[0]);
temp = transform(pOld);
x1 = temp[0]; y1 = temp[1];
temp = transform(pNew);
x2 = temp[0]; y2 = temp[1];
ctx.moveTo(x1, y1); ctx.lineTo(x2, y2); //x1, y1 -> x2, y2
ctx.moveTo(x1, -y1); ctx.lineTo(x2, -y2); //x1,-y1 -> x2,-y2
ctx.moveTo(-x1, y1); ctx.lineTo(-x2, y2); //-x1,y1 -> -x2, y2
ctx.moveTo(-x1, -y1); ctx.lineTo(-x2, -y2); //-x1,-y1 -> -x2,-y2
pOld = pNew;
}
ctx.lineWidth = 2;
ctx.strokeStyle = "#232323";
ctx.stroke();
</script>
</body>
</html>
You values are NaN (Not-a-Number). Change these lines:
var HEIGHT = ctx.height;
var WIDTH = ctx.width;
to
var HEIGHT = c.height;
var WIDTH = c.width;
and you get proper Numbers. However, your y value is outside the canvas area - you will see this if you console.log the values. There seem to be some issues with the math in general which I don't address here, but in relation to canvas you should be one step further.
I'm trying to draw a red circle where my mouse clicks but nothing is drawn. I can follow my x,y coordinates being the ones I click. If I put constant values for x,y in the arc method a circle is displayed. What am I doing wrong?
var currColor = "#FF0000";
var currSize = 20;
window.onload = function() {
var theCanvas = document.getElementById('my_canvas');
theCanvas.addEventListener("click", CircleOnClick, false);
}
function Cell(row, column) {
this.row = row;
this.column = column;
}
function getCursorPosition(e) {
var x;
var y;
if (e.pageX != undefined && e.pageY != undefined) {
x = e.pageX;
y = e.pageY;
}
else {
x = e.clientX + document.body.scrollLeft + document.documentElement.scrollLeft;
y = e.clientY + document.body.scrollTop + document.documentElement.scrollTop;
}
var cell = new Cell(x, y);
return cell;
}
function CircleOnClick(e) {
var canvasElement = document.getElementById('my_canvas');
if (canvasElement && canvasElement.getContext) {
var ctx = canvasElement.getContext("2d");
if (ctx) {
var cell = getCursorPosition(e);
var x = parseInt(cell.row);
var y = parseInt(cell.column);
//Start drawing
ctx.fillStyle=currColor;
ctx.beginPath();
console.log("x" + x);
console.log("y" + y);
console.log("Current color" + currColor);
console.log("Current size" + currSize);
ctx.arc(x,y,currSize,0,Math.PI*2,true);
ctx.closePath();
ctx.fill();
}
}
}
Using fabric.js, this would take something like 10 lines:
HTML:
<canvas id="c" width="300" height="300" style="border:1px dotted #ccc"></canvas>
JS:
var canvas = new fabric.Canvas('c', { selection: false });
canvas.observe('mouse:up', function(e) {
var pointer = canvas.getPointer(e.memo.e);
canvas.add(
new fabric.Circle({
radius: 10,
left: pointer.x,
top: pointer.y,
fill: 'red',
selectable: false
}));
});
Here's a demo on jsfiddle.
Your code works fine for me. Are you sure that your HTML canvas element has an id="my_canvas" attribute?
Or could you show your HTML code too?
If you are testing in Internet Explorer 9, your HTML document must start with <!DOCTYPE html> and you must also comment out your console.log rows unless you have the Developer Tools enabled (F12):
ctx.fillStyle=currColor;
ctx.beginPath();
//console.log("x" + x);
//console.log("y" + y);
//console.log("Current color" + currColor);
//console.log("Current size" + currSize);
ctx.arc(x,y,currSize,0,Math.PI*2,true);
ctx.closePath();
ctx.fill();