HTML5 Canvas fills windows with full resolution - css

I am trying to achieve a layout like this:
where:
Navbar is just a bootstrap-like top menu, 60px of height, always on top
Pop-up menu is fixed in that position (not always visible), always on top
The entire free area (windows w.o. navbar) is filled with Canvas.
Live example: jsFiddle
I have a problem with Canvas. I currently have a simple style:
<canvas id="le_canvas">Y U NO CANVAS</canvas>
...
#le-canvas {
position:absolute;
width:100%;
height:100%;
}
and the canvas is filling the background, but:
the resolution is very low
it doesn't maintain ratio during window resizes.
What I'd like (if it is possible):
full resolution of the area to fill (1:1 pixel on canvas and on screen)
set the ratio of the area to fill
bonus: update the above after window resize

Setting the canvas element in per-centage will not set the actual canvas size which must be set in absolute pixels. What happens here is that you get a canvas with a default size which then is stretched by the html-rendering giving the blurry look.
You therefor need to set the size by using f.ex. the window's sizes in absolute pixels.
You can do this like this (update of fiddle here: http://jsfiddle.net/x5LpA/3/ ) -
Create a function that sets the canvas size based on window size (you will of course need to subtract height of bars etc, but to show the principle):
function initCanvasArea(cnv) {
cnv.width = window.innerWidth;
cnv.height = window.innerHeight;
}
As the canvas content are cleared when the canvas is re-sized you need to render the content again for each time. Therefor it will be smart to extract the render content into a separate function like f.ex:
function renderCanvas(ctx) {
ctx.fillStyle = "rgb(200,0,0)";
ctx.fillRect(0, 0, 55, 50);
ctx.fillStyle = "rgba(0, 0, 200, 0.5)";
ctx.fillRect(20, 20, 55, 50);
}
Now, make the main function a self-invoking one where you also attach an event handler for windo.resize to update the canvas:
$(function () {
var canvas = $('#le_canvas')[0];
var ctx = canvas.getContext('2d');
initCanvasArea(canvas);
renderCanvas(ctx);
window.onresize = function(e) {
initCanvasArea(canvas);
renderCanvas(ctx);
};
})();
And finally edit the CSS-rule by removing the width/height set to 100%;
#le_canvas {
position:absolute;
}
(Tip: a better approach here is to use the fixed attribute for position - plus use a wrapper element, padding, box-sizing.. but that is out of scope for this question).

Is this what you are after? I used $(document).width() and $(document).height() to get the width and height for the rectangle. http://jsfiddle.net/x5LpA/1/

Related

CSS: Element fixed to viewport height, scaled proportionally, centered

I have elements which have a set height of 100% viewport height. Inside of these are a background image which is also fixed to the same height - so the image's top and bottom are always visible, it's centered, and sometimes it's edges get cut off.
What I'm trying to add on top of this is another element which matches the same behavior of the background image (to place other things over the image, but ensure they always line up).
I have a working example using Javascript, but wondering if this same behavior could be replicated with CSS. The pinkish box is the element which I am scaling based on the viewport's size and it should always match up with the background image behind it.
https://jsfiddle.net/louiswalch/p1rkohzt/
And all the scaling logic is as follows:
var $window = $(window);
var base_width = 1600;
var base_height = 960;
var base_ratio = (base_width / base_height);
var contents = $('SECTION .content');
$window.on('resize', function() {
var window_width = $window.width();
var window_height = $window.height();
var window_ratio = (window_height / window_height);
var scaled_width = (window_height * 100/base_height) * base_width/100;
contents.css({
width: (scaled_width+'px'),
height: (window_height+'px'),
marginLeft: ('-'+scaled_width/2+'px'),
});
}).trigger('resize');

CSS: Make Canvas as big as possible while keeping aspect ratio

I have a Canvas element that is inside a container div. When the user selects an image from his machine, this image should be displayed on the canvas. I want the canvas to be big as possible but at the same time keep the aspect ratio of the image. I know neither the proportions of the image nor the size of the container div, as this is relative to the screen/window size of the user.
If I set max-width and max-height to e.g 100% the canvas will not fill the container if the selected image is smaller then the container. If I set width and height instead of max-width and max-height the canvas doesn't keep the aspect ratio.
Does anyone have an idea how to solve this?
If you're willing to use JQuery (or regular JavaScript), then a solution like this might work:
<script>
// Note: this uses jQuery.
// It makes getting/setting the dimensions easier,
// but you can do this with normal JavaScript
var img = $("#img");
var container = $("#container");
var width = img.width();
var height = img.height();
var maxWidth = container.width();
var maxHeight = container.height();
var ratio = maxWidth / width;
if(height * ratio > maxHeight) {
ratio = maxHeight / height;
}
img.width(width * ratio);
img.height(height * ratio);
</script>
What this does is that it finds the ratio to multiply the width and the height by, whichever one is smaller (so that it will always fit in the window).
Update: Tested on JSFiddle.net. See it here.
I hope this helps you!
After reading your clarification about video, check out the following:
https://jsfiddle.net/d0dox9xt/
body {
background: #eee;
}
#container {
margin:0 2% 0 2%;
}
#v {
position:absolute;
top:0;
left:0;
width:100%;
}
The only trick is setting width:100%; This will maintain aspect ratio.
Note that in the JS
document.addEventListener('DOMContentLoaded', function(){
var v = document.getElementById('v');
var canvas = document.getElementById('c');
var context = canvas.getContext('2d');
}
function draw(v) {
c.drawImage(v, 0, 0);
}
The drawImage function can take many arguments. The first argument is inserting the media, the next two are for positioning. There are many arguments you can have to position and change the height and width. I left them alone so it will follow the CSS rules.
Here is a link to more on placing in canvas: https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/drawImage

Scaling a canvas nicely with css

I'm trying to draw an image on a canvas, then use css to fit the canvas within a certain size. It turns out that many browsers don't scale the canvas down very nicely. Firefox on OS X seems to be one of the worst, but I haven't tested very many. Here is a minimal example of the problem:
HTML
<img>
<canvas></canvas>
CSS
img, canvas {
width: 125px;
}
JS
var image = document.getElementsByTagName('img')[0],
canvas = document.getElementsByTagName('canvas')[0];
image.onload = function() {
canvas.width = image.width;
canvas.height = image.height;
var context = canvas.getContext('2d');
context.drawImage(image, 0, 0, canvas.width, canvas.height);
}
image.src = "http://upload.wikimedia.org/wikipedia/commons/thumb/0/00/Helvetica_Neue_typeface_weights.svg/783px-Helvetica_Neue_typeface_weights.svg.png"
Running in a codepen: http://codepen.io/ford/pen/GgMzJd
Here's the result in Firefox (screenshot from a retina display):
What's happening is that both the <img> and <canvas> start at the same size and are scaled down by the browser with css (the image width is 783px). Apparently, the browser does some nice smoothing/interpolation on the <img>, but not on the <canvas>.
I've tried:
image-rendering, but the defaults seem to already be what I want.
Hacky solutions like scaling the image down in steps, but this didn't help: http://codepen.io/ford/pen/emGxrd.
Context2D.imageSmoothingEnabled, but once again, the defaults describe what I want.
How can I make the image on the right look like the image on the left? Preferably in as little code as possible (I'd rather not implement bicubic interpolation myself, for example).
You can fix the pixelation issue by scaling the canvas's backing store by the window.devicePixelRatio value. Unfortunately, the shoddy image filtering seems to be a browser limitation at this time, and the only reliable fix is to roll your own.
Replace your current onload with:
image.onload = function() {
var dpr = window.devicePixelRatio;
canvas.width = image.width * dpr;
canvas.height = image.height * dpr;
var context = canvas.getContext('2d');
context.drawImage(image, 0, 0, canvas.width, canvas.height);
}
Results:
Tested on Firefox 35.0.1 on Windows 8.1. Note that your current code doesn't handle browser zoom events, which could reintroduce pixelation. You can fix this by handling the resize event.
Canvas is not quite meant to be css zoomed : Try over-sampling : use twice the required canvas size, and css scaling will do a fine job in down-scaling the canvas.
On hi-dpi devices you should double yet another time the resolution to reach the
same quality.
(even on a standard display, X4 shines a bit more).
(Image, canvas 1X, 2X and 4X)
var $ = document.getElementById.bind(document);
var image = $('fntimg');
image.onload = function() {
drawAllImages();
}
image.src = "http://upload.wikimedia.org/wikipedia/commons/thumb/0/00/Helvetica_Neue_typeface_weights.svg/783px-Helvetica_Neue_typeface_weights.svg.png"
function drawAllImages() {
drawImage(1);
drawImage(2);
drawImage(4);
}
function drawImage(x) {
console.log('cv' + x + 'X');
var canvas = $('cv' + x + 'X');
canvas.width = x * image.width;
canvas.height = x * image.height;
var context = canvas.getContext('2d');
context.drawImage(image, 0, 0, canvas.width, canvas.height);
}
img,
canvas {
width: 125px;
}
<br>
<img id='fntimg'>
<canvas id='cv1X'></canvas>
<canvas id='cv2X'></canvas>
<canvas id='cv4X'></canvas>
<br>
It's not good idea to scale canvas and think that you solved the image scale problem.you can pass your dynamic value to canvas,and then draw with that size whatever you want.
here is link of canvas doc: http://www.w3docs.com/learn-javascript/canvas.html
Simple answer, you can't do it. The canvas is just like a bitmap, nothing more.
My idea:
You should redraw the whole surface on zooming, and make sure you scale the image you're drawing to the canvas. As it is a vector graphic, this should work. But you're going to have to redraw the canvas for sure.

Getting a Image to Resize Responsively Before It's Edges Are Reached in Bootstrap 3

I have a small image in my project that I would like to resize responsively any time the resolution changes. I am currently using the class "img-responsive". With this class, the picture doesn't start resizing until the window reaches its edge. In this case, since it's a relatively small picture, this never happens.
Is there a built-in Bootstrap class I can use to have the image resize responsively at all times?
I ended up using JavaScript
$(window).resize(function(){
if($(window).width() < 1100){
var width = $(window).width();
var ceiling_width = 1100;
var difference = ceiling_width - width;
var decrease = difference * 0.2345;
var full_logo_width = 404;
var new_logo_width = full_logo_width - decrease;
$("#my_logo").css({"width": new_logo_width});
}
});
If the browser's width gets lower than 1100px then the picture will start shrinking. My image has a width of 404px by default (if the browser loads with a width of more than 1100px). I wanted the smallest possible width for the image to be a little over 200px. The per pixel decrease to per window width decrease variable (0.2345 in this case) was calculated based on this. I used the following CSS to set an upper and lower limit for the image's width.
#my_logo{
max-width: 404px;
min-width: 210px;
}

How can I autoscale the font size to fit the contents of a div?

I have a div with some text:
<div style="white-space:nowrap;overflow:none;width:50px;">
With some text in it
</div>
How can I scale the font size of the text so all of the text is visible?
Contrary-wise. You could wrap the text in an interior DIV, measure its width with JavaScript. Test if that width is wider than the parent DIV. Get the current font size, and incrementally move it down 1px at a time until inner DIV's width is less than or equal to the outer DIV's width.
I've been doing something like this, to set the text scale relative to the parent (or window) width / height. You can avoid jQuery by using offsetWidth and offsetHeight instead of width.
var setBodyScale = function () {
var scaleSource = $(window).width(), // could be any div
scaleFactor = 0.055,
maxScale = 500,
minScale = 75; //Tweak these values to taste
var fontSize = (scaleSource * scaleFactor) - 8; //Multiply the width of the body by the scaling factor:
if (fontSize > maxScale) fontSize = maxScale;
if (fontSize < minScale) fontSize = minScale; //Enforce the minimum and maximums
$('html').css('font-size', fontSize + '%'); // or em
}
Short Answer: You don't.
You would have to try a size, render it, see if it fits, try another size, render it see if it fits, etc. Then you have to handle the case where the calculated font size is so small no one can read the text.
There are other options, if the text doesn't fit, add an ellipsis (...) to the end of the text, when you mouse over it, the div could expand, you could use a popup window or tooltip with the full text, or put the full text in a larger area of the screen.
Find another way.
Came across this JQuery plugin in my quest to find the same.
Github
Demo
Also came across this Jquery script when I was looking for the same thing. It has the added benefit over the others, as far as I quickly tell, is that it also adjusts for height as well as width.
Comes from here: http://www.metaltoad.com/blog/resizing-text-fit-container
function adjustHeights(elem) {
var fontstep = 2;
if ($(elem).height()>$(elem).parent().height() || $(elem).width()>$(elem).parent().width()) {
$(elem).css('font-size',(($(elem).css('font-size').substr(0,2)-fontstep)) + 'px').css('line-height',(($(elem).css('font-size').substr(0,2))) + 'px');
adjustHeights(elem);
}
}

Resources