Recalculating element size on window resize - javascript

How do I propely use window.addEventListener("resize", () => { }) in the case below, where I need to recalculate size on every window resize:
const viewportWidth = Math.max(
document.documentElement.clientWidth,
window.innerWidth || 0
)
const viewportHeight = Math.max(
document.documentElement.clientHeight,
window.innerHeight || 0
)
const elements = list(48, () => {
const circle = document.createElement("span")
const minSize = Math.round((viewportWidth + viewportHeight) / 72)
const maxSize = Math.round((viewportWidth + viewportHeight) / 21)
const size = random(minSize, maxSize)
Object.assign(circle.style, {
width: `${size}px`,
height: `${size}px`
})
return circle
})
For whatever reason, I’m struggling with this, and I would greatly appreciate any help.

Try this :
window.addEventListener("resize", () => {
const docHeight = Math.max(document.documentElement.clientHeight, window.innerHeight);
document.getElementById('documentHeight').innerHTML = docHeight;
});
<div id="documentHeight">
Open this demo in full page view and resize the window to get the Inner height of the document.
</div>

You may simply encapsulate the above logic within the callback function within your event listener.
For instance,
class yourClass {
constructor() {
window.addEventListener("resize", () => {
// logic to carry out recalculation
elements();
});
}
// the rest of your logic
}
Doing so will ensure that the methods/functions will be called whenever the resize event is triggered on the Window.

Related

How to use value in 1 function in second function

Im still pure beginner with programing. I have this function
window.onload = function () {
currentWidth = window.innerWidth
console.log(currentWidth)
}
This function shows me in console.log what is my window width when i reload the page.
Then i have little bit complicated function which return also function.
const resizeHandler = (function () {
const isBig = () => window.innerWidth > 850
let wasBig = isBig()
return function handler(event) {
//if (isBig() == wasBig) return; // no change
if (window.innerWidth > 850) {
$('.side-bar').removeClass('non-active')
wasBig = true // future use
} else {
$('.side-bar').addClass('non-active')
wasBig = false
}
}
})()
window.addEventListener('resize', resizeHandler)
I have width value in variable called currentWidth I thought when i replace window.innerWidth by variable name currentWidth it's fine but it is not.
Is my logic correct or in javascript is "smater" way to do that please?
Directly call the resize handler on page load as well.
resizeHandler();
window.addEventListener('resize', resizeHandler);
Variables declared inside a function are function-scoped, that means they exist only inside that specific function.
Try:
var currentWidth;
window.onload = function () {
currentWidth = window.innerWidth
}
So now you can replace window.innerWidth with currentWidth, as you asked.
by LL

How to add/remove a scroll event using resize observer

I want to trigger the scroll event when the browser window is 75rem and greater and remove it when the window is smaller.
This only works but doesn't watch for window size change:
const mql = window.matchMedia("(min-width: 75rem)")
const thumb = document.querySelector(".entry-figure")
const rate = 0.5
if (mql.matches) {
document.addEventListener("scroll", () => {
thumb.style.opacity = (100 / window.scrollY) * rate
})
}
I tried the following, but it fails:
mql.addEventListener( "change", (e) => {
if (e.matches) {
document.addEventListener("scroll", () => {
thumb.style.opacity = (100 / window.scrollY) * rate
})
}
})

Using "scroll" listener efficiently

What I'm trying to achieve:
I want few "scroll" listeners that will work smoothly (As smooth as it can be)
What I have so far works but I have noticed that it is not performing well.
I have good PC but when those functions fire all at once there is huge FPS drop that results in bad user experience (drops to about 1/3 of normal performance which results in slideshow on certain elements).
On page where the problem occurs there are in total 5 "scroll" listeners.
3 of them are pretty basic like:
watching if i'm scrolling upwards oraz downwards and applying class to element according to direction (show menu when scrolling up)
checking if element is visible in window and applying class according to it and then don't trigger on same element (triggering css animation).
again checking if element is visible but this time performs function if it is in window visible and then doesn't fire again (listener is removed when function performs).
and now there are 2 listeners that makes much more on scroll
both of them animate certain element according to how far user scroll from top of page
first one widen certain element when user scrolls into its section
const scaleContainer = () => {
const container = document.querySelector('#social-posts').parentElement;
const element = container.parentElement;
const windowHeight = (window.innerHeight || document.documentElement.clientHeight);
container.style.width = window.getComputedStyle(container).width;
container.parentElement.style.margin = '0 auto';
window.addEventListener('scroll', () => {
if (window.innerWidth < 767) {
element.style.width = '100%';
return;
}
const bounding = element.getBoundingClientRect();
const fromScreenBottom = bounding.top - windowHeight;
let width = 0;
if (fromScreenBottom < 0) {
width = (-(Math.floor(fromScreenBottom)) / 5);
if (width > 100 || width < 0) {
return;
}
}
element.style.width = width + '%';
});
}
ready(scaleContainer);
window.addEventListener('resize', scaleContainer);
and the other one checks how far users scrolls and then prepare keyframes for animation function and then animate.
Adding whole class that have all options set will be a pain to read so I will explain briefly what every part that is not defined in this part do.
this.currentIndex is the index of element that is currently visible
this.prevIndex is the index of previously visible element
this.options.keyframes is an array of keyframes that function chooses from to perform animation.
eg:
keyFrames: {
0: {top: '5%',left: '90%',transform: 'rotate(-38deg)'},
5: {top: '16%',left: '86%',transform: 'rotate(-36deg)'},
10: {top: '27%',left: '82%',transform: 'rotate(-33deg)'},
15: {top: '36%',left: '78%',transform: 'rotate(-30deg)'},
//...
}
this.options.accordionsCount is count of element that needs to be taken into account when choosing how many keyframes needs to be used
this.options.objectContainer is parent element of whole section.
class TruckAccordions {
//...
animateTruck = () => {
if(this.currentIndex === this.prevIndex || window.innerWidth <= 992) {
return;
}
const previousPercent = Math.floor((100 / this.options.accordionsCount) * (this.prevIndex + 1));
const percent = Math.floor((100 / this.options.accordionsCount) * (this.currentIndex + 1));
const objectKeyFrames = Object.entries(this.options.keyFrames);
let keyFrames = [];
if (previousPercent < percent) {
objectKeyFrames.forEach(keyFrame => {
if ((keyFrame[0] <= percent && keyFrame[0] >= (previousPercent - 5))) {
keyFrames.push(keyFrame[1]);
}
});
} else {
objectKeyFrames.reverse().forEach(keyFrame => {
if ((keyFrame[0] >= percent && keyFrame[0] <= (previousPercent + 5))) {
keyFrames.push(keyFrame[1]);
}
});
}
const truck = this.options.objectContainer.querySelector('.truck');
truck.animate(
keyFrames,
{
duration: 1000,
fill: 'forwards',
easing: 'ease-in-out'
}
);
this.prevIndex = this.currentIndex;
}
}
(() => new TruckAccordions())();

Keeping iframe/image ratio when resizing on height

I managed to keep the iframe's ratio for when the user resizes the window on width, but I have trouble adding the logic for when the user resizes the window on height due to conflicting logic, since the resize on width already alters the height of the iframe.
This is the function that gets called when resizing:
function calculateAspectRatioFit(width, height, ratio) {
if(height) {
let width = ((length)/(Math.sqrt((1)/(Math.pow(ratio, 2)+1))));
return Math.round(width);
} else if(width) {
let height = ((width)/(Math.sqrt((Math.pow(ratio, 2)+1))));
return Math.round(height);
}
}
But I believe that the problem lies in the trigger:
const resizeHandler = (e) => {
console.log("inside ", parseInt(iframeHeight), iframeElement.offsetHeight);
if(parseInt(iframeWidth) > iframeElement.offsetWidth) {
// overwrite inline styling
iframeElement.style.cssText = 'height: ' + calculateAspectRatioFit(iframeElement.offsetWidth, null, iframeRatio) + 'px!important';
} else if (parseInt(iframeHeight) > window.innerHeight) {
iframeElement.style.cssText = 'width: ' + calculateAspectRatioFit(null, iframeElement.offsetHeight, iframeRatio) + 'px!important';
}
}
Got any solutions for this? (pen below)
https://codepen.io/Dragosb/pen/WNoeXRa?editors=0011
Solved, as per the codepen (link is the same as the one in the original post):
Added a container for the iframe (if you are using a modal, that can be the container):
const resizeHandler = (e) => {
// get container measures
let computedContainerStyling = getComputedStyle(iframeContainer);
let containerWidth = parseInt(computedContainerStyling.width);
let containerHeight = parseInt(computedContainerStyling.height);
if ( (containerWidth / iframeRatio) > containerHeight){
iframeHeight = containerHeight;
iframeWidth = containerHeight * iframeRatio;
} else {
iframeWidth = containerWidth;
iframeHeight = containerWidth / iframeRatio;
}
iframeElement.style.width = Math.floor(iframeWidth) + 'px';
iframeElement.style.height = Math.floor(iframeHeight) + 'px';
}
window.addEventListener('resize', resizeHandler, false);
https://codepen.io/Dragosb/pen/WNoeXRa?editors=0011

Rerun javascript function when screen orientation changes

I'm using a code that scale images to fit the parent div, it's called "aspectcorrect".
The problem happens on the mobile version: my parent div has 100% width, and when the user changes the orientation of the screen to landscape, the image doesn't resize to fit the new div's width.
There is a way to rerun the onload event (which scales the image), when the user changes the orientation of the screen?
Here is my website: www.mcsoftware.com.br/sitemc
I'm still working on it.
(To understand what I'm saying, open it on your cellphone, and when you change the screen orientation just click on "Continuar mesmo assim" to navigate)
Thanks!
aspectcorrect.js
function ScaleImage(srcwidth, srcheight, targetwidth, targetheight, fLetterBox) {
var result = { width: 0, height: 0, fScaleToTargetWidth: true };
if ((srcwidth <= 0) || (srcheight <= 0) || (targetwidth <= 0) || (targetheight <= 0)) {
return result;
}
// scale to the target width
var scaleX1 = targetwidth;
var scaleY1 = (srcheight * targetwidth) / srcwidth;
// scale to the target height
var scaleX2 = (srcwidth * targetheight) / srcheight;
var scaleY2 = targetheight;
// now figure out which one we should use
var fScaleOnWidth = (scaleX2 > targetwidth);
if (fScaleOnWidth) {
fScaleOnWidth = fLetterBox;
}
else {
fScaleOnWidth = !fLetterBox;
}
if (fScaleOnWidth) {
result.width = Math.floor(scaleX1);
result.height = Math.floor(scaleY1);
result.fScaleToTargetWidth = true;
}
else {
result.width = Math.floor(scaleX2);
result.height = Math.floor(scaleY2);
result.fScaleToTargetWidth = false;
}
result.targetleft = Math.floor((targetwidth - result.width) / 2);
result.targettop = Math.floor((targetheight - result.height) / 2);
return result;
}
onimageload.js
function OnImageLoad(evt) {
var img = evt.currentTarget;
// what's the size of this image and it's parent
var w = $(img).width();
var h = $(img).height();
var tw = $(img).parent().width();
var th = $(img).parent().height();
// compute the new size and offsets
var result = ScaleImage(w, h, tw, th, false);
// adjust the image coordinates and size
img.width = result.width;
img.height = result.height;
$(img).css("left", result.targetleft);
$(img).css("top", result.targettop);
}
Where onload function goes
<img onload="OnImageLoad(event);" />
https://jsfiddle.net/ffxeqq21/
You can try some javascript library like jQuery mobile and use the orientationchange event This way you could just do
$( window ).on( "orientationchange", function( event ) {
//Some code
});

Categories