Problem with scrollable canvas in front of image - javascript

So, im doing a canvas that is deployed in front of an image. The image is in the background and because of it's size I need to put it inside an scrollable area.
Rendering the image inside the scroll it's not a problem and works fine. The problem comes when I do the same with the canvas.
Right now, the canvas width and height is calculated after loading the image.
img.onload = function () {
if (img.complete) {
self.canvas.height = img.height;
self.canvas.width = img.width;
The canvas data is correctly calculated and can be seen inpecting the html but it doesn't work. It's like it doesn't has width or height.
The CSS and HTML are very simple.
<div id="container" hidden>
<img id="mapImage">
<canvas id="mapCanvas">
</canvas>
</div>
#container {
max-height: 75vh;
max-width: 100vw;
overflow: scroll;
}
#mapCanvas {
border: 1px solid #000000;
}
I saw a post solving a problem like this but without the image.
What is what I'm missing?
Thanks in advice.

Related

why html5 canvas is not full screen when vertical scrollbar appears

I'm using a full screen canvas as background of the first section of my page. But as soon as I add the second section and vertical scrollbar appears, the height of canvas reduces a little bit and a gap appears. here's my code:
P.S: Sorry, my code contained bugs, I fixed them. now you can see the red gap.
var canvas = document.getElementById('canvas')
var c = canvas.getContext('2d')
scaleCanvas()
window.addEventListener("resize", scaleCanvas)
function scaleCanvas() {
canvas.width = window.innerWidth
canvas.height = window.innerHeight
c.fillStyle = 'black'
c.fillRect(0, 0, canvas.width, canvas.height)
}
* {
box-sizing: border-box;
max-width: 100%;
}
body {
margin: 0;
padding: 0;
}
#first-section {
position: relative;
min-height: 100vh;
background-color: red; /* to see the gap */
}
#content {
position: relative;
z-index: 2;
}
#second-section {
min-height: 100vh;
background-color: blue;
}
#canvas {
display: block;
padding: 0;
margin: 0;
border: none;
position: absolute;
top: 0;
left: 0;
z-index: 1;
}
<div id="first-section">
<canvas id="canvas"></canvas>
<div id="content">content</div>
</div>
<div id="second-section"></div>
Assuming you mean full screen, and not full page. The two are very different.
If you mean full page then the link to the Screen API will also give you details on obtaining the page size.
Size full screen canvas.
The problem is that you have content that extends outside the page width and height (innerWidth, innerHeight)
The elements with ids first-section, content, and second-section must be inside the display area or else you will get a scroll bar. The scroll bar will change the innerWidth, innerHeight values subtracting the scrollbar width or height depending on which is visible.
To prevent scroll bars the best option is to keep all content inside innerWidth, and innerHeight
Full screen with scroll bars.
If you want have the scroll bars and you are using full screen you can use the Screen API to get the width and height of the display in pixels. You can set the canvas size to match the screen without the scroll bars effecting its size.
Note Do read the provided link to Screen as what defines the screen may not be as expected. EG more than one monitor, or device orientation will effect how you use the API.
Basic example
Thus when in full-screen mode you can set the canvas size and ignore scroll bars with
function sizeFullScreenCanvas() {
canvas.width = screen.width;
canvas.height= screen.height;
}

Horizontally and vertically centered iframe with aspect ratio 16:9 that uses as much screen estate as possible without being cropped anywhere

Requirements:
The HTML: The iframe HAS to be inside of a containing div. See code down below.
The CSS: The container should be able to have ANY valid width and height using the vw and vh viewport units. Se code down below.
Yes, the width and height HAS to be in vw and vh.
The static video preview image should NEVER be cropped.
The static video preview image should NOT have any black bars above and below (letterboxing).
The static video preview image should NOT have any black bars to the left or to the right (pillarboxing).
The static video preview image should use as much space estate as possible inside the div that contains it.
The static video preview image should ALWAYS keep its aspect ratio of 16:9.
Scrollbars should NEVER appear.
The static video preview image should be centered vertically as well as horizontally inside the div that contains it.
Responsive Web Design.
When resizing the browser or viewport all of the above requirements should be fulfilled.
HTML:
<div class="container">
<iframe></iframe>
</div>
CSS:
.container {
width:90vw;
height:50vh;
}
Same solution, but no extra markup for keeping the ratio.
JsFiddle with same comments totally not needed.
<!DOCTYPE html><html lang="en"><head><meta charset="utf-8">
<title>Fully Container Centred Iframe</title>
<meta name="generator" content="PSPad editor, www.pspad.com">
<style>
.container {
display:table-cell; /* (specs: omitted table parts, the browser will insert mandatory elements in the dom tree) */
position:relative;
padding:; /* optional, margins ignored */
width:100vw; /* any value */
height:1vh; /* will expand by the :before element */
overflow:hidden; /* hide eventual black bars */
background:tan; /* bg-colors just for demo testing */
vertical-align:middle;
text-align:center;
}
.container:before {
display:block;
padding-top:56%; /* keeps the 16/9 ratio for the AP */
height:0;
background:red;
content:"\a0";
}
.container iframe {
position:absolute; /* to be ratio consistent */
top:-.5%;
left:-.5%; /* overflow eventual black bars */
border:0;
width:101%; /* grow some to avoid thinner black bars */
height:101%;
overflow:hidden; /* for html5 browsers the html attribute is depreciated */
background:gold;
}
</style>
</head><body>
<div class="container">
<iframe scrolling="no" src=""></iframe>
</div>
</body></html>
Using JavaScript, you can listen for the resize event, which fires whenever the browser's window changes shape. Then, with some simple algebra you can calculate the dimensions of the iframe based on the dimensions of the container. Here is a demo that shows all of the requirements.
"use strict";
var container = document.querySelector('.container');
var frame = container.querySelector('iframe');
function resizeVideo() {
frame.width = frame.height = 0;
var width = container.offsetWidth;
var height = container.offsetHeight;
if (height * (16 / 9) <= width) {
frame.height = height;
frame.width = height * (16 / 9);
} else {
frame.width = width;
frame.height = width * (9 / 16);
}
}
window.addEventListener('load', resizeVideo);
window.addEventListener('resize', resizeVideo);
.container {
width: 90vw;
height: 50vh;
display: table-cell;
text-align: center;
vertical-align: middle;
}
<div class="container">
<iframe src="https://www.youtube.com/embed/BKhZvubRYy8" frameborder="0" allowfullscreen></iframe>
</div>
if you want Responsive use
.container, iframe {
width:100%;
height:auto;
}
.container {
width:90vw;
height:50vh;
}
.container iframe {
width: 100%;
height: 100%;
}
Seems to work quite nicely in this fiddle https://jsfiddle.net/1q10L7hj/
why don't you just use the calc method to get the aspect ratio width you are wanting?
HTML
<div class="container">
<iframe src="" frameborder="0"></iframe>
</div>
SCSS
<style>
$width = 80vw;
.container {
width: $width;
height: calc(($width/16) * 9);
position: relative;
}
iframe {
position: absolute;
width: 100%;
height: 100%;
top: 50%;
left: 50%;
-webkit-transform: translate(+50%, -50%);
transform: translate(+50%, -50%);
}
</style>
then you can change the width of it anywhere and apply whatever positioning you want on the container div and the iframe with follow suit
I think the table-cell display could solve this. Just apply it on the container so the iframe is the content
According to specs the browser will insert dummy elements where it needs to render the cell correctly and fully centre and to contain its content and if it need, grow with it.
The requirements: I think some of them is beyond the scope of your question, they will also depend on what is loaded in the iframe, out of control of this container document. My suggested code is simple, but I believe it meets all requirements possible for the iframe parent and still be crossbrowser friendly.
The forbidden black bars and the mandatory aspect ratio could still be at fault in the loaded document. If you can't control whats loaded, the last option might be the "srcdoc" and "seamless" attributes, but that would exclude e.g. all IE versions.
JsFiddle with some comments totally not needed. Hope the edit below solves the case.
Anyway, I had fun! Thanks! :)
<!DOCTYPE html><html lang="en"><head><meta charset="utf-8">
<title>Fully Container Centred Iframe</title>
<meta name="generator" content="PSPad editor, www.pspad.com">
<style>
.container {
display:table-cell;
padding:;
width:100vw;
height:20vh;
background:tan;
vertical-align:middle;
text-align:center;
}
.container .ratio{
display:inline-block;
position:relative;
padding-bottom:56%;
width:100%;
height:0;
overflow:hidden;
vertical-align:middle;
}
.container iframe {
position:absolute;
top:-1%;
left:-1%;
border:0;
width:102%;
height:102%;
overflow:hidden;
vertical-align:middle;
}
</style>
</head><body>
<div class="container">
<div class="ratio">
<iframe scrolling="no" src=""></iframe>
</div>
</div>
</body></html>
I have gotten the result you wanted, I however had to add an extra div as the parent of the .container class. This JSFiddle should work for users on chrome (Windows desktop version) however when I tried to use the same fiddle on Edge and IE11 I found that it would create the undesired letter-box effect due to the image cover zooming too far out.
HTML
<div id="wrapper">
<div class="container">
<iframe scrolling="no" src="https://www.youtube.com/embed/YL9RetC0ook" frameborder="0" allowfullscreen>
</iframe>
</div>
</div>
CSS
body {
margin: 0;
}
#wrapper {
width: 90vw;
height: 50vh;
}
.container,iframe {
width: 100%;
height: 100%;
}
I am not sure if this works for Firefox, so perhaps if you have Firefox you can try it on my JSFiddle. However for Chrome (at the very least) this should be the solution you where looking for as stated by the requirements you listed.
I would recommend using a JavaScript window.resize listener to solve this kind of an issue. Cannot write code today cause I have a pretty tight schedule, but I'll try writing an algo:
On window resize, compute window width (wW) and window height (wH);
Determine container width (cW) as per wW (say cW = wW-10 to get almost all the width available - you can omit the -10 if you want);
Determine container height (cH) as per cW computed above: cH = cW * 9 / 16;
Now, if cH > wH (i.e. the container is not fitting into the screen vertically because it is too wide), we should revise cW as per available window height. In this case, cH = wH-10 (to get almost all the vertical space available - again, you can omit the -10 if you want) and then cW = wH * 16 / 9;
You should have a valid cW and cH now to make you container fit into the window without going out of the screen and you can apply it to the container.
To center the container to the screen, use position: absolute, left: 50%; top: 50%; in your CSS. When you update the cW and cH, also update margin-left: -(cW/2); margin-top: -(cH/2);
This is the concept - you can improvise as per your needs. I hope it helps.

jquery, resize a canvas without scaling

I was trying to put a canvas in a container. I wanted the canvas to have the same size as the container. To do this I used JQuery, however, this turned out to scale my canvas. This was not my intention, especially because I draw after resizing. Doing seemingly the same thing in good old fashion JavaScript gives me the expected result.
I personally did not expect the JQuery result and it took some time before I figured out the problem. Does anybody know why they opted for this implementation and why it gives a different result? I hope by sharing this I can save some people a lot of time!
Thanks for anybody willing to research this further of fix this!
Here is some example code:
<html>
<head>
<title>Canvas resizing</title>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
<style type="text/css">
#container1{
background-color: green;
width: 100px;
height: 100px;
margin: 50px auto;
}
#container2{
background-color: red;
width: 100px;
height: 100px;
margin: 50px auto;
}
</style>
</head>
<body>
<div id="container1">
<canvas></canvas>
</div>
<div id="container2">
<canvas></canvas>
</div>
<script type="text/javascript">
function draw (canvas) {
var context=canvas.getContext("2d");
context.lineWidth = 5;
context.rect(25,25,50,50);
context.stroke();
}
$(document).ready(function () {
//javascript
var container = document.getElementById('container1');
var canvas = container.childNodes[1];
canvas.width = 100;
canvas.height = 100;
draw(canvas);
//jquery
var container = $('#container2');
var canvas = container.children()[0];
$(canvas).width(100);
$(canvas).height(100);
draw(canvas);
});
</script>
</body>
</html>
The jQuery width and height methods are shorthand aliases for setting the CSS width and height properties. Sizing a canvas using CSS causes the scaled, distorted look you're seeing. Your pure javascript version of the code is setting the width and height attributes of the canvas element. To achieve the same in jQuery you can use:
$(canvas).prop('width', 100)
$(canvas).prop('height', 100)
JSFiddle

How to fill the browser window with a canvas element without creating scroll bars?

I have a problem to get my window size, I try this code:
Javascript
var game;
function game() {
this.canvas = document.getElementById('canvas');
this.canvasWidth = window.innerWidth;
this.canvasHeight = window.innerHeight;
this.initCanvas = function() {
this.canvas.style.width = this.canvasWidth + "px";
this.canvas.style.height = this.canvasHeight + "px";
}
this.run = function() {
this.initCanvas();
}
}
game = new game();
game.run();
I also have
CSS
html, body {
padding: 0;
margin: 0;
}
I only have a canvas in my body.
Problem is, that I have a vertical and horizontal scroll bar. This means the size of canvas is too large. How to make it of the window size without the scroll bars appearing?
It looks like you're just trying to make your canvas have a width and height of 100%. You can do this with just css:
HTML
<body>
<canvas id="canvas"></canvas>
</body>
CSS
body, html {
height: 100%;
width: 100%;
margin: 0px;
}
canvas {
background: #ffcccc;
height: 100%;
width: 100%;
display: block;
}
​
Demo
Or if you want to use your code but get rid of the scroll bars on the window, you need to specify block on the canvas tag.
CSS
canvas {
display: block;
}
Demo
When you use CSS to style your <canvas> element it will get scaled instead of sized. Be sure to set the .width and .height properties on the canvas element instead (ie canvas.width not canvas.style.width).
jsfiddle example
In the example the first canvas element is scaled correctly, the second (using CSS) is not scaled properly. This has to do with a default canvas element size (300x150) that CSS scales.
To prevent getting scrollbars when setting the <canvas> to the full window width/height set the body to overflow:hidden; as used in the jsfiddle above.

Can't get accurate dimensions of my canvas

I don't know why but my JS won't return the correct values of my canvas' dimensions.
I have this to get the values:
temp = document.getElementById('myCanvas');
canvas = new Array();
canvas['width'] = temp.width;
canvas['height'] = temp.height;
My CSS & HTML is:
//html
<canvas id="myCanvas" class="c"></canvas>
//related css
.c{
width:100%;
margin:0 auto;
height:500px;
background-color:green;
position:absolute;
left: 0;
top: 0;
border:1px solid red;
}
The result of the array shows:
width: 300, height: 150
This cannot be correct if the CSS sets it as 500px and it shows on the screen as 500px. Why might this be ?
This is the correct size!
By setting canvas dimensions in CSS, you haven't changed the pixel-by-pixel size of the canvas. It's still the default 300x150, you just stretched the pixels. You can verify this if you draw a circle on the stretched canvas: you will get an ellipse. It's better to change the width and height attributes of the canvas tag directly, and not in CSS.
Source, Example

Categories