I have a chart.js Donut chart in the center of which I have to show a value.There is a date field which refreshes the chart thereby affecting the central value.
var text = dataTxt,
textX = Math.round((width - ctx.measureText(text).width) / 2),
textY = height / 2;
ctx.fillText(" ", textX, textY);//attempting to write blank value.
ctx.fillText(text, textX, textY); //this writes the value.
ctx.save();
Problem is that on subsequent update of the chart the central area is not cleared & the value gets written over the old one.
For this I added the line ctx.fillText(" ", textX, textY); in above code but to no effect.
Any Ideas on how to clear up the area before the text is written there?
There is a HTML/CSS solution to write the data in the center but I cant use that since it doesnt export the central data when chart is downloaded as PNG.
In typical use cases people don't attempt to "undo" their changes on the Canvas - it's far easier to just clear the Canvas and start drawing all over again.
ctx.clearRect(0, 0, canvas.width, canvas.height);
// Do my drawing again
myChart.update(); // With chart.js this triggers a redraw.
In your case I think you're making the mistake of thinking that the Canvas saves the text image and lets you alter it in subsequent drawings. Think of it like Microsoft Paint - once that text is on the image, you're not going to be able to get rid of it easily without undo'ing.
Related
I am starting to work with the Javascript canvas (CanvasRenderingContext2D) and I am finding centering text really hard to do. I am using the following piece of code to center the text both horizontally and vertically:
ctx.textAlign = "center";
ctx.textBaseline = "middle";
I know I can use ctx.measureText() to get the width of a string but the height is not available in the returned object. I tried using advanced text metrics but they seem to be a new thing and my Firefox build (latest in the Ubuntu store) doesn't support it yet and I want my webpage to be at least compatible with 1 year-old browser versions.
I am being able to center the text right now but the problem is centering two objects (an image and a piece of text), like the second situation in the following image, where the objects must be centered together (like they were a single object that contained both the image and the text):
https://drive.google.com/file/d/1_P9826O1x0bFhRqPEKz_AB18iYNPa5CP/view?usp=sharing
The only way I can think of doing that is by knowing the height of the text, because I need to calculate both the position of the image and the text (pseudo-code):
//I can do this
image.x = (canvas.width / 2) - image.width;
text.x = (canvas.width / 2) - text.width;
//But not this
image.y = (canvas.height / 2) - (image.height / 2) - (text.height / 2);
//Do this with top-left text align
text.y = (canvas.height / 2) + (image.height / 2) - (text.height / 2)
Sadly, the only ways I found of getting the height of the text was through "it kinda works" approximations and rendering the text to a canvas and getting its pixel data to see the lowest pixel, which is bad for performance.
What can I do to fix this and get the text height in a better way? Is ti possible to center them without even having the height of the text? I would like to keep using the canvas element because this will be for a game, so I can't use HTML and CSS to center objects. Please, only use plain Javascript (no things like query).
Thanks in advance.
So I have a game(that is more of a map) that loads a bunch of tiles and places them together. The tiles load just fine, but I'd like to move the viewport. I've looked into this subject, and I have a function that checks the keyboard. If 'd' is being pressed, I'd like to move the canvas so the viewport sees something different.
So far, the function for moving the canvas right looks like this:
function moveRight() {
ctx.translate(3000, 0);
imageSearch();
};
Where the imageSearch function updates the canvas. The updating, and loading etc. works fine, I just can't figure out how to move the canvas. Help would be appreciated, thanks in advance.
EDIT:
Here's a JSFiddle that 1j01 fixed for me: jsfiddle.net/jujhp0yv/1
The canvas still doesn't move though, so I'm still awaiting your responses :)
Try storing the view port in a variable.
var view = {x: 0, y: 0};
Then, at the beginning of your draw loop / render function, save the canvas state and translate to the view port.
ctx.save();
ctx.translate(view.x, view.y);
If you want view.x and view.y to represent the center of the view, instead translate like this:
ctx.translate(view.x - canvas.width/2, view.y - canvas.height/2);
At the end of your draw loop / render function, restore the state so translations won't stack up.
ctx.restore();
Now you should be able to modify view.x and view.y to move the view. (e.g. view.x += 5)
I was making a small JavaScript game when I ran into this small issue: The text is not centrally aligned.
A simple example:
var txt="Lorem Ipsum";
context.fillText(txt,100,100);
Now the problem is that the beginning of the text is at the point 100,100. So later when I change the value of txt into a longer sentence, it is still drawn staring from 100,100 , reducing the aesthetic appeal of the program.
My question is, is there a way to draw text in such a way that the coordinates given mark the center of the text and not the beginning?
You can use textAlign:
context.textAlign = "center";
You can use the measureText() method of the context, to get the width of the text, and then make adjustments based on it. So let's suppose that you want to put it in the center of the canvas, then
(canvas.width / 2) - (ctx.measureText(txt).width / 2)
gives the position where the text should go. In the vertical case:
(canvas.height / 2) - (ctx.measureText(txt).height / 2)
Where canvas is the HTML5 Canvas itself, and ctx is the 2DContext object:
var canvas = document.getElementById("myCanvas");
var ctx = canvas.getContext("2d");
I've built a very simple line graph using canvas (pulling in data from google analytics). I'm having a few small issues. First off, the plot line is jagged:
http://jsfiddle.net/uJQ7K/
I'm just using lineTo for this:
ctx.lineTo((i*cellWidth) + cellWidth + padding,(tableHeight + padding) - data[i].v);
I've read that using splines can fix this but surely there's a way to draw a straight line out of the box?
Other problems I'm having are changing one attribute like strokeStyle changes all the strokes on a page. How do I just change the stroke of the plot line and not affect the appearance of the grid?
Have you tried changing your line cap?
cxt.lineCap = 'round';
EDIT -
By adding ctx.beginPath(); before your ctx.lineCap you will get a better result -
ctx.beginPath();
ctx.lineCap = 'round';
http://jsfiddle.net/uJQ7K/1/
I am following a tutorial from Dev.Opera about HTML5 Painting application and trying to improve it by adding a text tool that prompts user of what text they wanted to input after clicking on coordinate.
E.g. User clicked on coordinate 100,200 , a prompt will ask what text they wanted to show and after user entered the text, it should draw it on canvas.
I knew my browser support canvas fillText and strokeText function, because when I load this web the text shows.
On the tutorial I follow, Dev.Opera creates a temp canvas on the real canvas so that images (shapes and text) are supposedly drawn to temp canvas and then transferred to real canvas by img_update() method.
// This function draws the #imageTemp canvas on top of #imageView,
// after which #imageTemp is cleared. This function is called each time when the
// user completes a drawing operation.
function img_update () {
contexto.drawImage(canvas, 0, 0);
context.clearRect(0, 0, canvas.width, canvas.height);
}
I tried to do fillText on context like this:
context.fillText(textVar, x, y);
img_update();
and this does not draw the text, while:
contexto.fillText(textVar, x, y);
draws it perfectly.
I had expand the program to draw circle, polyline, and fills and all of them works perfectly on the context without having to draw them at contexto.
How can I force the text to be drawn at context and then transfer it using img_update()?
maybe fill style is set so that you do not see the text?