How to draw rectangle with 1px border using html5 canvas? - javascript

I don't know why that white point appear at the bottom right corner of the created rectangle.
(Only visible in 21.0.1180.83 and .89 under WinXP)
It depends on the canvas height...
http://jsbin.com/ejeyef/1/

It probably has something to do with Subpixel rendering . Looking at your code, you do the following:
c.rect(10.5, 10.5, 100, 100);
Which means: "Draw a rectangle, with a size of 100x100px at the coordinates 10.5px from X, and 10.5px from Y". The screen/browser can't render a "half pixel", so it's always rounded somewhere. That might be the cause of your problem.
To fix this, simply don't use half values for this kind of things. This works fine:
c.rect(10, 10, 100, 100);

Related

How to flip/mirror a PIXI Graphics instance (drawRoundedRect)

I'm animating the height of a drawRoundedRect instance, however, because it starts drawing from the upper left corner, it's animating from top to bottom, and I need it to start from the bottom.
Is it possible to flip my graphics instance (I tried by setting the scale to inverse, but this doesn't render anything, perhaps it only works on sprites), or to start drawing a rounded rectangle from the bottom?
EDIT:
Okay so I found out it's possible to animate my height going in to the other direction by just multiplying my interpolated value by -1:
graphics.drawRoundedRect(
x,
y,
barsWidth,
interpolatedHeight * -1,
10
);
However, now the radius isn't working anymore, it's just drawing square rectangles..
TIA!
I am not entirely sure that I did understand the question but if a got it right, all you need to do is to change the pivot of the rectangle you are animating. In your case, pivot.y should be equal to the rectangle's height rectangle.pivot.y = rectangle.height. After you change the pivot you also need to position it /the rectangle/ accordingly, so it could retain its visual position rectangle.y += rectangle.pivot.y
a simple demo https://jsfiddle.net/4L1od09n/23/

Canvas Line Width changes when canvas width changes

I don't know if there will be a solution to this.
I have a canvas element which I wish to change the width of. That's easy enough, I know, but when the width changes, the lines in the drawing also go thinner/thicker when the width goes narrower/wider.
I could probably get around this by redrawing the image and playing around with scaling and lineWidth, etc, but I do not want to re-draw every time the width changes (I am changing the width using setInterval, so I don't think redrawing every 40-50 - or less - milliseconds is a reasonable/doable solution).
Can anyone think of a way to get around this?
A simple explanation to explain, I have:
ctx.beginPath()
ctx.strokeStyle="#000000";
ctx.lineWidth=1;
ctx.strokeRect(10, 10, 400, 400);
So when the width of canvas changes, the lineWidth becomes less than 1 pixel, to a point where it becomes "broken" and disappears.
In writing this question I am think more and more that the only solution would be to redraw the image but please let me know your thoughts.
ADDITION***
I am using this to change width, hope it makes sense:
repeater = setInterval(function() {
$(".action").css("width", originalWidth - borderRight - borderLeft + (mouseX - clickX));
}, 40);
I check when mouse is over right edge of canvas, then on "mousedown" originalWidth, borderRight, borderLeft, mouseX and clickX are set outside of repeater, so as mouse moves left and right the width increases/decreases. The interval is cleared on "mouseup", of course.
Thanks, Mike
Do not use CSS to rescale a canvas. When you use CSS, you scale the output of the canvas in the HTML layout, but don't change the internal resolution.
Change the width and height attribute of the canvas HTML node instead.

KineticJS strokeWidth centering

When you use strokeWidth in Kinetic, it adds width on each side of the actual point. So, in other words the stroke is centered on the normally 1px line and the width of that line grows outward from the center.
So for example in the below image "A", you see that the point is at (0,0) but the line is growing outward from that point. What I need is something like image "B".
I know I can accomplish this by just enlarging the polygon by the difference of the strokeWidth, but that will throw off many measurements and I'm hoping there's something easier to say "grow outward."
Center-aligned is the only native html canvas stroke alignment.
It is occasionally proposed that strokes be given "in" | "out" | "center" alignments, but so far nothing from whatWG: http://old.nabble.com/Canvas-stroke-alignment-tc29205720.html
You could put your polygon in a custom Kinetic Shape. That way you could draw a second "stroking" polygon that is outside the original polygon. It's a bit more setup work, but you could achieve your desired result.

Why do images lose quality after the context has been rotated?

I'm making a top-down shooter game that relies on the avatar always being rotated pointing to the mouse cursor. I achieve rotation like this:
//Rendering.
context.save(); //Save the context state, we're about to change it a lot.
context.translate(position[0] + picture.width/2, position[1] + picture.height/2); //Translate the context to the center of the image.
context.rotate(phi); //Rotate the context by the object's phi.
context.drawImage(picture.image, -picture.width/2, -picture.height/2); //Draw the image at the appropriate position (center of the image = [0, 0]).
context.restore(); //Get the state back.
When the phi is zero, the image is rendered in its normal quality, with sharp edges and detectable pixels. But, when I set the phi to a nonzero value (actually, when it's not 0, Pi/2, Pi, Pi+Pi/2 or 2Pi), the image looses it's sharpness and the individual pixels can't be seen anymore, because they are blurred out.
Here's a screenshot (sorry about the general bad quality of the screenshot, but I think that the difference is more than noticeable):
This is, well, a bit unacceptable. I can't have the images always blurred out! Why is this happening and can I solve it?
You could try
context.imageSmoothingEnabled = false;
See docs:
context.imageSmoothingEnabled [ = value ]
Returns whether pattern fills and the drawImage() method will attempt to smooth images if they have to rescale them (as opposed to just rendering the images with "big pixels").
Can be set, to change whether images are smoothed (true) or not (false).
If you want a true pixel-art retro style effect, you'd need to manually create rotated sprite images for several angles, look up the appropriate sprite for the current value of phi, and draw it without rotation. This obviously requires a fair amount of art work!
IF you are rotating images around their center point, make sure the image itself has an even number of pixels. Once you end up on odd coordinates the image data needs to be interpolated for the target canvas. Apple has some nice documentation on translating and rotating the canvas.
So for any image, as suggested above use rounding to snap to full pixels.
context.translate(Math.floor(img.width/2), Math.floor(img.height/2));
This way every source pixel of your image will always be drawn exactly into a pixel inside the canvas and blurring does not occur. This however is only true for multiples of 90 degrees.
It seems that all browsers do, to some extend, antialiasing in image drawing so you will probably have to provide rotated images as sprites.
According to this Chromium bug report you might be lucky there if they haven't fixed it yet. Read through and you'll learn that Ian Hickson likely opposed making antialiased image drawing optional.
(picture.width/2, picture.height/2) point won't always work.
(Math.floor(picture.width/2) + 0.5, Math.floor(picture.height/2) + 0.5) should help.
Well, actually it is something you cannot get around
If you rotate an image by a multiple of 90 degrees, your library should smart enough so that no interpolation is applied.
But as soon as you rotate an image by an angle different from a multiple of 90 degrees, you need to interpolate. As a consequence, you get that smoothing. If you are interested in the theory, you may look for a book on computer graphics or image processing.
For the concrete case of image rotation you may have a look at this paper,
http://bigwww.epfl.ch/publications/unser9502.html

Grid drawn using a <canvas> element looking stretched

I'm trying to draw a grid on a <canvas> element with the ultimate goal of making a Go board.
For some reason the grid is looking stretched, with the lines being thicker than 1 pixel and the spacing being completely wrong. It doesn't even start in the (10,10) position..
It would be great if someone could take a look at tell me what I'm doing wrong.
http://jsfiddle.net/h2yJn/
I've found the problem. I was setting the dimensions of the <canvas> using CSS, when you actually have to set the width and height attributes. This was causing it to be stretched/skewed.
var canvas = $('<canvas/>').attr({width: cw, height: ch}).appendTo('body');
http://jsfiddle.net/h2yJn/66/
Please try it outside jsfiddle, maybe jsfiddle is applying some linear transformation.
Also please make sure that you add 0.5 everywhere to both x and y coordinates. Alternatively, you can apply translate(0.5, 0.5) to shift all coordinates by half a pixel.

Categories

Resources