Javascript Canvas bad rendered - javascript

I just experimented a bit with Javascript and HTML5 canvas and when I saw it in my browser (chrome) I realised that it's not very pretty rendered. After that I saw it in the Internet Explorer and there it looks even more crawful. I made a little Example: http://ios.xomz.de/
I just declared the canvas object in the html code
<canvas id="mycanvas" width="1000px" height="600px"/>
and rendered into it with
var canvas = document.getElementById("mycanvas");
var context = canvas.getContext("2d");
context.beginPath();
context.rect(200, 200, 600, 200);
context.lineWidth = 5;
context.strokeStyle = 'black';
context.stroke();
context.font = "40pt arial";
context.fillStyle = "black";
context.fillText("Hello World!", 220, 380);
for example.
Can you explain why the rendering isn't good ?

Do not use "px", also I'd recommend not using a self-closing tag:
<canvas id="mycanvas" width="1000" height="600"></canvas>
http://jsfiddle.net/c2KeD/

This problem is related to the way objects are drawn on a float based grid (especially vertical and horizontal lines and thus rects).
See there for an explanation and a schema : http://canop.org/blog/?p=220
Depending on the size of your objects, you need to use integer or mid-integer coordinates and sizes for your shapes, the goal being to fill complete pixels in both dimensions.
For example :
use a mid-integer for a thin line (one pixel width)
use an integer coordinate for a 2 pixels wide line
(and extend the logic for rects)
In your case, with a line width of 5, you have sharper rects by using this :
context.rect(200.5, 200.5, 600, 200);
Demonstration here : http://jsfiddle.net/dystroy/TyNBB/

Related

Draw rectangles in a cartesian coordinate system

I want to draw a following chart in JavaScript. Basically, the goal is to draw some rectangles in a cartesian coordinate system. Each rectangle can be represented by 4 points, whose coordinates are given.
Does anyone know how to draw it? Is there any library to do so? Ideally, i would expect some example code that I could adjust a little bit, rather than drawing everything from scratch.
You have two main options:
SVG - vector graphics that are pretty similar to HTML (you have elements with attributes etc). you can also use CSS for styling SVG.
canvas - this is basically a bitmap on which you can draw with JS.
(HTML) - of caurse you could also use simple HTML + CSS.
Here are some tutorials about those two:
http://svgtutorial.com/manipulating-svg-with-javascript/
https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API/Tutorial/Drawing_shapes
There are bunch of 3rd party libraries to help with this like:
https://d3js.org/
http://dmitrybaranovskiy.github.io/raphael/
http://fabricjs.com/
http://paperjs.org/
Here is simple example with canvas:
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
ctx.strokeRect(0, 0, 400, 200);
ctx.strokeRect(0, 200 - 20, 20, 20);
ctx.strokeRect(30, 200 - 70, 20, 70);
<canvas id="canvas" width="400" height="400"></canvas>

Canvas transform not behaving as expected

Suppose I have a 400x200 canvas.
I want to work in a coordinate system where (0, 0) is in the exact middle of the canvas and positive y means up and positive x means right.
So, I set the transform as follows:
var ctx = document.getElementById("canvas").getContext("2d");
ctx.setTransform(1, 0, 0, -1, 200, 100);
ctx.fillRect(-20, -20, 40, 40);
<canvas id="canvas" style="width: 400px; height: 200px"></canvas>
So when I fill the rectangle as in the snippet above, I would expect to see a square centered in the middle of the canvas element. However, when running the above snippet (in latest Chrome) the square is demonstrably not centered. Why is this? Am I misunderstanding something about the transform matrix? If so, how can I achieve my goal?
The size for the canvas element isn't set properly which means the canvas defaults to 150 pixels in height, which is then stretched out using CSS. This gives the illusion of the object being offset.
To properly set canvas size use its attributes instead of CSS:
<canvas id="canvas" width=400 height=200></canvas>
Also be aware of that the Y-axis is now flipped upside-down so any text and images are drawn upside-down as well. These will need local transformation to be drawn correctly.
The problem seems to be that the dimensions in style are ignored and default to the standard dimensions 300×150. So set them properly with
<canvas id="canvas" width="400" height="200"></canvas>
Independent of that, it can be a good idea to not rely on hard-coded dimensions, especially if you are going to use a local coordinate system anyway.
My snippet modifications:
Use the actual canvas dimensions and scale so that the local coordinates still at least contain the square (-100,100)×(-100,100).
Add a coordinate cross before setting the transformation, that shows that even when the canvas is "wrong", the square is at the coordinate origin.
After the transformation, add a circle at positive y position to show that "up" is really up.
var cnv = document.getElementById("canvas");
var w = cnv.width, h = cnv.height;
var ctx = cnv.getContext("2d");
ctx.beginPath();
ctx.moveTo(0,h/2); ctx.lineTo(w,h/2);
ctx.moveTo(w/2,0); ctx.lineTo(w/2,h);
ctx.closePath(); ctx.stroke();
var scale = Math.min(w,h)/200.0;
ctx.setTransform(scale, 0, 0, -scale, w/2, h/2);
ctx.moveTo(0,50); ctx.arc(0,50,10,0,2*Math.PI); ctx.stroke();
ctx.fillRect(-20, -20, 40, 40);
<canvas id="canvas" width="450" height="250"></canvas>

HTML5 canvas line width less that 1 pixel

Is there any way to draw a rectangle whose composing lines have width thinner than 1 pixel?
This code works perfectly, as expected:
// context is a HTML5 canvas 2D context
context.lineWidth = 1;
context.strokeStyle = "black";
context.rect(0, 0, 20, 20);
context.stroke();
It draws a nice rectangle.
But, if I try to draw a rectangle with thinner lines:
// See line width
context.lineWidth = 0.5;
context.strokeStyle = "black";
context.rect(0, 0, 20, 20);
context.stroke();
It still draws a rectangle whose borders have 1 pixel width.
I'm dealing with the canvas object here, and not CSS, where you have ways to "simulate" this.
Although it doesn't make much sense, you can acheive that with using a regular 1-pixel line with a 50% scaled canvas (but again it's a 1-pixel rendition, read below). See this snippet:
var canvas = document.querySelector('canvas');
var context = canvas.getContext('2d');
function scale() {
context.scale(0.5, 0.5);
draw();
}
function draw() {
context.beginPath();
context.moveTo(100, 150);
context.lineTo(450, 50);
context.stroke();
}
draw()
<canvas width="400" height="150"></canvas>
<button onclick="scale()">Scale down</button>
But again, I wonder how you expect the half-pixel line to look on your screen, antialiasing?
Right :) I suppose I was thinking on some way of drawing thinner lines, like, for example, when you use CSS styles. I've looked around and I don't think I can use alternate units.
There's no way to make something that's smaller than the smallest component unit, in our case a pixel. You can mimic the thinner look by transparency, or opacity, or even some sort of antialiasing (which again relies on transparency or the colouring of the neighbouring pixels), but not by trying to go below one pixel.
I agree, there is a sub-pixel rendering mode in browsers, for example, when you work with percentages, but in the end, the browser just renders full pixels with some of the modification I've described above.
And you know if you could render unit smaller than pixels, you'd technically have infinite resolutions on displays. I wish it was possible. :)

JS Canvas - how to fill area with bitmap?

Using JavaScript's Canvas - how to fill specific area with a bitmap? And not just draw the bitmap, but for example fill a 100x100 rectangle with 20x20 px bitmap?
graphics.beginBitmapFill(bmd, matr);
graphics.draw()
This is ActionScript3 code, that I know how to use. I'm searching for JavaScript alternative to it.
As per link http://www.w3schools.com/tags/canvas_drawimage.asp, you can proceed as follows:
assuming you have a 100px by 100px canvas in your html:
<canvas id="cv"></canvas>
you can process it in JavaScript as follows:
var canvas, context;
canvas = document.getElementById('cv');
context = canvas.getContext('2d');
you can place your 20x20 image with the upper left corner at 10px to the left and 30px to the top as follows
context.drawImage('img.jpg', 10, 30, 20, 20);
My first open-source JavaScript library is entirely based on HTML5 canvas, where you can see more examples on how to work with it in JS:
http://pickled-plugins.github.io/ripsaw-demo/#pages/home
maybe this will help
context.fillStyle = context.createPattern(image, "repeat");
context.fillRect(0, 0, 300, 300);
full code at
http://www.williammalone.com/briefs/how-to-fill-pattern-html5-canvas/

lineTo on HTML 5 canvas not working properly

I'm trying to learn canvas.
I was trying to draw some lines using moveTo() and lineTo() on canvas.
The co-ordinates I give and the point rendered over canvas are not matching
I have taken a canvas of size 500px X 500px
for (0,0) it is coming fine.
for all other points it is not matching the co-ordinates
for (300, 150) it is painting at (500,500).
I'm not getting why this is happening because if I set my canvas size t0 300px X 150px it is painting correctly
here is my js
var context = document.getElementById("myCanvas").getContext("2d");
context.moveTo(0, 0);
context.lineTo(100, 100);
context.lineTo(100, 100);
context.lineTo(200, 100);
context.lineTo(300, 150);
context.stroke();
jsfiddle here
Can any one please tell me where I'm wrong
set the height and width of the canvas element directly:
<canvas id="myCanvas" width="500" height="500"> </canvas>
fiddle: http://jsfiddle.net/nLUEX/2/

Categories