I'm trying to make a full screen game to help me learn JS. I made a canvas item and streched it to the size of the screen using CSS. Then I draw a circle. The issue I have is that the circle looks terrible!
_draw.arc(20, 20, 10, 0, 2 * Math.PI);
Here is a jsfiddle example. http://jsfiddle.net/H5dHD/152/
I've tried using different scale factors (so _draw.scale) but it dosent seem to matter...
What am I doing wrong?
P.S. I know the coordinates are off. I didn't include that code for the example.
The problem is that you resized the canvas using the CSS-style, and do not change the actual width and height. When you use CSS styling to change the size, the canvas will be stretched, but the internal drawing resolution stays the same. The result is that the canvas blurs.
To change the internal resolution, change the width and height attributes of the canvas HTML element itself.
document.getElementById('iDraw').height = screen.availHeight;
document.getElementById('iDraw').width = screen.availWidth;
Here is your updated fiddle:
http://jsfiddle.net/H5dHD/154/
Related
I am attempting to resize a canvas chart when a user resizes their browser window. The problem with changing it directly, or so I've found...is that the image disappears during the resizing. Here are some screenshots to help you understand my problem.
This is the chart before resizing.
This is the chart during the resizing. (without targeting the DOM element)
I've identified the chart overflowing on the right hand side.
Chart being resized and targeting the canvas width.
As you can see, the chart disappears.
let canvas = document.getElementById('canvas');
this.canvas.width = ${
event.target.innerWidth - (window.innerWidth / 100) * 2
};
Please let me know what options I have for dynamically resizing canvas charts. Thanks!
P.S. I'm using AngularJs for this particular project.
Update 12/30/2020
Discovered that the obvious reason for the chart disappearing is that the canvas is based on coordinates which originate from a set height/width. So the solution was re-mapping the strokes/fills as the canvas is resizing.
New challenge:
Using clearRect (0, 0, width, height) doesn't clear the canvas. Re-mapping results in an inifite mapping of charts on top of one another. As shown in the photo below.
Is this the solution I get paid a million dollars for? No. But...
After hours of spinning around thoughts as to why the creators never made an easy solution for resizing a canvas, I've finally found an option that works for resizing the charts. Note that if you're scaling up that it can become pixelated. But this option will work.
Instead of defining the height and width with the inline properties:
<canvas id="canvas" height="200" width="600" (window:resize)="onResize($event)"> </canvas>
You should use css to make the height and width 100%. This turns the canvas into an image essentially. Which is why it pixelates when you scale up. The next step is to setup functionality or styling for the element that the canvas is embedded within. This is where the solution arises. Because you can't adjust the canvas without losing the graphic. You have to adjust the element that encapsulates it!
Ex:
<div id="area-chart">
<canvas id="canvas" (window:resize)="onResize($event)"> </canvas>
</div>
You would dynamically adjust the height and width of the #area-chart. I personally suggest using viewport width to define the height as it is the most flexible in terms of scaling and the graphic pixelates far less than using other measurements (%, px, pt, etc.). Of course your needs may be different than mine, but here's some sample styling.
Sample scss:
#area-chart {
#canvas {
width: 100%;
height: 10vw;
}
}
Chart on load:
Chart scaled down:
Chart scaled up:
** note that the pixel dimensions in the screenshots are the full window size and not the size of the element
I need to apply zoom to the javascript canvas which I have badly accomplished by using the following line of code:
ctx.scale(2,2) //doubles everything's size
Instead of zooming, its obviously doubling the size of the canvas and all of its elements. I'd be okay with this if I got it working like the image below shows:
Any ideas on how I could accomplish what is depicted in the picture above? I'm not using any external libraries hence making this so difficult. Thanks.
You can translate the context by half the canvas size using ctx.translate()
EDIT :
var zoomfactor = 2; //set whatever you want as zoom factor
ctx.transform(zoomfactor,0,0,zoomfactor,-(zoomfactor-1)*canvas.width/2,-(zoomfactor-1)*canvas.height/2)
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.
When I first started this project that I'm working on, my canvas size with 1400px wide and 480px tall. I realized that I am going to need to make the canvas the same size as the window itself later, so I did that and everything inside of the canvas zoomed in or something. I set a drawImage(); to be 300 px wide and 180 px tall, and it is a LOT bigger than that, the image is actually the same width as the canvas now. Any suggestions? Here's the link to the project:
http://brycemckenney.com/animation-app
Thank you guys!
You have set the dimensions through css, instead of the physical dimensions of the (image) canvas.
The relevant piece (for others to read in the future) of your code is:
var canvas = document.getElementById("canvas1");
var ctx = canvas.getContext("2d");
var windowHeight = $(window).height();
var windowWidth = $(window).width();
$(canvas).css({
height: windowHeight - 8,
width: windowWidth - 8
});
Think of it like this: suppose you have a normal jpg-image.
That jpg has it's own 'physical' dimensions (aka width and height).
In both HTML and CSS you can set the dimensions (in px, percent, etc) that you'd like the browser to render (scale) the picture (hey, the picture already has a immutable size right?).
Now for canvas:
In order for canvas to have a physical width/height, you have to set the .width and .height of the canvas-element itself, either in HTML or per javascript (a side-effect is that setting the physical dimensions is that the canvas will clear itself, as per spec).
Then to scale the image (like you did with the above jpg example) you use css (again in px/percent/etc).
I think this is a clever solution by the way to add that new canvas-element to the HTML-Spec!
So, rounding up:
A canvas with a width and a height of 300 px rendered as 100% of a container (like document.body) that measures 900x900px will be scaled-up 3 times!
The reverse (scaling down) will let you draw even more crisp lines by the way!
Hope this helps your understanding!
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.