Html5 Canvas - drawing perfect lines using fabric.js or without - javascript

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.

Related

Javascript draw border around shape on Image canvas

I am searching for a solution to draw a border around all shapes on an Image. I have already tried this solution Draw border around nontransparent part of image on canvas but this doesnt work for me.
Imagine this png
the solution I am looking for should look like this
is there any libary/solution?
Thank you
If you're drawing the all the shapes using ctx.fill(), you can just call ctx.stroke() before each call to ctx.fill(). This will result in a line of width ctx.lineWidth/2, since half of the line will be covered by the shape itself. However, his won't work for other methods such as ctx.drawImage() or ctx.putImageData(). Please specify how exactly you're drawing these shapes to the canvas to receive some more detailed help.
Edit: I think you can use the solution you already mentioned, you just need to make the non-black part of your image transparent. You can do this by editing the the imageData of the canvas:
var ctx = canvas.getContext("2d");
var imageData = ctx.getImageData(0,0,canvas.width,canvas.height);
for (let i=0;i<imageData.data.length;i+=4){
if (shouldBeTransparent(imageData.data[i],imageData.data[i+1],imageData.data[i+2]){
imageData.data[i+3] = 0;
}
}
ctx.putImageData(imageData,0,0);
function shouldBeTransparent(r,g,b){
return r!=0||g!=0||b!=0;
}
This will make all pixels that are not entirely black transparent, so you can continue with the method you already mentioned.

p5.js canvas drawing path with ellipses

I am working on a real time canvas drawing webapp using socket.io, node.js, and p5.js. I am having trouble creating a smooth line when the mouse is dragged. If the mouse is dragged too fast there is a trail of empty space in between each ellipse. The end goal here is to create a smooth path. Here are the things I have tried so far:
Attempt 1:
noStroke();
fill(lineColor[0],lineColor[1],lineColor[2]);
ellipse(mouseX, mouseY, lineThickness, lineThickness);
Attempt 2:
strokeWeight(lineThickness);
line(mouseX,mouseY);
stroke(lineColor[0],lineColor[1],lineColor[2]);
Here is a picture of what the issue looks like:
canvas drawing incomplete path image
any feedback is welcome; thanks!
Kevin's answer is great because it will be more efficient to draw lines instead of many ellipses. You should also look into:
beginShape()/endShape()
bezierVertex()
curveVertex()
curvePoint()
The above should help you draw a smooth path and setting a thicker stroke will looks as it many filled ellipses are connected forming the path.
If for some reason you do want to draw many ellipses, you can interpolate position when the mouse move faster and create gaps to fill those gaps.
For more information and p5.js example, check out this answer:
Processing: Draw vector instead of pixels
You could use the pmouseX and pmouseY variables, which hold the previous position of the cursor. Use that to draw a line from the previous position to the current position to fill in the blank space between mouse events.
From the reference:
// Move the mouse across the canvas to leave a trail
function setup() {
//slow down the frameRate to make it more visible
frameRate(10);
}
function draw() {
background(244, 248, 252);
line(mouseX, mouseY, pmouseX, pmouseY);
print(pmouseX + " -> " + mouseX);
}
<script src="https://github.com/processing/p5.js/releases/download/0.5.11/p5.js"></script>

Re-aligning Javascript/Canvas drawing?

So I have a semi-complex canvas drawing someone gave me. It draws an image vertically (i.e., top-down). Let's assume its a stick figure with facial features.
This is done in Javascript and Canvas. i.e.: ctx.beginPath(), ctx.moveTo(x,y), ctx.lineTo(1,1), etc.
I want the stick figure to move towards some point (x,y) and to face that direction while moving toward it. For example, if the x,y is near the bottom right, I want the stick figure to be oriented in a way such that its feet are facing towards the bottom right while it is moving.
The main question is, how would I go about doing this (i.e changing the stickman), knowing that I have a "hardcoded" drawing (in this example, stickman) that has been given to me?
You can render the received image on a separate canvas (doesn't need to be displayed) and use ctx.canvas.toDataURL() to convert it to an image. You could then embed the resulting image in your canvas and apply transforms to it more easily.
I mentioned this in a comment on the question but it sounded like fun, so I implemented a proof of concept.
var canvasObject = function(ctx) {
ctx.beginPath();
ctx.moveTo(0,0);
ctx.arc(30,30,15,0,2*Math.PI);
ctx.fillStyle='red';
ctx.fill();
return ctx;
}
var myCtx = document.querySelector('canvas').getContext('2d');
var objCtx = document.createElement('canvas').getContext('2d');
var renderedObjUrl = canvasObject(objCtx).canvas.toDataURL();
var renderedObj = document.createElement('img');
renderedObj.setAttribute('src', renderedObjUrl);
myCtx.drawImage(renderedObj, 30, 10);
<canvas id="myCanvas" width="600" height="400"></canvas>

JavaScript canvas, getting flat lines

I'm working on project which have to draw graphs. Everything is quite good, but noticed one problem, the lines are showing strange.. it seems like someone draw my graph with brush holding horizontally.. when line goes down everything is OK, but when line is going horizontal the it becomes much smaller ... I can't find what's the problem could be..
Please help, because I started to get wrong graphs when it needs to draw horizontal line...
Here is the link to my project:
http://www.unolita.lt/images/signalai/Documents/Koreliacine%20funkcija.html
You can clearly see my problem on 1st picture..
Here is it's code:
function drawSignal()
{
var canvas = document.getElementById("canvSignal");
if (canvas.getContext)
{
var ctx = canvas.getContext("2d");
ctx.lineWidth = 3;
function Signalas()
{
<...>
ctx.beginPath();
ctx.moveTo(x, y);
ctx.strokeStyle = "black";
<...>
y=250- Sn[n] ;
ctx.lineTo(x, y);
ctx.stroke(x, y);
<...>
To put all code here was too much problematic..
This is due to the fact lines are drawn over all pixels they're over (on canvas positionning is in float). When you want to draw precise vertical or horizontal lines in javascript on a canvas, you'd better have them in half ints.
Possible Solution : If you have to draw a line with an odd numbered width, then you will have to offset the center of your line by 0.5 up or down. That way rendering will happen at boundary of pixel and not in middle, and you will always have a sharp line with no residue at the end edges.
So add 0.5 for odd numbered line width so that your points should be half numbered
ctx.lineTo(x+0.5, y+0.5);
ctx.stroke(x+0.5, y+0.5);
I have modified your code like this in line number 134 and 135 and got a output like this . Hope, this helps
Refer Here :
incorrect display lineWidth=1 at html5 canvas
HTML5 Canvas and Line Width
Line Width in Canvas

Canvas shows the text blurred

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

Categories

Resources