How can I achieve, so that the HTML5 canvas element ist resizeable?
I would like to implement this element so that you can scale it in any size. The event of the scaling should be the mouse which snaps the edge and the user resizes the element.
I've already read about how you can achieve this on a object in the canvas element. But in my case I need this on the canvas element itself (<canvas>).
Setting a canvas's width or height properties has the effect of clearing the canvas. Even canvas.width = canvas.width; will cause you to lose everything in the canvas. Sometimes this is desirable, but in your case it probably isn't.
What you will probably need to do is something like this
var myCanvas = document.getElementById('myCanvas');
var tempCanvas = document.createElement('canvas');
tempCanvas.width = myCanvas.width;
tempCanvas.height = myCanvas.height;
// save your canvas into temp canvas
tempCanvas.getContext('2d').drawImage(myCanvas, 0, 0);
// resize my canvas as needed, probably in response to mouse events
myCanvas.width = newWidth;
myCanvas.height = newHeight;
// draw temp canvas back into myCanvas, scaled as needed
myCanvas.getContext('2d').drawImage(tempCanvas, 0, 0, tempCanvas.width, tempCanvas.height, 0, 0, myCanvas.width, myCanvas.height);
In most browsers, the scaling will be done with a bicubic scaling algorithm, causing it to get blurry. In some cases you can set a CSS property to cause nearest neighbor on the canvas if you want, but browser support for this is very spotty right now. You can instead manually do a nearest neighbor scale , as this question shows: How to stretch images with no antialiasing
Alternative CSS Approach
Another approach is to scale the canvas using CSS. In Chrome/Safari/IE you can just do:
<canvas style="zoom:200%" />
In Firefox, you can use a scale transform to achieve the same effect:
<canvas style="-moz-transform:scale(2)" />
In many ways this approach is easier, but it comes with its own little gotchas and browser specific quirks.
I think you need to bind the onresize event to your body of document.
Then inside the the event you need to resize the canvas using window.innerWidth and window.innerHeight.
Have a look # http://kile.stravaganza.org/lab/js/canvas_resize/ (view source)
Although it's a bit late to answer this question, I'd like to share what I found to solve the same question. Take it a look please.
panel.css
#Panel {
width: 100%;
height: 30%;
}
app.js
var widthG = 0, height=G = 0;
function updateScale() {
widthG = parseInt($('#Panel').width());
heightG = parseInt($('#anel').height());
}
...
function updateCanvas() {
ctx = $('#canvas').get(0).getContext('2d');
ctx.clearRect(0,0,ctx.canvas.width, ctx.canvas.height);
ctx.canvas.width = widthG;
ctx.canvas.width = heightG;
}
I also tried to re-assign these properties by css syntax, but it doesn't work.
$('#canvas').width(panelW);
$('#canvas').height(panelH);
Hope this helps ppl suffered from the same question.
Related
So I am trying to learn javascript by making a game where you click on a canvas to move a circle and you have to dodge multiple other circles coming in your direction. I am close to the final result but I just realized that the larger your screen is, the easier it is for you to play.
The reason is that the enemies spawn at the edges of the canvas, so if the canvas is bigger, you have more time to react to them since their speed doesn't change. The game is supposedly refreshing around 60fps and each time it resizes the canvas depending on if you change your window size. The only thing I can think of is increasing the speed of enemies with the size increase but I don't know if there's any other way to go about this. Maybe I could increase the size of the of the player and the enemies to accommodate the change in window size but I don't know which is better or how to make sure I am consistent with the ratio increase.
Any suggestions would be much appreciated. Thanks for your time
Here's my full code: https://jsfiddle.net/r2f6eb89/2/
It doesn't actually run on this site so it's just a reference for my logic.
Here are the resizing functions:
/*
function setCanvasSize() {
//c.width = window.innerWidth-100;
//c.height = window.innerHeight-100;
if (window.innerWidth < window.innerHeight) {
c.width = window.innerWidth - 150;
c.height = window.innerWidth - 150;
} else {
c.width = window.innerHeight - 150;
c.height = window.innerHeight - 150;
}
}
*/
function setCanvasSize() {
c.width = 600;
c.height = 600;
}
There's actually two kinds of "width" and "height" property. One is the width and height you can actually see in your website, that is, the one you can change by the property on your html file element. The other one is the width and height you set in the javascript file, for setting the coordinate you use to print image or draw in the canvas.
Example for first type of the width/height property:
<canvas id="my_canvas" width="500" height="200"></canvas>
Example for second type of the width/height property:
var canvas = document.getElementById("my_canvas");
canvas.width=500;
canvas.height=200;
It seems like you are changing the second type of the width/height property each refresh. If that's not what you want, try modifying the first type of width/height. It seems like a simpler solution to your question. To modify the first type of property, the CSS property in javascript, here's the code:
canvas.style.width="500px";
canvas.style.height="200px";
Hope that helps :)
I am working on a multiple web game using JavaScript. My canvas is currently set to the width and the height of my screen.
html
<canvas id = "canvas"></canvas>
javascript
var c=document.getElementById("canvas");
var ctx = c.getContext("2d");
//Making canvas scale;
c.width = window.innerWidth;
c.height = window.innerHeight;
function resize(){
//Add some code
}
My problem is, I do not want my players to zoom out, well not by default. It will make the game look bad and give the players an edge over everyone else. So I need to add some code to go into the resize method, that regardless of scale, the canvas will not be zoomed out. If the end result is something blurry at 300%+ that is fine.
IMPORTANT: the resize function cannot remove or reset the canvas back to default.
There are various ways to scale a canvas.
First off, there are 2 main parameters for the canvas size:
-Canvas Pixel Count. Set via canvas.width = 1000
-Canvas Display Pixel Size. Set via canvas.style.width = '1000px'
If you want all players to see a 1000x1000 region but displaying it fullscreen:
canvas.width = 1000;
canvas.height = 1000;
canvas.style.width = window.innerWidth + 'px';
canvas.style.height = window.innerHeight + 'px';
There is also another option with canvas.style.transform = 'scale(2,2)'.
This method is the closest thing to the browser zoom done via Ctrl+ or Ctrl-.
The big advantage of transform is that the scaling is applied to all DOM children elements. If your game is using HTML for its interface, then this is the way to go. (By applying the scaling on the div containing the canvas + HTML interface.
I want to use HTML5 canvas with flexbox. I need to set canvas.width and canvas.height automatically when user resizes window. I have tried to use jQuery for it:
$(".cnvs").attr("width", $(".cnvs").width());
$(".cnvs").attr("height", $(".cnvs").height());
but it keeps increasing actual width of canvas so it almost fills entire screen. I have put it on jsfiddle - try to resize output window with separator.
Is there any reasonable way how to do it? Thanks.
Edit: Just to be clear: I don't want to fill entire screen with that canvas. I want UI where I have:
<div class="container">
<div class="control"></div>
<canvas></canvas>
<div class="control"></div>
</div>
then use flexbox to put those three elements beside eachother, while canvas will be twice as wide as the other. This works without problem, but canvas.width and canvas.height doesn't get updated, so whenever I render something onto that canvas, it is rendered as if that canvas was 320x140 px.
Edit 2: I am sorry, but (perhaps because of my poor English) I am not clear enough. I will try to explain it once again:
Actual width of canvas element is correct (even without using any JavaScript code) only by using flexbox. My problem is that although width is correct (and $(".cnvs").width() returns correct value of width), it doesn't have any "width" attribute, it is still:
<canvas>
</canvas>
and I need to provide width argument by myself (because it renders badly when it's not set). When I try to use my code or proposed:
...
var rect = canvas.parentNode.getBoundingClientRect();
canvas.width = rect.width;
canvas.height = rect.height;
...
it behaves weirdly, canvas's width keeps increasing with every resize, but too much (it erases both control divs almost immediately).
Update 2
If I understand the question correct: the canvas has a flex CSS set (not shown in the question right now). It defines the canvas to be 2x the size of the other two elements, but since the canvas is resized and not its bitmap, the drawings are stretches as well and you want the bitmap to adopt dynamically.
If so, do this change to the code -
This update will leave the CSS rules of the canvas element alone and let flexbox handle it. It will read the actual pixel size of the element and then apply it to the bitmap so that data isn't stretched:
$(window).on("resize", function() {
var cnvs = $(".cnvs")[0]; // cache canvas element
var rect = cnvs.getBoundingClientRect(); // actual size of canvas el. itself
cnvs.width = rect.width;
cnvs.height = rect.height;
// ... redraw content here ...
}
Additionally, since resizing the window can produce a lot of events, you may want to consider "debouncing" so that you only deal with the more recent resize:
var timerID;
$(window).on("resize", function() {
clearTimeout(timerID);
timerID = setTimeout(function() {
var cnvs = $(".cnvs")[0]; // cache canvas element
var rect = cnvs.getBoundingClientRect(); // actual size of canvas el. itself
cnvs.width = rect.width;
cnvs.height = rect.height;
// ... redraw content here ...
}, 180); // adjust at will
}
This will delay the resizing/redrawing until 180ms has passed.
You don't even have to load jQuery, it is simple:
var canvas = document.querySelector("canvas");
window.addEventListener("resize", function(){
canvas.setAttribute("width", window.innerWidth);
canvas.setAttribute("height", window.innerHeight)
})
You have to add a listener to the resize event on the window object.
If your looking for a jquery solution.
$( window ).resize(function() {
$(".cnvs").attr("width", $(window).width());
$(".cnvs").attr("height", $(window).height());
});
This should work just fine.
In my project i have a canvas (200*150) and i want to draw an image of size (800*600) . The result is that image become bluer (not smooth and clear) , but if we put that image on img tag it look well. So how can we deal with this? thanks.
<img src="http://www.drivingkids.com/wp-content/uploads/2010/07/preschool-math-game-for-kids-math-racing-equatations.jpg"
width="200" heigh="150" />
<canvas id="my_canvas" width="200" height="150"></canvas>
<script type="text/javascript">
window.onload = function () {
var context = document.getElementById("my_canvas").getContext("2d");
var image = new Image();
image.src = "http://www.drivingkids.com/wp-content/uploads/2010/07/preschool-math-game-for-kids-math-racing-equatations.jpg";
image.onload = function () {
context.drawImage(image, 0, 0, context.canvas.width, context.canvas.height); //dx-30, GY-28, GW+50, GH+35
}
}
</script>
Cause
Browsers can prioritize quality or performance depending on the current scenario.
For images quality is typically prioritized over performance for most pages. But for canvas performance is not as good as with for instance direct browser rendering and CSS so the interpolation with canvas may have performance prioritized before quality. Depending on browser implementation.
Solution
Luckily there is a way to work around this by sort of splitting the burden with the resizing and interpolation by doing it in two (or more) steps, or one intermediate step if you like.
The intermediate step will first scale the image 50% to an off-screen canvas. Then use that canvas to draw to the final size. For larger images more steps will perhaps be needed.
The time spent in sum is about the same due to the sum of the operations to get the new sizes (more simply put: less to interpolate with intermediate step x2, versus more to interpolate x1) so you won't notice much performance reduction.
But most importantly: the result will be better than with just a single step.
Implementation
This is how you can implement an intermediate step:
image.onload = function () {
/// create an extra step for re-sizing image
var tmpCanvas = document.createElement('canvas'),
tmpContext = c.getContext('2d');
/// set this canvas to 50% of image
tmpCanvas.width = image.width * 0.5;
tmpCanvas.height = image.height * 0.5;
/// draw image step 1
tmpContext.drawImage(image, 0, 0, image.width * 0.5, image.height * 0.5);
/// draw image step 2
context.drawImage(tmpCanvas, 0, 0, canvas.width, canvas.height);
}
Demo (proof-of-concept)
ONLINE DEMO HERE
The result will be:
Left image: IMG element. Right image: canvas two steps (rendered in Firefox)
As you can see there is now no noticeable difference between image and canvas element.
I am trying to draw a shape on an HTML5 canvas but have the shape appear in a div (that can be manipulated by javascript). How can i do this? I would post code but i dont even know where to start with this. Please help.
To clarify: i want the shapes rendered on the canvas to be placed in divs. Sorry for any confusion.
Mozilla Drawing: https://developer.mozilla.org/en/Canvas_tutorial/Drawing_shapes
<div>
<canvas id="my_canvas"></canvas>
</div>
<script>
var canvas = document.getElementById('my_canvas');
// Set width height. You should probably use the width/height of the div.
canvas.width = 300;
canvas.height = 300;
var ctx = canvas.getContext('2d');
// Draw something with ctx.....
// ....
</script>
You could use the library Canvas2Image. It will allow you to convert what's on the Canvas into an image. There are some quirks on a per browser basis, but it is the closest thing to what you want to do without having to put many canvas elements on your page that you update in tandem.