I am trying to draw a sharp thin rectangle using canvas control.I want the canvas background to get loaded with an image and in foreground with some text .
Though i am able to set the color and text they are somehow appearing blurred.Is there a way to fix this issue ?
And i want to apply an image as background image for each canvas rectangle i will draw.These rectangels will appear a in a div control.So wherever there is a canvas rectangle i want its background image to be filled with the image i choose.entire div will not be filled with canvas rectangles but only half of it.Is there a way whether we can have one image for all the canvas rectangles i will draw or do ineed to draw it for every rectangle ?
html:
<div id="divBoard" >
<canvas id="canvasBoard" />
</div>
javascript:
canvas = document.getElementById("canvasBoard");
if (canvas.getContext) {
var context = canvas.getContext("2d");
}
context.fillStyle = "green";
context.fillRect(x, y, width,height);
context.font = "5px tahoma";
context.fillStyle = "black";
context.fillText("cell"+i, x, y + width);
this is the image displayed after executing my code
I have experienced the same issue with fonts not rendering as sharply on a canvas. In my project I did a workaround by placing the font in a separate DIV and overlaying it on the canvas using an appropriate z-index. This approach worked very well for me.
Have you tried adding 0.5 to x and y? The html5 canvas uses antialiasing so if you want "crisp" lines, you need to draw "in between" the pixels.
You will find a good explanation on how this works in mozilla developer reference page for lineWidth
PS. also see this question
Related
I am creating a game, I need to achieve a perfect canvas line on HTML5 under different types of screen resolutions and zooms.
To easily understand I am talking about, simply paste the two different codes into an HTML file(not jsFiddle, as it is too small to notice):
With fabric.js:
<canvas id = "c" width = "600" height = "300"></canvas>
<script src = "https://rawgit.com/kangax/fabric.js/master/dist/fabric.js"></script>
<script> var c=document.getElementById("c");
var context=c.getContext("2d");
new fabric.Canvas('c', { selection: false });
context.moveTo(0, 0);
context.lineTo(0, 300);
context.stroke();
</script>
Without fabric.js:
<canvas id = "c" width = "600" height = "300"></canvas>
<script> var c=document.getElementById("c");
var context=c.getContext("2d");
context.moveTo(0, 0);
context.lineTo(0, 300);
context.stroke();
</script>
Now as you can see, fabric.js removes the blurriness that you get under different kind of browser zooms(Mouse wheel) once the page loads.
I have two problems with it though:
1) Once you click on the canvas the line is gone
2) It's a big framework/library, and I only need it to draw lines(Maybe not if it can achieve the same thing with PNG images)
So, is there a way to achieve the same sharpness result with a clean, short javascript code, without using fabric.js?
If not, how can I fix the clicking problem?
Thanks.
All lines drawn on the canvas are automatically given anti-aliasing to lessen the visual effect of "jaggies". This anti-aliasing also makes the line appear blurry.
If you ONLY are drawing horizontal and vertical lines you can make them crisp:
Before drawing the lines, context.translate(0.50,0.50),
Draw the lines using only integer coordinates,
After drawing the lines, context.translate(-0.50,-0.50),
If you are drawing non-horizontal and non-vertical lines, then you can use Bresenhan's Line Algorithm to draw crisp lines on the canvas by drawing lines pixel-by-pixel. This previous Q&A has example code using Bresenhan's algorithm.
I'm having a bit of trouble here to develop this functionality since it must work on IE9+ so css clip-path is not an option ( http://caniuse.com/#feat=css-clip-path ).
The issue:
I need to create a grid composed of 6 elements.
Each element is an image.
The images can be different according to user answers before getting to the grid page.
Eeach element / image must be clicable and will acquire a "selected" class that will overlay div with text and background image.
image:
What is the best way to achieve this?
One way to do this could be to save out each combination of the six images you require into one big image. Then, depending on the user's answer combination, you insert the corresponding image as a background-image of a div. You then overlay click-able hotspots within the same div that roughly correlate to the dividing edges.
This may however not be the most practical solution and largely depends on how many answers/images you are dealing with.
Alternatively you could draw SVG shapes and set their fills to the images you require.
I can recommend Raphael.js as a starting point. You should be able to find what you need in the documentation
Another option would be to use HTML5 canvas:
http://jsfiddle.net/julienbidoret/GKP7X/1/
(credit goes to julienbidoret for the jsfiddle)
Javascript:
var canvas = document.getElementById('c');
var ctx = canvas.getContext('2d');
var img = document.createElement('IMG');
img.onload = function () {
ctx.save();
ctx.beginPath();
ctx.moveTo(20, 0);
ctx.lineTo(240, 0);
ctx.lineTo(220, 240);
ctx.lineTo(0, 240);
ctx.closePath();
ctx.clip();
ctx.drawImage(img, 0, 0);
ctx.restore();
}
img.src = "http://upload.wikimedia.org/wikipedia/commons/2/2b/Clouds.JPG";
HTML:
<canvas id="c" width="300" height="300" ></canvas>
Both SVG and canvas are supported in IE9.
I have one canvas with some text and i want to re-size it in all directions but problem is that text content inside that canvas is getting blurred if i make it re-sizable by using css properties.
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
ctx.font = "30px Arial";
ctx.fillText("Hello World",10,50);
I have tried jquery re-sizable with container to canvas and resize canvas by using css but getting text content's height/width problem and also text is getting blurred.
can anyone help me please..
Yes, text has many small & tight curves whose flaws quickly become visible if you try to resize the original text. Therefore, resizing text-especially resizing larger, will always result in the texts natural "jaggies" and anti-aliasing artifacts becoming more visible.
The usual approach to canvas is to treat everything on the canvas as redrawable. Using that approach, you could clear the canvas and redraw the text using an appropriately resized font.
If your text will always appear topmost on your canvas drawings, an alternative would be to place an SVG element on top of your canvas. SVG text scales well because it is vector based, rather than pixel based. You could use the svg translate+scale to position & resize the svg text according to your scale factor. Here's a link showing how it's done: http://msdn.microsoft.com/en-us/library/gg589508(v=vs.85).aspx
I am writing a colouring game for small children, where I have a black and white image shown on a canvas initially, and as the user moves the drawing tool (mouse) over the canvas, the black and white surface gets over-painted with the colour information from the corresponding coloured image.
In particular, on every mouse move I need to copy a circular area from the coloured image to my canvas. The edge of the circle should be a little blurry to better immitate the qualities of a real drawing tool.
The question is how to accomplish this?
One way I see is to use a clipping region, but this approach does not let me have blurry edges. Or does it?
So I was thinking about using an alpha mask to do that and copy only pixels that correspond to the pixels in the mask that have non zero alpha. Is it feasible?
My suggestion is to have your drawable canvas in front of the coloured image you wish to reveal. (You could use your coloured image as a CSS background image for the canvas.)
Initially have the canvas containing the black and white image with 100% opacity. Then, when you draw, actually erase the contents of the canvas to show the image behind.
Like this:
var pos_x, pos_y, circle_radius; // initialise these appropriately
context.globalCompositeOperation = 'destination-out';
context.fillStyle = "rgba(0,0,0, 1.0)";
// And "draw" a circle (actually erase it to reveal the background image)
context.beginPath();
context.arc(pos_x, pos_y, circle_radius, 0, Math.PI*2);
context.fill();
I would probably use multiple clipping regions with varying alpha (one dab for each) to mimic the effect you are after. Render the low opacity one first (paste using drawImage) and render the rest after that till you reach alpha=1.0.
Have you considered using radial gradients that go from an opaque color to a fully transparent one?
Here is a demo from Mozilla. The circles are drawn the way you need. - https://developer.mozilla.org/samples/canvas-tutorial/4_10_canvas_radialgradient.html
I've got a canvas that includes images, I'm re-drawing 1 pixel lower each time to give the effect of falling. I've got the images in an array and I just place them 1 pixel lower without recreating the image.
Is it possible to add a border dynamically to images that reach a certain point and if so, how?
Yes, all you have to do is draw a path outside the image and call ctx.stroke() to make the border.
So say the image has the coordinates x and y, with a width and height of w and h, you just do:
ctx.rect(x, y, w, h);
ctx.stroke();
Want a different colored border?
ctx.strokeStyle = 'blue';
Thicker?
ctx.lineWidth = 5;
If you know your images' size and location and as you draw them you probably do, You can use the .rect canvas method to draw a rectangle around the image.