Canvas element not maintaining height of parent Div - javascript

I have a <canvas> in a div and in order to keep its bounds equal to the div I'm using the following code (I'm creating some of my html/css using Javascript for unrelated reasons, I assume doing in JS should be equivalent).
when I create and add the canvas:
this.canvas = document.createElement("canvas")
this.canvasContainerDiv.appendChild(this.canvas)
this.canvas.style.backgroundColor = "orange"
this.canvas.style.width = "100%"
this.canvas.style.height = "100%"
this.canvas.width = this.canvasContainerDiv.clientWidth
this.canvas.height = this.canvasContainerDiv.clientHeight
Then in the window resize callback:
window.onresize = (e) => {
this.canvas.width = this.canvasContainerDiv.clientHeight
this.canvas.height = this.canvasContainerDiv.clientHeight
}
Unfortunately, the canvas doesn't quite fill the bounds of the parent div. It leaves a few pixels of missing height. So that if I resize the window such that the parent div is 522, the canvas' clientHeight will be 518 or something. In addition, as I resize the window's height, the canvas will grow in height monotonically.
I have many questions about this. 1) is assigning the parent div's clientHeight to the canvas' height property the right way to keep the canvas' height matching it? 2), can I size the canvas' element to its parent div with css width/height alone? 3) why does the canvas grow and grow when I resize the window? 4) why does the canvas' clientHeight not its height (although that is wrong too) wind up coming out slightly smaller than the parent div's clientHeight? the width's match fine?
Some extra information. If I replace the canvas with a div element, I don't see either of the problems I mentioned. The div now spans the exact height of its parent, and doesn't suffer from that infinite height growth issue. This leads me to believe that the sizing issues are related to the canvas' own functionalities like context/drawing size/height properties, etc..

I've run into this before. Try adding the following styles:
html, body { padding: 0; margin: 0; width: 100%; height: 100%; }
I think this has helped me before as well:
body { overflow: hidden; }
If those don't do the trick, there are all kinds of other weird things that can cause undesirable/unexplainable space, sometimes setting line-height: 0, font-size: 0 helps
I just remembered something else that might work without any of the above. Make your canvas { position: absolute; top: 0; left: 0 }

Related

change image manually as window sizes

I used js to set image width and height according to window size. But in some cases when the browser is very wide, the image's hight exceeds all its father element's height. As a result, the bottom part of the image is not shown. How can I solve this?
I used bootstrap and swiper in this project and the image I want to change is inside my swiper division. I set and all the image's father elements' height to 100%. Here is my js code to change is image dymanically. The image size is 2560*1440.
if(winWidth/winHeight < 2560/1440) {
imgHeight = winHeight;
imgWidth = winHeight/1440 * 2560;
}else {
imgWidth = winWidth;
imgHeight = winWidth/2560 * 1440;
}
attr = "width:" + imgWidth + 'px;height:' + imgHeight + 'px;margin-left: -' + imgWidth/2 + 'px;margin-top:-' + imgHeight/2 + 'px';
$('.main .swiper-slide > img').attr('style',attr);
PS:
Sorry I didn't make it clear. The following methods you provided scale the image down in vertical view and so leaves much blank in the page. Actually I want my image's height to occupy the whole window's height, no matter in vertical window or horizontal window. And if the window is wide enough, image's width equals the window's width, otherwise cut the image in width and make it equals the window's width too.
#patstuart is correct, this is much better handled directly through CSS. It's pretty amazing how many styling issues (go figure) can be solved without writing a single line of JavaScript. So to answer your second question, let's figure out how it can be done with CSS. Without seeing a fiddle or your actual page / image, I'll just shoot from the hip here. If I understand correctly, you want the full image to display at its correct ratio no matter what the width / height of the screen is. If that's the case, here's a nice little trick:
.main .swiper-slide {
width: 100%;
height: 0;
/* Padding bottom should be the height's ratio to the width.
Which in this case, would be 56.25% */
padding-bottom: 56.25%;
}
.main .swiper-slide > img {
width: 100%;
}
That is how aspect ratio can be handled with CSS. Let me know if that resolves your issue or if you have any other questions. CSS was made for styling so always look for a solution there first.

Maintaining aspect ratio of of iframe

I have an iframe that I want to maintain the aspect ratio at 16:9 (height/width) right now there is an box below the iframe that I don't want the iframe to ever overlap. So I can't use the padding bottom trick because it causes the video to overlap the box. How can I get the maximum width and height that the iframe can attain in the remaining space?
So for example let's say I have a window that is 1200px by 600px, 50px is used for a box. I want the iframe to take the maximum width and height on the remaining 1200px by 550px and still keep its aspect ratio and not ever go below the box at the bottom of the page. How can I do that using jquery? Also as the window resizes the iframe should keep its aspect ratio
I'm asking for the formula that embedded videos use to maintain their aspect ratio in an iframe. When I embed an iframe that has a video in it the video always maintains its aspect ratio by adding black boxes around it.
Here's the HTML:
<div class="iframe-container">
<iframe></iframe>
</div>
<div class="box"></div>
This is pretty straightforward and can be done with CSS, if you know the expected aspect ratio. For video embeds at 16:9 (56.5%), it's done like this.
You can add max-height and max-width properties to the container just as you would any other element. The height is 0 and the padding is simply set according to the aspect ratio you want. The iframe is set to fill the container width and height so it will conform to the aspect ratio based on the padding.
.iframe-container {
position: relative;
padding-bottom: 56.5%;
height: 0;
}
.iframe-container iframe {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
Update: You can do this much better with vw units.
This will work if your iframe is intended to be the full width of the browser. Otherwise you can do some calculations on it. But, for a full width iframe that you want to preserve aspect ratio on, it goes as follows (for 16:9 aspect ratio):
iframe {
width: 100vw;
height: 56.5vw;
}
Maintaining an aspect ratio is pretty straightforward with some conditional math, over time.
Generally, we have a container, a thing contained, and a known ratio (16/9). The height or the width can be determined by trapping the thing in the container (checking for out of bounds) and computing the other value from the ratio.
Update : once you have the new values, check for out of bounds. In this case, a min height and a max width.
A bit like so:
// if the iframe height (container width / ratio) is greater than the container height
if ( (cW / RATIO) > cH){
h = cH; // set the height equal to the container
w = cH * RATIO; // set the width equal to the container height * ratio
} else {
w = cW; // set the width equal to the container
h = cW / RATIO; // set the height equal to the container width / ratio
}
// Ok so, now that the iframe is scaled up, check for out of bounds
if ( iH < MIN_HEIGHT ){
iH = MIN_HEIGHT; // set the height to the const
iW = iH * RATIO; // use the same basic formula, but use the new value
}
if (iW > MAX_WIDTH){
iW = MAX_WIDTH; // set the width to the const
iH = iW / RATIO; // same formula, new value
}
- Working fiddle with some discussion.
- Updated fiddle with some out of bounds checks.
You can, obviously, work some extra math into the computation to make space for a control bar, or whatever. This is just the basic principle, in a very simple state. I almost always have some additional checks against max width, or do some positioning or whatever. But this should be a good start.
Cheers -

CSS "position:fixed": mobile zoom

I'm trying to solve an issue with css "position:fixed" property on mobile browsers. I have a fixed div:
<div id="logo">
...other content here...
</div>
with css:
#logo{
position: fixed;
-webkit-backface-visibility: hidden;
bottom: 100px;
right: 0px;
width: 32px;
height: 32px;
}
So, usually the behaviour is exactly the desired one, with the div position always on the bottom right of the window, indipendently of the scroll position.
My issue is that on mobile browsers, when the users zoom the page, after a certain zoom level the div position is wrong (sometimes the div disappear out of the window).
I know that fixed position is not well supported on mobile browsers, but I wonder if there is some workaround. I tried with this js code onScroll event:
window.addEventListener('scroll', function(e){
drag.style['-webkit-transform'] = 'scale(' +window.innerWidth/document.documentElement.clientWidth + ')';\\I want to avoid zoom on this element
var r = logo.getBoundingClientRect();
var w = window.innerWidth;
var h = window.innerHeight;
if(r.right != w){
rOff = r.right - w;
logo.style.right = rOff;
}
if(r.top+132 != h){\
tOff = r.top + 132 - h;
logo.style.bottom = tOff;
}
});
Unfortunately, the code seems to return the wrong position.
Does anyone have any tip?
Ok, that's how I solved the issue...I hope that could help anyone to simulate fixed position on iOS devices.
I switched the position from fixed to absolute;
Attach to window a listener to get the new position when the page is scrolled or zoomed,
setting window.onscroll and window.onresize events with the following function:
function position() {
drag.style.left = window.innerWidth + window.pageXOffset - 32 + 'px';
drag.style.top = window.innerHeight + window.pageYOffset - 132 + 'px';
}
Do you want to catch if zoom is active?
There's no window.onZoom listener, but you can read this thread:
Catch browser's "zoom" event in JavaScript
and this answer: https://stackoverflow.com/a/995967/3616853
There's no way to actively detect if there's a zoom. I found a good entry here on how you can attempt to implement it.
I’ve found two ways of detecting the zoom level. One way to detect zoom level changes relies on the fact that percentage values are not zoomed. A percentage value is relative to the viewport width, and thus unaffected by page zoom. If you insert two elements, one with a position in percentages, and one with the same position in pixels, they’ll move apart when the page is zoomed. Find the ratio between the positions of both elements and you’ve got the zoom level. See test case. http://web.archive.org/web/20080723161031/http://novemberborn.net/javascript/page-zoom-ff3
You could also do it using the tools of the above post. The problem is you're more or less making educated guesses on whether or not the page has zoomed. This will work better in some browsers than other.
There's no way to tell if the page is zoomed if they load your page while zoomed.
Just a theory, but you may want to try setting the bottom/right positions in % rather than px.
I think what you're seeing when using pixel measurements is just the zoom effecting the pixels. Or to put it better, when you zoom-in the pixels appear larger and that throws off the position of the element, even pushing it out of the view-port on smaller screens.
Example using pixel positioning
Notice that even on a desktop as you zoom-in and out the element appears to move up and down?
Example using percent positioning
In this example the element appears to stay in the bottom right corner, because it is always positioned at 10% from the bottom of the view-port.
#logo{
position: fixed;
-webkit-backface-visibility: hidden;
bottom:10%;
right: 0;
width: 32px;
height: 32px;
}
Having two different z-index for the logo and the rest of the page could help. Allowing zooming only to the rest of the page and not to the z-index layer where logo is included. So, this might not affect the stretching on the logo.
We can
Implement a ZOOM listener
Attach it to browser
Make the zoom listener change the zoom level of the element (modify the elements position) using z-index as a factor.

Can this Flash effect be receated with JS and css?

take a look at the first panel (in red) on the homepage.
http://www.boomtown.co.za/
I'd like to do something like this with an invisible image and only reveal parts of it as the mouse tracks over. Is this possible without using Flash?
This can be done quite easily using some css and background positioning with javascript. Here's 2 examples : http://jsbin.com/ococal/3
The source code is quite easy to understand and you can start working out with this.
You could do it by using a transparent png image that was a radial fade from transparent in the centre to semi-transparent at the edges and making it follow the mouse.
document.onmousemove=mousefollower
function mousefollower(e){
x = (!document.all)? e.pageX : event.x+document.body.scrollLeft;
y = (!document.all)? e.pageY : event.y+document.body.scrollTop;
document.getElementById('myImage').style.left = x + 'px';
document.getElementById('myImage').style.top = y + 'px';
}
Obviously you can use jQuery for this too, and set the mousemove function to occur only over a specific div. Also make sure the image you use is large enough (at least twice the size) so that the edges don't show up when you move to the far sides of the div (this means that for large areas you will need a huge image so it may get a big laggy). Put the image in the div and set overflow to none to clip anything that falls outside of the area.
It is possible yes, but only in modern browsers (chrome, safari, firefox, opera).
You would need to have two <div>'s
like so..
<div class="container">
<div class="revealer"></div>
</div>
and CSS like so
.container {
position: relative;
background: url("images/your-background.jpg");
}
.revealer {
position: absolute;
//set the mask size to be the size of the container
top: 0;
left: 0;
bottom: 0;
right: 0;
z-index: 1;
background: url("images/your-background-over-state.jpg");
//css3 image masks, this is not cross browser, see the demo for
// cross browser syntax
mask: url("images/mask-shape.png") no-repeat;
//make sure the mask is off screen at first, by setting the mask position
//to minus the width and height of your mask image
mask-position: -300px -300px
}
And the JS
window.addEventListener('load',function(){
var background = document.querySelector('.container'),
revealer = document.querySelector('.revealer');
background.addEventListener('mousemove', function(e){
//the minus represents the half the width/height of your mask image
// to make the reveal centred to the mouse.
var x = e.offsetX - 150,
y = e.offsetY - 150;
// move the position of the mask to match the mouse offsets
revealer.style.maskPosition = x+'px '+y+'px';
return false;
});
});
Because of the way this works you need to ensure that any other content in the .container has a higher z-index than the mask to ensure the content is not masked. To do this add relative positioning to the elements in the container
like so
.container *:not(.revealer) {
position: relative;
z-index: 2;
}
Images used in masks are images where the solid colours create the visible or fill area, and the transparent areas are the mask or cut out.
Demo with cross browser code

Forcing a negative bottom margin on Flash

I have an .swf navigation carousel that is 650 pixels high, the bottom 200 pixels being reserved for the reflection of the carousel. The reflection is very subtle and is not considered important information, so we would like to remove vertical scrollbars when the window is high enough to fit the topmost 450 pixels, but not the reflection.
I tried to accomplish this by setting a margin-bottom: -200px to the flash <object> but this only made the container's height shrink 200 pixels, causing the background pattern to cut before the bottom of the page. The Flash itself is still taking up 650 pixels.
Is there some "proper" fix to this, other than hiding/showing the scrollbars actively using javascript?
You could try using css:
#idOfElement {
overflow-x: hidden;
overflow-y: hidden;
}
My apologies, I thought you were trying to remove scrollbars from the element. If you want to get them off of the window, just do body {overflow: hidden}
Parts of the element will only get cut off when you do overflow: hidden if the content of the element is larger than its container, so you may want to look into that.
Try this to hide the overflow when the window height reaches 450px:
window.onresize = function () {
var height = window.innerHeight;
if (height > 450) {
document.body.style.overflow = "hidden";
}
}
An issue you may have with this is that some browsers like to fire a lot of resize events during resizing, instead of one after, which could impact performance. Paul Irish wrote a short blog post about mitigating this at http://paulirish.com/2009/throttled-smartresize-jquery-event-handler/ and I think that jQuery's .resize() function does this automatically.

Categories