Removing text in HTML5 Canvas? - javascript

I'm working on a HTML5 Canvas project and have some text drawn on the screen. Right now, it appears and just stay there, but what I need is for it to disappear after a few seconds so that every time it's called it's not just new text being drawn on top of the old text.
I tried clearRect() but that completely clears the entire rectangle and removes some of my background too, which I don't want.
Is there a way to do this?
I'm drawing the text with this basic function:
function drawText() {
ctx.font = "30px Arial";
ctx.fillText("Please wait...", 575, 130);
}

<!DOCTYPE HTML>
<html>
<head>
<style>
body {
margin: 0px;
padding: 0px;
}
</style>
</head>
<body>
<button onclick="showTheText()">Click to show text</button>
<canvas id="myCanvas" width="578" height="200"></canvas>
<script>
var canvas = document.getElementById('myCanvas');
var context = canvas.getContext('2d');
function showTheText() {
var myText = {
text: 'Hello World',
x: 0,
y: 75,
fill: 1
};
drawText(myText, context);
// wait one second before starting animation
setTimeout(function() {
animate(myText, canvas, context);
}, 1000);
}
function drawText(myText, context) {
context.font="30px Arial";
context.fillStyle="rgb(0, 0, 0, " + myText.fill + ")";
context.fillText(myText.text, myText.x, myText.y);
}
function animate(myText, canvas, context) {
// clear
context.clearRect(0, 0, canvas.width, canvas.height);
// !!!!!!!! redraw your background !!!!!!!!
// then redraw your text with new opacity
myText.fill -= .1;
drawText(myText, context);
// request new frame
if (myText.fill > -.1) {
setTimeout(function() {
animate(myText, canvas, context);
}, 2000 / 60);
}
}
</script>
</body>
</html>
Hope this can help you. What it does it immediately draws the text (and the rest of your background, you didn't provide it), then sets up a recursive timeout that will clear the rect, redraw your background, decrement the amount of opacity to apply to the text's fill, and redraw the text as well. You can slow it down by changing the time of the last setTimeout.
I adapted it from this example: https://www.html5canvastutorials.com/advanced/html5-canvas-animation-stage/

you can create a simple function to delete ,
you will need some values. For example, font height. width of character ... etc ,
for example in this case , you can use the following function , With few modifications :
function removeText(x,y,txt_length,font_height,char_width,ctx) {
ctx.clearRect(x, y-font_height ,char_width*txt_length,font_height);
}
and this function for write your string :
function drawText(x,y,text,ctx) {
ctx.font = "30px Arial";
ctx.fillText(text,x,y);
}
The same parameters x and y are passed to the functions and txt_length = text.length;

Once you've drawn text to canvas, it's no longer text - it's just a bunch of pixels! Since those pixels overwrite what is already there, there's no way to delete just the text.
Generally what you can do is re-draw the entire scene without the text, if you want to get rid of it.
You could also try re-drawing the text in the same position using the background color, which would remove the text, but this only works if the text is on a solid background.

To achieve expected use below option of fillStyle in clearText function
Create another function clearText with fillStyle white color with same text and x , y coordinates
Call clearText function from the drawText
var canvas = document.getElementById("myCanvas");
var ctx = canvas.getContext("2d");
function drawText() {
clearText()
ctx.font = "30px Arial";
ctx.fillStyle = "black";
ctx.fillText("Please wait...", 575, 130);
}
function clearText() {
ctx.font = "30px Arial";
ctx.fillStyle = "white";
ctx.fillText("Please wait...", 575, 130);
}
<button onclick="drawText()">draw text</button><br>
<canvas id="myCanvas" width="800" height="800"
style="border:1px solid #d3d3d3;">
Your browser does not support the canvas element.
</canvas>
code sample - https://codepen.io/nagasai/pen/oqOXxz

Related

The countdown timer is not working properly when I insert few numbers such as 31,41,51,61

I want to show a countdown timer using JavaScript. However when I insert the current value to be 31,41,51,99,61,81 and few other numbers I am unable to get the Arc based on the inserted current value. The Arc should display the current value. As the number gets reducing, closer to Zero, the Arc should keep moving towards completing the circle.
I tried using HTML5 Canvas, I almost close to getting the answer but it's throwing some error.
The fields should have Maximum Value input text field and Current Value text field and a button which on clicked should display the Current Value Arc inside Canvas Element. Please help
<!-- Click event function, works when button is clicked -->
function clickevent()
{
var max=document.getElementById("maxsec").value;
var curr=document.getElementById("currsec").value;
myFunction(max,curr);
}
//This is the
function myFunction(maxvalue,currentvalue) {
//alert(maxvalue + ' ' + currentvalue);
if (currentvalue<=maxvalue)
{
var x = (2*3.14*currentvalue/maxvalue);
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
ctx.clearRect(0, 0, c.width, c.height);
ctx.font="15px Georgia";
ctx.textAlign = "center";
ctx.fillText(currentvalue,c.width/2, c.height/2);
ctx.beginPath();
ctx.arc(75, 75, 50, x, 2 * Math.PI);
// ctx.lineWidth = 10;
// line color
ctx.strokeStyle = 'black';
ctx.stroke();
}
if (maxvalue==currentvalue)
{
ctx.clearRect(0, 0, c.width, c.height);
ctx.font="15px Georgia";
ctx.textAlign = "center";
ctx.fillText("Time Up",c.width/2, c.height/2);
ctx.textAlign="center";
}
}
<!DOCTYPE html>
<html>
<body>
<div>
Max Second: <input type="text" id="maxsec" value="300"><br/>
Current Second: <input type="text" id="currsec" value="150">
<button onclick="clickevent()">Click me</button>
<br/>
//This is the canvas section where the Arc or the curvature will be displayed.
<canvas id="myCanvas" width="150" height="150" style="border:1px solid #d3d3d3;">
Your browser does not support the HTML5 canvas tag.</canvas>
</div>
</body>
</html>
You are passing the values as a string into the function instead of number, if you change the below lines of code, it works fine!
JS:
var max=parseInt(document.getElementById("maxsec").value);
var curr=parseInt(document.getElementById("currsec").value);
myFunction(max,curr);
JSFiddle Demo
Please use this attempt of making your timer using setTimeout() function as a reference and build your code!
JSFiddle Demo

Gradually fade to colour using JS

I am trying to make a rectangle gradually change its colour (fade) from yellow to white using Javascript after a button is pressed. Sadly my code does not work. Could you help me figure out what is wrong with the code and how to fix it?
I have just begun studying Javascript. Sorry, if this question is stupid. Thank you in advance.
This is my code:
<!DOCTYPE html>
<html>
<body>
<canvas id="myCanvas" width="300" height="150" style="border:1px solid #d3d3d3;">
Your browser does not support the HTML5 canvas tag.</canvas> // create canvas to work with
<button onclick="fade(ctx)">Change the colour!</button>
<script>
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d"); //set context
ctx.rect(20, 20, 150, 100); // draw a rectangle
ctx.stroke(); // with border
ctx.fillStyle="#FFFF00"; // fill with yellow
ctx.fillRect(20,20,150,100);
function fade(ctx) { // fade function responsible for changing colour
var dom = getElementById(ctx), level = 1; // new object based on rectangle object, initial iterator is set to 1
function step() { // inner step function
var h = level.toString(16);
dom.fillStyle = '#FFFF' + h + h; // construct a new colour using h variable
if (level < 15) {
level += 1;
setTimeout(step, 100); // do this after every 100 ms
}
}
setTimeout(step, 100);
}
</script>
</body>
</html>
You almost have it with your code though. You are passing the context into the function already so no need for the getElementById(ctx) bit. In fact that will give you an error so remove that line from your code. Instead directly set the fillStyle on the ctx variable like this:
ctx.fillStyle = '#FFFF' + h + h;
and you also need to redraw the rectangle, so add this line:
ctx.fillRect(20,20,150,100);
after you set the colour. And that will do it.

Text position on canvas is different in FireFox and Chrome

I need to draw a text string at a precise position on HTML5 canvas.
Here's my test code:
<!DOCTYPE html>
<html>
<body>
<canvas id="mainCanvas" width="320" height="240" style = "border:1px solid #d3d3d3;">
Your browser does not support the HTML5 canvas tag.
</canvas>
<script>
window.onload = function() {
var canvas = document.getElementById("mainCanvas");
var ctx = canvas.getContext("2d");
ctx.textBaseline = "top";
ctx.font = '100px Arial';
ctx.textAlign = 'left';
ctx.fillStyle = 'rgba(0, 0, 0, 255)';
ctx.fillText('Test', 0, 0);
}
</script>
</body>
</html>
The margin at the top is different in Chrome and Firefox:
I'm going to draw other elements (e.g. images, shapes) on the canvas, and I need to make sure the text appears at the same position in all browsers. Is it possible?
Cause
As #iftah says: This mis-alignment is caused by a Firefox bug.
Please add your voice to the Firefox's bug page so they fix it soon.
Workaround
(Unfortunately), The workaround is to draw the text on a second canvas and scan that pixel data to find the topmost & leftmost pixel of the text.
Then draw the text on the main canvas but pulled upward and leftward by the calculated pixel offsets.
Here is annotated code and a Demo:
// canvas vars
var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
var cw=canvas.width;
var ch=canvas.height;
// test vars
var text='Test';
var fontsize=100;
var fontface='arial';
drawTextAtXY(0,0,text,fontsize,fontface,'black');
function drawTextAtXY(x,y,text,fontsize,fontface,fill){
// find the leftmost & topmost pixel of the text
var minXY=getTextTop(text,fontsize,fontface);
// set the font styles
ctx.textBaseline='top';
ctx.font=fontsize+'px '+fontface;
ctx.fillStyle=fill;
// draw the text
// Pull the text leftward and topward by minX & minY
ctx.fillText(text,x-minXY.x,y-minXY.y);
}
function getTextTop(text,fontsize,fontface){
// create temp working canvas
var c=document.createElement('canvas');
var w=canvas.width;
var h=fontsize*2;
c.width=w;
c.height=h;
var cctx=c.getContext('2d');
// set font styles
cctx.textBaseline='top';
cctx.font=fontsize+'px '+fontface;
cctx.fillStyle='red';
// draw the text
cctx.fillText(text,0,0);
// get pixel data
var imgdata=cctx.getImageData(0,0,w,h);
var d=imgdata.data;
// scan pixel data for minX,minY
var minX=10000000;
var minY=minX;
for(var y=0;y<h;y++){
for(var x=0;x<w;x++){
var n=(y*w+x)*4
if(d[n+3]>0){
if(y<minY){minY=y;}
if(x<minX){minX=x;}
}
}}
// return the leftmost & topmost pixel of the text
return({x:minX,y:minY});
}
body{ background-color: ivory; }
#canvas{border:1px solid red; margin:0 auto; }
<h4>Text drawn exactly at specified X,Y</h4>
<canvas id="canvas" width=300 height=200></canvas>
You can fix it easily.
you can use textBaseline = "middle";
and must use transform to 50px of top
means:
<canvas id="mainCanvas" width="320" height="240" style = "border:1px solid #d3d3d3;">
Your browser does not support the HTML5 canvas tag.
</canvas>
<script>
window.onload = function() {
var canvas = document.getElementById("mainCanvas");
var ctx = canvas.getContext("2d");
ctx.textBaseline = "middle";
ctx.font = '100px Arial';
ctx.textAlign = 'left';
ctx.fillStyle = 'rgba(0, 0, 0, 1)';
ctx.save();
ctx.transform(1, 0, 0, 1, 0, 50);
ctx.fillText('Test', 0, 0);
ctx.restore();
}
</script>
A another bug is in your code: rgba(0, 0, 0, 255)
fourth number in rgba must be between 0-1 for example 0.75.
why I write .save() and .restore() ?
for reset transform and clear after use it.
Of course you can use
ctx.fillText('Test', 0, 50);
Instead
ctx.save();
ctx.transform(1, 0, 0, 1, 0, 50);
ctx.fillText('Test', 0, 0);
ctx.restore();
This appears to be a bug in Firefox dating back to 2012 and still not fixed!
See https://bugzilla.mozilla.org/show_bug.cgi?id=737852
Edit:
Setting the baseLine to "alphabetic" (the default) results in both Chrome and Firefox having the same vertical location for the text.
Edit:
Unfortunately, the vertical location isn't the only difference between Firefox and Chrome. Changing the string to "Testing" shows clearly that not only is the vertical location different, but also the space between the letters is slightly different - resulting in different width of the text.
If you really must have pixel perfect location AND size of the text maybe you should use Bitmap fonts
As stated in other answer it's some king of bug (or maybe just a different implementation). textBaseline bottom and Y position to 100 can fix it.
<canvas id="mainCanvas" width="320" height="240" style = "border:1px solid #d3d3d3;">
Your browser does not support the HTML5 canvas tag.
</canvas>
<script>
window.onload = function() {
var canvas = document.getElementById("mainCanvas");
var ctx = canvas.getContext("2d");
ctx.textBaseline = "bottom";
ctx.font = '100px Arial';
ctx.textAlign = 'left';
ctx.fillStyle = 'rgba(150, 50, 0, 1)';
ctx.fillText('Test', 0, 100);
}
</script>
In general: Use baseline bottom and increase Y position the font size amount

What does beginPath() and closePath() do exactly?

The question that I have is with context.beginPath() and context.closePath(). The code below will draw a circle in an arc around the screen until it disappears followed by a small dot which I would comment out because it is a .jpg which I do not know how to include.
My question is exactly what does the beginPath() do and also the closePath() do?
If I comment them out I get a wild result other than what I am expecting. I have looked on the internet but I have not seen the results like this.
Code with a question:
function drawTheBall() {
context.fillStyle = "#00AB0F"; //sets the color of the ball
context.beginPath();
context.arc(ball.x,ball.y,10,0,Math.PI*2,true); //draws the ball
context.closePath();
context.fill();
}
Working code below
HTML-Javascript
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>CH5EX10: Moving In Simple Geometric Spiral </title>
<script src="modernizr.js"></script>
<script type="text/javascript">
window.addEventListener('load', eventWindowLoaded, false);
function eventWindowLoaded() {
canvasApp();
}
function canvasSupport () {
return Modernizr.canvas;
}
function canvasApp() {
var radiusInc = 2;
var circle = {centerX:250, centerY:250, radius:2, angle:0, radiusInc:2}
var ball = {x:0, y:0,speed:.1};
var points = new Array();
theCanvas = document.getElementById('canvasOne');
context = theCanvas.getContext('2d');
var pointImage = new Image();
pointImage.src = "point.png"; <-- Comment this line out
if (!canvasSupport()) {
return;
}
function erraseCanvas() {
context.clearRect(0,0,theCanvas.width,theCanvas.height);
}
function drawPathPoints() {
//Draw points to illustrate path
points.push({x:ball.x,y:ball.y});
for (var i= 0; i< points.length; i++) {
context.drawImage(pointImage, points[i].x, points[i].y,1,1);
}
}
function drawTheBall() {
context.fillStyle = "#00AB0F"; //sets the color of the ball
context.beginPath();
context.arc(ball.x,ball.y,10,0,Math.PI*2,true); //draws the ball
context.closePath();
context.fill();
}
function buildBall() {
ball.x = circle.centerX + Math.cos(circle.angle) * circle.radius;
ball.y = circle.centerY + Math.sin(circle.angle) * circle.radius;
circle.angle += ball.speed;
circle.radius += radiusInc;
}
function drawScreen () {
erraseCanvas();
buildBall();
drawPathPoints();
drawTheBall();
}
function gameLoop() {
window.setTimeout(gameLoop, 20);
drawScreen()
}
gameLoop();
}
</script>
</head>
<body>
<div style="position: absolute; top: 50px; left: 50px;">
<canvas id="canvasOne" width="500" height="500">
Your browser does not support the HTML 5 Canvas.
</canvas>
</div>
</body>
</html>
beginPath()
beginPath() clears the current internal path object and its sub-paths, which accumulates path operations such as line, rect, arc, arcTo and so on, regardless of if they are filled or stroked.
closePath()
closePath() connects the current path, or sub-path, position with the first point on that path created either with beginPath() or moveTo() if that was used. The latter creates a sub-path on the current main path and only this sub-path gets closed.
Some methods do a closePath() implicit and temporary for you such as fill() and clip() which means it's not needed for those calls. In any case, it must be called before a stroke() (or fill(), if you chose to use that) is called.
One can perhaps understand this method better if one think of it as "closing the loop" rather than ending or closing the path [object] which it doesn't.
BeginPath will start a new path, unlike moveTo which will begin a new subpath
Close path will close the path. it probably isn't needed unless you want stroking to stroke the entire path without a gap
Close Path:
//An Open Box
ctx.moveTo(0 , 0);
ctx.lineTo(0 , 100);
ctx.lineTo(100, 100);
ctx.lineTo(100, 0);
ctx.stroke();
ctx.translate(150, 0);
//A closed box
ctx.moveTo(0 , 0);
ctx.lineTo(0 , 100);
ctx.lineTo(100, 100);
ctx.lineTo(100, 0);
ctx.closePath();
ctx.stroke();

Clear canvas button in Javascript/HTML not working

So my code displays an html page with some text on it and then below that I have a "clear Canvas" button which I would like to have clear the canvas once pushed and then be able to draw on this blank canvas. My clear canvas button isn't working, it isn't doing anything once pushed. I'm using a call back in order to perform the canvas clear and the html file is connected to a javascript file which then draws things on the new cleared canvas. The first code here is the .html file with the canvas that is being cleared that also has the.js file joined to it.
I tried context.Rect(x, y, w, h);
and canvas.width.canvas.width;
and neither seem to work. I'm using Chrome
<html><head></head>
<h3> </h3>
<body >
<canvas id="main" width="300" height="500"></canvas>
<script>
var canvas = document.getElementById("main");
var context = canvas.getContext('2d');
context.fillStyle = "#008000";
context.rect(0,0,300,300);
context.fill();
</script>
</body></html>
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="user-scalble=no,initial-scale=1.0,maximum-scale=1.0" />
<style>
body { padding:10px; margin:0px; background-color: #FF9; }
#main { margin: 10px auto 0px auto; }
</style>
<script src=".js"></script>
</head>
<body >
<button id="clear">Clear Canvas</button><br>
<canvas id="main" width="300" height="500"></canvas>
</body>
</html>
//end of .html file
// JavaScript Document
// wait until window is fully loaded into browser
window.onload = function()
{
// so smart phone does not move/resize image when touched
document.ontouchmove = function(e)
{
e.preventDefault();
}
var canvas = document.getElementById('main');
// Number of pixels used by the Clear button above canvas
var canvasTop = canvas.offsetTop;
var context = canvas.getContext('2d');
var lastX, lastY;
context.strokeStyle = #FA8072;
context.lineCap = 'round';
context.lineJoin = 'round';
context.lineWidth = 8;
context.fill();
// Function to Clear the Canvas
function clear()
{
context.fillStyle = 'blue'
context.rect( 0, 0, 300, 500);
context.fill();
}
// Function Dot (to start a new line or just a point)
function dot(x,y)
{
context.beginPath();
context.fillStyle = '#D2691E';
// draw tiny circle
context.arc(x,y,1,0, Math.PI*2, true);
context.fill();
context.closePath();
}
// Handle the Clear button
var clearButton = document.getElementById('clear');
// set callback funct. clear()for future touch events
clearButton.onclick = clear;
clear(); // do a clear canvas now
} // end window.onload
You've got a typo on this line:
context.strokeStyle = #FA8072;
You need quotes:
context.strokeStyle = '#FA8072';
With that fixed it seems to work: http://jsfiddle.net/eMSXU/
(By the way, you might like to press the "Tidy Up" button in the fiddle to see how your code should've been indented...)

Categories