HTML5: Canvas width and height - html

Consider:
<canvas id="myCanvas" width="200" height="300" />
Are those units in pixels? If not, is there a workaround to change it?

Yes, those units are always in pixels and applies to the bitmap the canvas element uses. However, if there is no size defined on the element using CSS (ie. style attribute or using a style sheet) the element will automatically adopt to the size of its bitmap.
There is no other way of setting the size of the bitmap than by number of pixels. Using CSS will only change the size of the element itself, not the bitmap, stretching whatever is drawn to the bitmap to fit the element.
To use other units you will have to manually calculate these using JavaScript, for example:
// using % of viewport for canvas bitmap (pixel ratio not considered)
var canvas = document.getElementById("myCanvas"),
vwWidth = window.innerWidth,
vwHeight = window.innerHeight,
percent = 60;
canvas.width = Math.round(vwWidth * percent / 100); // integer pixels
canvas.height = Math.round(vwHeight * percent / 100);
// not to be confused with the style property which affects CSS, ie:
// canvas.style.width = "60%"; // CSS only, does not affect bitmap
If you want to support retina then you need to use the window.devicePixelRatio and multiply it with the sizes. In this case CSS would be necessary as well (combine with code above):
var pxRatio = window.devicePixelRatio || 1,
width = Math.round(vwWidth * percent / 100),
height = Math.round(vwHeight * percent / 100);
canvas.width = width * pxRatio;
canvas.height = height * pxRatio;
canvas.style.width = width + "px";
canvas.style.height = height + "px";

Almost all size parameters in HTML5 are going to be in pixels. If you're experiencing issues drawing the canvas with your current code, try taking out the self-closing block at the end:
<canvas id="myCanvas" width="200" height="300"></canvas>
You may also consider viewing the properties of the canvas element as defined by W3 Schools: http://www.w3schools.com/html/html5_canvas.asp

use css to setup your canvas styles
<canvas id="el"></canvas>
<style>
#el{
display: block;
width:100%;
height: 100%;
}
</style>

Related

Fit (contain) <img> of unknown size to parent, keeping aspect ratio WITHOUT img-element having same w/h as parent [duplicate]

I realise this has been asked many times under many guises, but most solutions seem to not care about the resulting image height, or only scale in one direction. This:
min-width: 100%;
height: auto;
isn't a solution.
I'm trying to fit an image to the height and width so that it can be dynamically injected into a number of places in different systems and sites, so I don't necessarily know what the parent object is going to be - might be a div with or without overflow set, or a p, or the body - or its dimensions; The parent container mustn't change size just by injecting my image/script .. jQuery is NOT available.
I can't see how the css3 background technique would work.
Proportional scaling is as easy as using a ratio:
<img onload="scale(this)" src="screenshot.png">
<script type="text/javascript">
function scale(img){
var p = img.parentNode,
x = p.offsetWidth,
y = p.offsetHeight,
w = img.naturalWidth,
h = img.naturalHeight;
ratio = h / w;
if (h >= y) {
h = y;
w = h / ratio;
img.style.width = w + "px";
img.style.height = h + "px";
} else if(w >= x) { //} && ratio <= 1){
w = x;
h = w * ratio;
img.style.width = w + "px";
img.style.height = h + "px";
}
}
</script>
but this only scales in one plane - I need it to continue to scale both width and height until it fits into the parent container space neatly in both dimensions. If the image is smaller than the parent container, it should scale UP to fill proportionally.
Adapt image to fit parent container (of unknown size) without stretching image
Instead of messing with JS, let CSS do the job!
Set your image to 100%; height and width;
Replace your image's src with a transparent pixel and set it's background to the actual src.
Use CSS's background-size on your (now) full-sized image:
contain (image will cover the parent completely)
cover (image will respect image proportions instead)
Example using contain
function scale( img ) {
if(img.isScaled) return;
img.style.background="no-repeat url("+ img.src +") 50%";
img.style.backgroundSize="contain"; // Use "contain", "cover" or a % value
img.style.width="100%";
img.style.height="100%";
img.isScaled=true; // Prevent triggering another onload on src change
img.src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7";
}
<div style="width:300px; height:300px; background:#000; margin:10px;">
<img onload="scale(this);" src="//placehold.it/1200x600/f0f">
</div>
<div style="width:300px; height:300px; background:#000; margin:10px;">
<img onload="scale(this);" src="//placehold.it/400x600/cf5">
</div>
Tested in: FF, CH, E, IE(11), SA
NB: The transparent pixel data is used solely to prevent the browser's Missing Iimage Icon that would be otherwise caused by doing img.src = "";
http://caniuse.com/#search=background-size
I used this code to fit a video to its parent:
var parent = vid.parentNode,
vw = vid.videoWidth,
vh = vid.videoHeight,
vr = vh / vw, // video ratio
pw = parent.offsetWidth,
ph = parent.offsetHeight,
pr = ph / pw; // parent ratio
if(pr > vr) {
vid.style.width = 'unset';
vid.style.height = `${ph}px`;
} else {
vid.style.height = 'unset';
vid.style.width = `${pw}px`;
}

Pixi.js - Unable to set sprite width to full width of canvas

Ultimately I want to have a canvas that fills the entire viewport width of the browser and have an image on the canvas fill the entire width of that canvas. I'm taking advantage of pixi.js's displacement filter so that I can create a pseudo 3d effect using a depth map underneath it. The code I'm currently using is
let app = new PIXI.Application();
var w = window.innerWidth;
var h = w / ratio;
app.view.style.width = w + 'px';
app.view.style.height = h + 'px';
document.body.appendChild(app.view);
let img = new PIXI.Sprite.from("images/horses.png");
img.width = w;
img.height = h;
app.stage.addChild(img);
depthMap = new PIXI.Sprite.from("images/horses-depth.png");
depthMap.renderable = false;
depthMap.width = img.width;
depthMap.height = img.height;
img.addChild(depthMap);
app.stage.addChild(depthMap);
displacementFilter = new PIXI.filters.DisplacementFilter(depthMap, 0);
app.stage.filters = [displacementFilter];
Here's a screenshot of it in action.
I even tried manually setting the width to the viewport pixel width on the canvas and the sprite to the actual pixel width of the viewport width and it still wasn't the right size. Manually setting the width for the viewport and sprite to the exact same number also doesn't work; the sprite is inexplicably smaller than the canvas.
I tried to look at the documentation of the sprite class and see if there is something unusual about how sprites handle widths but I couldn't find anything https://pixijs.download/dev/docs/PIXI.Sprite.html
How can I create a pixi.js sprite that fills the entire width of the canvas in order to make both the canvas and the sprite fill the entire viewport width?
pixijs.download
PixiJS API Documentation
Documentation for PixiJS library

HTML5 canvas: how do I query or modify the underlying bitmap dimensions as opposed to the DOM element dimensions?

I'm using an HTML5 canvas element:
<style>
#myCanvas {
width: 100%;
height: 100%;
object-fit: contain;
}
</style>
<canvas id="myCanvas" ontouchstart="..." />
I understand that there is an underlying bitmap, and then there is a DOM element that this bitmap is boxed in, and the 2 objects have different dimensions, so e.g. the bitmap is scaled/squished to fit into the DOM element. It would be easier for me to understand if the bitmap dimensions always equalled the DOM element dimensions, but that's not how it works.
How do I query the respective dimensions?
How do I set the respective dimensions?
How do I see the 2 sets of dimensions in the Chrome developer tool?
How do I keep the 2 sets of dimensions in sync?
This is important because mouse-clicks and finger touches are delivered in DOM coords but we'd usually need to interpret them in canvas coords.
(And a related question: have I done it correctly, to set the DOM element to expand to the maximum dimensions allowed by the parent?).
To get the dimensions of the canvas's underlying bitmap:
var w = canvas.width;
var h = canvas.height;
To get the dimensions of the DOM element:
var w = canvas.clientWidth;
var h = canvas.clientHeight;
To set the canvas's underlying bitmap:
canvas.width = 900;
canvas.height = 400;
To set the DOM element's dimensions, this is down to CSS styles and whatever else is on the screen and it's a more complex question.
In Chrome, "Developer Tools", Chrome displays the DOM element dimensions and I couldn't find any way to get the canvas underlying bitmap dimensions other than typing in "canvas.width" and "canvas.height" into the commandline.
As for trying to arrange such that height==clientHeight and width=clientWidth , I would guess that it's possible but it's probably also difficult and probably undesirable.
So to map a touch action or mouseclick from DOM element coords to canvas bitmap coords, a simple scaling operation seems sufficient:
function elementCoordsToCanvasCoords(X,Y)
{
X = X * canvas.clientWidth / canvas.width;
Y = Y * canvas.clientHeight / canvas.height;
return [X,Y];
}
function onTouchStart(event)
{
fingerStart(event.changedTouches[0].clientX, event.changedTouches[0].clientY);
}
function fingerStart(X, Y)
{
[X,Y] = elementCoordsToCanvasCoords(X,Y);
...
}

Is it possible to keep canvas text sharp and responsive

When I give the canvas element width: 100% it gets pixelated even at a really small size. I tried giving the canvas itself a big size but it changes nothing. How can I keep the text sharp?
http://jsfiddle.net/kpknhuoa/
Setting Canvas Tag's size though css is not the best way do it.
Cause it enlarges the canvas's original size by a ratio of the width and height values you specify in css.
Below is how to set canvas width to the size of the window.
var can = document.getElementById('overlay'),
ctx = can.getContext("2d");
//innerWidth and innerHeight values of the window are the screen size.
can.width = window.innerWidth;
can.height = window.innerHeight;
ctx.font = "Bold 36px 'Helvetica'";
ctx.fillStyle = "black";
ctx.fillRect(0,0,1000,1000);
ctx.globalCompositeOperation = 'destination-out';
ctx.fillText("Some Text", 25, 50);

How to rotate an image on the canvas and expand the parent so that the image is not cut away?

How to rotate an image on an HTML5 Canvas, without loosing any image data? I mean if rotation causes the image dimensions to increase, I want to expand the Canvas container as well, so that the image is not cut off. The following image might say better:
The brown colored box is actually the container that wraps the Canvas. I want to expand it (and the Canvas to fit the image) when the Canvas is rotated, so that the image is not cut off.
Update:
The image could be larger than the Canvas hence I'm using a bounding box method to calculate proportional sizes with the parent container to fit the image. So the Canvas's style dimensions will be the calculated ones whereas it's height and width attributes will be the image dimensions.
Any help is appreciated!
This function will resize your canvas to exactly fit the rotated image. You must supply the width and height of the image and it's current rotation angle in degrees.
[Edited: OOPS! I should have converted the angle to radians ... And ... the canvas width/height should be changed, not the css width/height]
function resizeCanvasContainer(w,h,a){
var newWidth,newHeight;
var rads=a*Math.PI/180;
var c = Math.cos(rads);
var s = Math.sin(rads);
if (s < 0) { s = -s; }
if (c < 0) { c = -c; }
newWidth = h * s + w * c;
newHeight = h * c + w * s ;
var canvas = document.getElementById('canvas');
canvas.width = newWidth + 'px';
canvas.height = newHeight + 'px';
}