This will drag my rectangle path. It works perfectly if the window hasn't resized.
function onMouseDrag(event) {
MyRectanglePath.position = event.point;
}
This will resize my game to be a square at either 100% width or 100% length of the browser window.
function OnResizeCalled() {
var gameWidth = window.innerWidth;
var gameHeight = window.innerHeight;
var scaleToFitX = gameWidth / 640;
var scaleToFitY = gameHeight / 640;
var currentScreenRatio = gameWidth / gameHeight;
var optimalRatio = Math.min(scaleToFitX, scaleToFitY);
canvas.style.width = 640 * optimalRatio + "px";
canvas.style.height = 640 * optimalRatio + "px";
}
// Resize
window.addEventListener("resize", OnResizeCalled, false);
OnResizeCalled();
The smaller my browser window gets, the farther the rectangle is from my mouse when I drag it. How do I make event.point scale with the rest of the canvas?
Paper.js is not designed to support manual resizing of the canvas, since that will blow up the pixels and cause all kind of internal issues. It will also interfere with HiDPI handling on Retina screens.
but you can resize the canvas using:
paper.view.viewSize = [width, height];
I hope this helps!
Umm as Mr. Jürg Lehni stated before, Paper.js is not designed to support manual resizing of the canvas. when paper.view.setViewSize() extends/ shrink the canvas to that size.
If you want to scale the things inside the canvas (e.g. path), you had to apply transformation to every item (with right Matrix) using .transform();
Related
I am writing a simple game in javascript which draws on a HTML canvas. The canvas has a fixed size (1280 × 720) and that is also the "room" in which the objects are drawn.
Now I want the canvas to be stretched to be 100 % of the screen. I can't do that by just setting the width and height of the canvas because the javascript would only draw in the 1280 × 720 rectangle in the top left.
What I want instead is, that it is zoomed in so that it takes up the whole screen and if the javascript draws something at (1280, 720) it should be the bottom right corner.
Can I do this without using any external libraries?
If you wish to keep the rendering size at 1280x720 for the canvas, but stretch or expand it to the window size you can use the css width and height for that.
Using css will only cause the shape of the canvas to change, but the internal pixels/drawing frame are still set by the width and height attribute. (This will of course cause the image to be blurry if it is upscale to much)
With CSS:
* { margin: 0; padding: 0;}
body, html { height:100%; }
#canvasID {
position:absolute;
height:100%;
/*width:100%; /* uncomment if you don't care about aspect ratio*/
}
<canvas id="canvasID" width=128 height=72>
With a script:
$(document).ready(function() {
function resizeCanvas() {
var canvas = $("#canvasID");
// original width/height from the canvas attribute
var heightOriginal = canvas[0].height;
var widthOriginal = canvas[0].width;
// fill to window height while maintaining aspect ratio
var heightNew = window.innerHeight;
// replace with window.innerWidth if you don't care about aspect ratio
var widthNew = heightNew / heightOriginal * widthOriginal;
canvas.css("height", heightNew + "px");
canvas.css("width", widthNew + "px");
}
// keep size when window changes size
$(window).resize(resizeCanvas);
// initial resize of canvas on page load
resizeCanvas();
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<canvas id="canvasID" width=128 height=72>
Alternately if you wish for the internal canvas resolution/size to be able to change dynamically you can use scale to ensure that everything gets rendered to the right size.
$(document).ready(function() {
var canvas = $("#canvasID");
// original width/height from the canvas attribute
var heightOriginal = canvas[0].height;
var widthOriginal = canvas[0].width;
// current scale (original 1 to 1)
var verticalRatio = 1;
var horizontalRatio = 1;
// the canvas context
var ctx = canvas[0].getContext('2d');
function setScale() {
// remove previous scale
ctx.scale(1/horizontalRatio, 1/verticalRatio);
// fill to window height while maintaining aspect ratio
var heightNew = window.innerHeight;
// not needed if you don't care about aspect ratio
var widthNew = heightNew / heightOriginal * widthOriginal;
// these would be the same if maintaining aspect ratio
verticalRatio = heightNew / heightOriginal;
horizontalRatio = widthNew / widthOriginal;
// update drawing scale
ctx.scale(horizontalRatio, verticalRatio);
// update width and height of canvas
canvas[0].height = heightNew;
canvas[0].width = widthNew;
}
// keep size when window changes size
$(window).resize(setScale);
// initial resize of canvas on page load
setScale();
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<canvas id="canvasID" width=128 height=72>
I've been playing around with creating a hexagonal grid in HTML5 Canvas. I have a basic grid, where if you click a hex it will highlight the hex (demo here: http://cfiresim.com/hex-map-game-reboot/test.html)
In javascript, I am defining the canvas as such (some parts omitted for brevity):
var hex = {};
hex.canvas = document.getElementById("HexCanvas");
hex.ctx = null;
console.log("Initializing new game...");
this.radius = 20;
this.side = Math.round((3 / 2) * this.radius);
this.height = Math.round(Math.sqrt(3) * this.radius);
this.width = Math.round(2 * this.radius);
//Set Size of main div to size of canvas
$('#primary-panel').css('height', (hex.height * hex.rows)+hex.height*2);
hex.canvas.style.width='100%';
hex.canvas.style.height='100%';
hex.canvas.width = hex.canvas.offsetWidth;
hex.canvas.height = hex.canvas.offsetHeight;
//Set click eventlistener for canvas
this.canvas.addEventListener("mousedown", this.clickEvent.bind(this), false);
this.ctx = this.canvas.getContext('2d');
All of the code can be found here: https://github.com/boknows/hex-map-game-reboot
My primary question is: Is there a specific way to prevent the click events from getting all screwy when the canvas is resized via the browser? For example, if you shrink the browser to be just bigger than the grid, clicks dont register in the right place. Am I missing some feature of canvas? Maybe getSelectedTile() is not being defined correctly?
Edit: It seems like this primarily happens when the browser scrolls a little, and thus moves the grid off screen. The clicks then register with a weird offset, which I'm guessing is equal to the distance the screen scrolled. Advice?
You must take into a position of a page scroll.
In HexagonGrid.js, instead of this:
hex.clickEvent = function(e) {
var mouseX = e.pageX;
var mouseY = e.pageY;
Do this:
hex.clickEvent = function(e) {
var mouseX = e.pageX - window.pageXOffset;
var mouseY = e.pageY - window.pageYOffset;
I'm using createJS to drawn inside the canvas. I have my canvas set to occupy the browser window maintaining aspect ratio using the resize() function.
This is the code:
mytext = new createjs.Text("Lorem ipsum dolor sit amet 2","19px Calibri","#073949");
mytext.x = 450
mytext.y = 300;
stage.addChild(mytext);
resize = function() {
var canvas = document.getElementById('canvas');
var canvasRatio = canvas.height / canvas.width;
var windowRatio = window.innerHeight / window.innerWidth;
var width;
var height;
if (windowRatio < canvasRatio) {
height = window.innerHeight - 35;
width = height / canvasRatio;
} else {
width = window.innerWidth;
height = width * canvasRatio;
}
canvas.style.width = width + 'px';
canvas.style.height = height + 'px';
}()
What happens is that the text gets blurry (decrease of quality) when the canvas resizes.
http://i.imgur.com/RQOSajs.png
vs
http://i.imgur.com/Xwhf5c5.png
How can I solve this issue?
Since you are using CreateJS, you can simply resize the canvas, and scale the entire stage to redraw everything at the new size:
// just showing width to simplify the example:
var newWidth = 800;
var scale = newWidth/myCanvas.width;
myCanvas.width = newWidth;
myStage.scaleX = myStage.scaleY = scale;
myStage.update(); // draw at the new size.
#Adam's answer is correct as far as scaling the canvas goes. You do NOT want to scale with CSS, as it will stretch your canvas instead of changing its pixel dimensions. Set the width and height of the canvas using JavaScript instead.
stage.canvas.width = window.innerWidth;
stage.canvas.height = window.innerHeight;
As you stated in your comment, this will only change the canvas size, and not reposition or scale your content. You will have to do this manually. This is fairly simple. Generally, I recommend putting your "resize" listener in the JavaScript in your HTML file, rather than on a frame script.
First, determine the scale, based on the size of the window and the size of your content. You can use the exportRoot.nominalBounds.width and exportRoot.nominalBounds.height which is the bounds of the first frame. If you want to scale something else, use its nominalBounds instead.
Note that nominalBounds is appended to all MovieClips exported from Flash/Animate. If you enable multi-frame bounds, and want to use those, you will have to modify your approach.
The main idea is to use the original, unscaled size of your contents.
var bounds = exportRoot.nominalBounds;
// Uses the larger of the width or height. This will "fill" the viewport.
// Change to Math.min to "fit" instead.
var scale = Math.max(window.innerWidth / bounds.width, window.innerHeight / bounds.height);
exportRoot.scaleX = exportRoot.scaleY = scale;
You can then center it if you want.
exportRoot.x = *window.innerWidth - bounds.width*scale)/2;
exportRoot.y = *window.innerHeight - bounds.height*scale)/2;
Here is a quick sample of a responsive canvas using a simple shape as the scaling contents:
http://jsfiddle.net/lannymcnie/4yy08pax/
Doing this with Flash/Animate CC export has come up a few times, so it is on my list of future EaselJS demos to include on createjs.com, and in the EaselJS GitHub.
I hope this helps.
Take a look at my jsfiddle : https://jsfiddle.net/CanvasCode/ecr7o551/1/
Basically you just store the original canvas size and then use that to work out new positions and sizes
html
<canvas id="canvas" width="400" height="400">
Canvas was unable to start up.
</canvas>
<button onclick="resize()">Click me</button>
javascript
var canvas = document.getElementById('canvas');
var context = canvas.getContext('2d');
var originalWidth = canvas.width;
var originalHeight = canvas.height;
render = function()
{
context.fillStyle = "#DDD";
context.fillRect(0,0, originalWidth * (canvas.width / originalWidth), originalHeight * (canvas.height / originalHeight));
context.fillStyle = "#000";
var fontSize = 48 * (canvas.width / originalWidth);
context.font = fontSize+"px serif";
context.fillText("Hello world", 100 * (canvas.width / originalWidth), 200 * (canvas.height / originalHeight));
}
resize = function()
{
canvas.width = 800;
canvas.height = 600;
render();
}
render();
The HTML5 canvas element works with two different sizes
Visual size on screen, controlled via CSS, like you're setting with canvas.style.width/height
Size of pixel buffer for the drawing, controlled via numeric width and height pixel attributes on the canvas element.
The browser will stretch the buffer to fit the size on screen, so if the two values are not 1:1 ratio text will look blurry.
Try adding the following lines to your code
canvas.width = width;
canvas.height = height;
I created a function to resize all the elements on the screen after resizing the canvas. It saves the initial coordinates and scales for the elements with the original width of 900 px and then it changes them according to the current width ratio relative to the original width ratio. The text isn't blurry/bad quality anymore.
resize = function() {
var canvas = document.getElementById('canvas');
var canvasRatio = canvas.height / canvas.width;
var windowRatio = window.innerHeight / window.innerWidth;
var width;
var height;
if (windowRatio < canvasRatio) {
height = window.innerHeight;
width = height / canvasRatio;
} else {
width = window.innerWidth;
height = width * canvasRatio;
}
canvas.width = width;
canvas.height = height;
reziseElements();
};
reziseElements = function()
{
var canvrat = canvas.width / 900;
//Simplified
stage.scaleX = stage.scaleY = canvrat;
//Old Version
/*for (i=0; i<stage.numChildren ;i++)
{
currentChild = stage.getChildAt(i);
if (typeof currentChild.oscaleX == 'undefined')
{
currentChild.oscaleX = currentChild.scaleX;
currentChild.ox = currentChild.x;
currentChild.oy = currentChild.y;
}
}
for (i=0; i<stage.numChildren ;i++)
{
currentChild = stage.getChildAt(i);
currentChild.scaleX = currentChild.scaleY = currentChild.oscaleX * canvrat
currentChild.x = currentChild.ox * canvrat
currentChild.y = currentChild.oy * canvrat
} */
}
I'm trying to create a HTML5 canvas using Windows 8 / WinJS. Here's what I have:
var body = document.getElementById("body");
var canvas = document.createElement("canvas");
canvas.id = "myCanvas";
body.appendChild(canvas);
var canvasContext = canvas.getContext("2d");
canvas.width = document.width;
canvas.height = document.height;
canvasContext.fillStyle = "#f00";
canvasContext.fillRect(canvas.width - 100, canvas.height - 50, 100, 50);
console.log("canvas width " + canvas.width + ", height " + canvas.height);
Most of this is directly from a tutorial, but for all the tutorials I've seen, the width and height are set to hard coded numbers, for example:
canvas.width = 800;
canvas.height = 600;
Admittedly that does work, but I want the canvas to be as big as the screen, whatever the resolution. How do I achieve this?
You can just use the viewport with and viewport height CSS values to do this (see some information on these here)
In this specific case you could just do:
canvas.style.width = "100vw";
canvas.style.height = "100vh";
The advantage of this solution is that you don't have to load 3rd party libraries, e.g. JQuery to size to the full width / height.
By "screen", do you mean the browser window size?
If so, you can use window.outerWidth and window.outerHeight instead of document.width and document.height. Or if you use jQuery: $(window).width() and $(window).height().
Also, you want to listen to the resize event on the window so that you can reinitialize the canvas when the browser is resized.
Note: I'm using Google Chrome
Currently I have this test page
http://www.evecakes.com/doodles/canvas_size_issue.htm
It should draw a rectangle right below the mouse cursor, but there are some really weird scaling issues which is causing it to draw at a varying offset. I think it's because the canvas coordinate space is not increasing along with its html size. Is there a way to increase that coordinate space size?
Here's the javascript function
$('#mapc').mousemove(function (event) {
var canvas = $('#mapc');
var ctx = canvas[0].getContext('2d');
ctx.fillStyle = "rgb(200,0,0)";
ctx.fillRect(event.clientX, event.clientY, 55, 50);
document.title = event.clientX + " --- " + event.clientY;
});
Set the width and height HTML attributes of the canvas. Right now, it's assuming its default width and the CSS is just stretching it, and it appears as if it is scaling.
A side-note, you can use this in the mousemove event - it is a reference to #mapc element, so you won't have to query the DOM on every mouse move.
var offset = $('#mapc').offset();
$('#mapc').mousemove(function (event) {
var ctx = this.getContext('2d');
ctx.fillStyle = "rgb(200,0,0)";
ctx.fillRect(event.pageX - offset.left, event.pageY - offset.top, 1, 1);
});