Aspect Ratio for div and its elements - javascript

I'm building an HTML5 game without canvas and want to keep a 16:9 ratio for my div. That is easily done by javascript and it works perfectly well. But the elements inside the div itself, they sometime become too big (if the screen is big). I'm aware of max/min-height/width, but is there any other way to make it as if the game is scaled?
here is the code for js and css:
function fix() {
var gameWidth = $(window).width();
var gameHeight = $(window).height();
var fitX = gameWidth / 800;
var fitY = gameHeight / 480;
var screenRatio = gameWidth / gameHeight;
var optimalRatio = Math.min(fitX, fitY);
// checking ratio
if( screenRatio >= 1.77 && screenRatio <= 1.79)
{
$('#game').width ($(window).Width + 'px');
$('#game').height ($(window).Height + 'px');
}
else
{
$('#game').width (800 * optimalRatio + 'px');
$('#game').height (480 * optimalRatio + 'px');
}
$('#game').center();
}
the function is doing its job perfectly well.
but the CSS here is what I'm having issues with.
#game {
width: 800px;
height: 480px;
background: url(bg.png);
position: relative;
}
.landing {
position: absolute;
width: 20%;
max-width: 190px;
height: 60%;
max-height: 290px;
bottom: 10%;
background: #ff6600;
text-align: center;
}
I want it so that the landing scales while keeping the 190/290 ratio..
thanks.

Not percents will be the way but 'em' units.
Set the font-size of the outer div to 10px then 1.0em equals 10 Pixels. If you use 'em' for every element inside you just change font-size of outer div and everything else get's scaled.
CAVE: Nested 'em' font-sizes will multiply so only use these on the 'leaf' elements, that have no children. At least no children which use 'em' units themselves
What will be the advantage? You don't have to fiddle around with the scale of the outer element with jQuery.
If you want to depend on the available space you should act on window resizes with jquery and only change the outer wrap font-size in that case and all will be well
http://jsfiddle.net/HerrSerker/a8yc7/
HTML
<button class="five">50%</button>
<button class="ten">100%</button>
<button class="fifteen">150%</button>
<button class="twenty">200%</button>
<div class="wrap">
<div class="container">
<div class="elem elem1"></div>
<div class="elem elem2"></div>
<div class="elem elem3"></div>
<div class="elem elem4"></div>
</div>
</div>
CSS
.wrap {
font-size: 10px;
}
.container {
width: 30em;
height: 20em;
border: 1px solid gold;
position: relative;
overflow: hidden;
}
.elem {
position: absolute;
width: 10em;
height: 10em;
}
.elem1 {
background: silver;
top: 8em;
left: -5em;
}
.elem2 {
background: green;
top: -2em;
left: 12em;
}
.elem3 {
background: gray;
top: -3em;
left: 13em;
}
.elem4 {
background: red;
top: 5em;
left: 2em;
}
jQuery
$('.five').on('click', function() {
$('.wrap').css({
fontSize: '5px'
})
})
$('.ten').on('click', function() {
$('.wrap').css({
fontSize: '10px'
})
})
$('.fifteen').on('click', function() {
$('.wrap').css({
fontSize: '15px'
})
})
$('.twenty').on('click', function() {
$('.wrap').css({
fontSize: '20px'
})
})

Related

On horizontal scroll of overflown div, fill in progress bar

I have a div which contains an image. The container of this image has overflow:scroll, so that the user can scroll left or right to see the rest of the image.
I've also implemented a progress bar, which should indicate how much of the image remains to scroll. I.e. if the user has scrolled 5% to the right, it'll fill up 5% of the progress bar (and vice versa).
I can get the function working based on scrollHeight, but can't get it working based on scrollWidth.
Where am I going wrong?
window.onscroll = function() {myFunction()};
function myFunction() {
var winScroll = document.body.scrollTop || document.documentElement.scrollTop;
var width = document.documentElement.scrollLeft - document.documentElement.clientWidth;
var scrolled = (winScroll / width) * 100;
document.getElementById("myBar").style.width = scrolled + "%";
}
.imgCont {
background: black;
overflow: scroll;
position: relative;
}
.imgCont img {
width: auto;
max-width: none;
}
.progress-container {
width: 100%;
height: 8px;
background: blue;
}
.progress-bar {
height: 8px;
background: red;
width: 0%;
}
<div class="imgCont">
<img src="https://i.imgur.com/KhWo66L.png">
</div>
<div class="progress-container">
<div class="progress-bar" id="myBar"></div>
</div>
You need to add listeners on the .imgCont element and use it's scrollLeft, scrollWidth and clientWidth properties
let scrEl = document.getElementById("scr-el")
scrEl.addEventListener('scroll', event => {
let scrolled = (scrEl.scrollLeft / (scrEl.scrollWidth - scrEl.clientWidth) ) * 100
document.getElementById("myBar").style.width = scrolled + "%"
});
.imgCont {
background: black;
overflow-x: scroll;
position: relative;
}
.imgCont img {
width: auto;
max-width: none;
}
.progress-container {
width: 100%;
height: 8px;
background: blue;
}
.progress-bar {
height: 8px;
background: red;
width: 0%;
}
<div id="scr-el" class="imgCont">
<img src="https://i.imgur.com/KhWo66L.png">
</div>
<div class="progress-container">
<div class="progress-bar" id="myBar"></div>
</div>
windows.onscroll won't emit any events while you scroll horizontally because scroll is happening in the element with class imgCont.
put an id imgCont
<div class="imgCont" id="imgCont">
<img src="https://i.imgur.com/KhWo66L.png">
</div>
and call the on scroll event as
document.getElementById("imgCont").onscroll
Jquery solution setps:
subtract the visible width of the image and the real image width
var winScroll = $(".imgCont img").width() - $(".imgCont").width();
get the left scroll position
var width = $(".imgCont").scrollLeft();
get the percentage from the width and position
var scrolled = ((width / winScroll) * 100);
Check the snippet:
$(function(){
$(".imgCont").scroll(function(){
var winScroll = $(".imgCont img").width() - $(".imgCont").width();
var width = $(".imgCont").scrollLeft();
var scrolled = ((width / winScroll) * 100);
$("#myBar").width(scrolled + "%");
});
});
.imgCont {
background: black;
overflow: scroll;
position: relative;
height:200px;
}
.imgCont img {
width: auto;
max-width: none;
}
.progress-container {
width: 100%;
height: 8px;
background: blue;
}
.progress-bar {
height: 8px;
background: red;
width: 0%;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="imgCont">
<img src="https://static.toiimg.com/photo/msid-67868104/67868104.jpg?1368689">
</div>
<div class="progress-container">
<div class="progress-bar" id="myBar"></div>
</div>
Another solution.
let div = document.getElementById("theDiv")
div.addEventListener('scroll', function(e) {
let inner = window.innerWidth
let left = div.scrollLeft
let sWidth = div.scrollWidth
let total = sWidth - inner
let width = 1 * left / total * 100
if (width >= 100) {
return document.getElementById("myBar").style.width = "100%";
}
document.getElementById("myBar").style.width = `${width}%`;
});
body {
margin: 0;
}
.imgCont {
background: black;
overflow: auto;
position: relative;
}
.imgCont img {
width: auto;
max-width: none;
}
.progress-container {
width: 100%;
height: 8px;
background: blue;
}
.progress-bar {
height: 8px;
background: red;
width: 0%;
}
<div class="imgCont" id="theDiv">
<img src="https://i.imgur.com/KhWo66L.png">
</div>
<div class="progress-container">
<div class="progress-bar" id="myBar"></div>
</div>

Preserve position of elements in respect of background image while resize

Hey I have container with background-image and I added the "pins" to the container and set the position. But the problem is with resize of the window. While the resizing the position of the pins doesnt preserve (especially vertically). How can I set the position to stay always on the same place in respect of background image ?
DEMO:
JSFiddle
CSS:
.building {
height: 100%;
width: 100%;
position: relative;
background: transparent url('http://svgshare.com/i/403.svg') no-repeat left center/contain;
&__item {
position: absolute;
z-index: 50;
&--1 {
bottom: 11%;
left: 24%;
}
&--2 {
bottom: 18%;
left: 10%;
}
&--3 {
bottom: 10%;
left: 38%;
}
&--4 {
bottom: 20%;
left: 43%;
}
&--5 {
bottom: 48%;
left: 84%;
}
&--6 {
bottom: 38%;
left: 30%;
}
&--7 {
bottom: 70%;
left: 84%;
}
&--8 {
bottom: 23%;
left: 86%;
}
&--9 {
bottom: 60%;
left: 68%;
}
&--10 {
bottom: 8%;
left: 30%;
}
&--11 {
bottom: 35%;
left: 84%;
}
}
If you have the original width and height of the image and an initial position of your marker, you can calculate the new x position of the marker by doing this:
newX = (initialX / originalWidth) * newWidth
Same thing goes for the y position.
Here is a simple example using JS to recalculate the position, whenever the window resizes.
Let's stick the marker to the basketball ;)
var img = new Image()
var wrapper = document.getElementsByClassName('wrapper-inner')[0]
var marker = document.getElementsByClassName('marker')[0]
var initialPos = {x:740, y:555}
var padding = 25
var imgW = 0
var imgH = 0
img.onload = function() {
wrapper.firstElementChild.src = this.src
imgW = this.width
imgH = this.height
resize()
}
img.src = 'https://upload.wikimedia.org/wikipedia/commons/thumb/9/9d/Finish_%28235964190%29.jpg/1024px-Finish_%28235964190%29.jpg'
function resize() {
var imgRect = wrapper.getBoundingClientRect();
marker.style.left = ((initialPos.x/imgW) * imgRect.width) - padding + "px"
marker.style.top = ((initialPos.y/imgH) * imgRect.height) - padding + "px"
}
window.onresize = resize
body {
margin: 0;
}
.wrapper {
text-align: center;
}
.wrapper-inner {
display: inline-block;
font-size: 0;
position: relative;
}
.wrapper-inner img {
width: 100%;
height: auto;
}
.marker {
font-size: 32px;
color: red;
font-weight: bold;
border-radius: 25px;
line-height: 1.5;
width: 50px;
height: 50px;
background: white;
position: absolute;
left: 0;
top: 0;
z-index: +1;
}
<div class="wrapper">
<div class="wrapper-inner">
<img src="" alt="">
<span class="marker">&starf;</span>
</div>
</div>
You won't be able to accomplish this with pure CSS and background-image with sizing method set to contain.
You can however do pure CSS and use <img /> tag to load the svg because Images keep proportions when scaled.
First you'll need to to add the img tag in the .building
Make your markers 0x0px wide and tall and give them negative margin offset by half the width and height.
That way the center of the marker will always be your anchor when your use percentages. (Provided you use top % and left %. In your case you use bottom % so you need to add 15px)
Set display of .building to inline-block -- that way it always "wraps around" the image.
You'll now have a responsive image that you can control the width of trough .building{width:XX%}
Demo
.building {
width: 100%;
position: relative;
img{
width:100%;
}
&__item {
position: absolute;
z-index: 50;
width: 0;
height: 0;
margin-left: -15px; //sub half of width
margin-top: 15px; // add half of height
...
That's as far you'll get using pure CSS. For anything more advanced use jQuery and a Responsive Hotspot Plugin
Good luck!

Parallax Issue in Javascript

I was creating a parallax effect in which the image and the text move in opposite direction to the movement of the mouse. That is happening inside an element called parallax-wrapper. But when I move out of the element I want the image and the text to return back to their original positions. I have tried to detect the mouse position outside the element but for some reason it not firing properly.
The codepen link is - https://codepen.io/rohitgd/pen/gRLNad?editors=1010
HTML
<div class="parallax-wrapper">
<div class="layer" data-mouse-parallax="0.1">
<img src="https://tympanus.net/Development/MorphingBackgroundShapes/img/1.jpg"/>
</div>
<div class="layer" data-mouse-parallax="0.3">REVERT</div>
</div>
CSS
body {
background-color:#fff;
padding: 100px;
display: flex;
justify-content: center;
align-items: center;
}
.parallax-wrapper {
width: 500px;
height: 300px;
background-color:#0c0c0c;
position: relative;
overflow: hidden;
.layer {
width: 80%;
height: 80%;
position: absolute;
left: 30px;
text-align: center;
line-height: 300px;
font-size: 38px;
color:#FFF;
transition: all 200ms ease-out;
}
}
img {
width: 200px;
height: 200px;
position: relative;
top: 50px;
right: 70px;
}
Javascript
$(".parallax-wrapper").mousemove(function(e) {
var x = e.pageX - $(this).offset().left - $(this).width() / 2;
var y = e.pageY - $(this).offset().top - $(this).height() / 2;
$("*[data-mouse-parallax]").each(function() {
var factor = parseFloat($(this).data("mouse-parallax"));
x = -x * factor;
y = -y * factor;
$(this).css({ transform: "translate3d( " + x + "px, " + y + "px, 0 )" });
});
});
$(document).mouseleave(function(e) {
var target = $(e.target);
if( !target.is("div.layer")) {
alert('out of the element');
e.stopPropagation();
}
});
What I want is when the mouse is outside the parallax-wrapper the Image and the text return back to their original positions.
You're not resetting the transformations when your mouse leaves. You need to add this where you have the alert...
$(".parallax-wrapper").mouseleave(function(e) {
$("*[data-mouse-parallax]").each(function() {
$(this).css({ transform: "translate3d( 0, 0, 0 )" });
});
});
Note that the mouseleave event is triggered when the mouse leaves .parallax-wrapper, not document as you previously had it.
Here's a modified codepen...
https://codepen.io/anon/pen/ZyBgYJ
I think a selector was wrong. Here's a correct version or see code below.
To show better when you are inside/outside I change the background color, that's better than an alert. When you leave the wrapper (the black background) it flips correctly now.
Where RED is set you can reset the transform to the origin.
// Trying to replicate the effect here - https://tympanus.net/Development/MorphingBackgroundShapes/
$(".parallax-wrapper").mousemove(function(e) {
var x = e.pageX - $(this).offset().left - $(this).width() / 2;
var y = e.pageY - $(this).offset().top - $(this).height() / 2;
$(".parallax-wrapper").css("background-color", "#00ff00"); // <-- EXIT
// reset transform here
$("*[data-mouse-parallax]").each(function() {
var factor = parseFloat($(this).data("mouse-parallax"));
x = -x * factor;
y = -y * factor;
$(this).css({ transform: "translate3d( " + x + "px, " + y + "px, 0 )" });
});
});
// this is the selector I changed from "document" to ".parallax-wrapper"
$(".parallax-wrapper").mouseleave(function(e) {
var target = $(e.target);
if( !target.is("div.layer")) {
$(".parallax-wrapper").css("background-color", "#ff0000"); // <-- ENTER
e.stopPropagation();
}
});
body {
background-color:#fff;
padding: 100px;
display: flex;
justify-content: center;
align-items: center;
}
.parallax-wrapper {
width: 500px;
height: 300px;
background-color:#0c0c0c;
position: relative;
overflow: hidden;
.layer {
width: 80%;
height: 80%;
position: absolute;
left: 30px;
text-align: center;
line-height: 300px;
font-size: 38px;
color:#FFF;
transition: all 200ms ease-out;
}
}
img {
width: 200px;
height: 200px;
position: relative;
top: 50px;
right: 70px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="parallax-wrapper">
<div class="layer" data-mouse-parallax="0.1">
<img src="https://tympanus.net/Development/MorphingBackgroundShapes/img/1.jpg"/>
</div>
<div class="layer" data-mouse-parallax="0.3">REVERT</div>
</div>
Replace $(document).mouseleave with $(".parallax-wrapper").mouseleave.
$(".parallax-wrapper").mousemove(function(e) {
var x = e.pageX - $(this).offset().left - $(this).width() / 2;
var y = e.pageY - $(this).offset().top - $(this).height() / 2;
$("*[data-mouse-parallax]").each(function() {
var factor = parseFloat($(this).data("mouse-parallax"));
x = -x * factor;
y = -y * factor;
$(this).css({ transform: "translate3d( " + x + "px, " + y + "px, 0 )" });
});
});
$(".parallax-wrapper").mouseleave(function(e) {
alert('out of the element');
});
body {
background-color: #fff;
padding: 100px;
display: flex;
justify-content: center;
align-items: center;
}
.parallax-wrapper {
width: 500px;
height: 300px;
background-color: #0c0c0c;
position: relative;
overflow: hidden;
}
.parallax-wrapper .layer {
width: 80%;
height: 80%;
position: absolute;
left: 30px;
text-align: center;
line-height: 300px;
font-size: 38px;
color: #FFF;
transition: all 200ms ease-out;
}
img {
width: 200px;
height: 200px;
position: relative;
top: 50px;
right: 70px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="parallax-wrapper">
<div class="layer" data-mouse-parallax="0.1">
<img src="https://tympanus.net/Development/MorphingBackgroundShapes/img/1.jpg"/>
</div>
<div class="layer" data-mouse-parallax="0.3">REVERT</div>
</div>

Hide Sticky Div Once Scrolling Past Next Parent Div

I'm trying to hide a "sticky" div once it scrolls past the next parent div. I've currently successfully have it so it appears after scrolling "y > 100" but I'm having a lot of trouble getting the "Sticky Note" to disappear after scrolling past #break.
Example below.
http://codepen.io/anon/pen/BojKBx
$(document).scroll(function() {
var y = $(this).scrollTop();
if (y > 100) {
$('.bottomMenu').fadeIn();
} else {
$('.bottomMenu').fadeOut();
}
});
.bottomMenu {
display: none;
position: fixed;
bottom: 0;
width: 50%;
height: 60px;
border-bottom: 1px solid #000;
z-index: 1;
margin: 0 auto;
left: 50%;
margin-left: -500px;
text-align: center;
}
#header {
font-size: 50px;
text-align: center;
height: 60px;
width: 100%;
background-color: red;
}
#container {
height: 2500px;
}
#break {
text-align: center;
font-size: 30px;
margin-bottom: 300px;
width: 100%;
background-color: yellow;
}
#footer {
height: 60px;
background-color: red;
width: 100%;
bottom: 0;
}
<div id="header">Home</div>
<div class="bottomMenu">
<h2>Sticky Note</h2>
</div>
<div id="container"></div>
<div id="break">Should Not Be Seen After This Point</div>
<div id="footer"></div>
You can get Y position of a div (its vertical offset starting from the top of the page), and then add condition to show sticky note only when you're below the required "Y" coordinate, and above the required div. Example:
http://codepen.io/anon/pen/EVPKyP
Javascript code:
$(document).scroll(function () {
var bodyRect = document.body.getBoundingClientRect(),
elemRect = document.getElementById("break").getBoundingClientRect(),
offset = elemRect.top - bodyRect.top - window.innerHeight;
var y = $(this).scrollTop();
if (y > 100 && y < offset) {
$('.bottomMenu').fadeIn();
} else {
$('.bottomMenu').fadeOut();
}
});
Sources:
Retrieve the position (X,Y) of an HTML element
screen width vs visible portion

Resize Div whilst maintaining ratio

I'm trying to create a page where a centrally placed div resizes to fit in the page both horizontally and vertically whilst retaining the ratio.
Currently I'm using a combination of JS and CSS although I'm not sure it's particularly efficient - it also seems a little hacky.
How would I either clean up this code or rewrite it to achieve this?
Javascript
function changesize(){
var $width = $(".aspectwrapper").height();
var $changewidth = $width * 1.5;
var $doc = $(document).width();
var $height;
if ($doc <= $changewidth){ $changewidth = ( $doc - 100 );
$height = ( ($doc - 100) / 1.5 );
$(".aspectwrapper").css('height', "" + $height + "");
};
$(".content").css('width', "" + $changewidth + "");
$(".aspectwrapper").css('width', "" + $changewidth + "");
};
$(document).ready(function(e) {
$(changesize);
});
$(window).resize(function(e) {
$(changesize);
});
CSS
html, body {
width: 100%;
height: 100%;
padding: 0;
margin: 0;
}
.aspectwrapper {
display: inline-block;
position: relative;
margin: 0 auto;
height: 90%;
border: #F00 1px solid;
background-color: #F00;
}
.content {
position: absolute;
top: 0;
bottom: 0;
right: 0;
margin-top: 60px;
outline: thin dashed green;
overflow: hidden;
background-color: #09C;
}
#wrapper {
width: 100%;
height: 100%;
text-align: center;
background-color: #0F3;
float: left;
}
HTML
<div id="wrapper">
<div class="aspectwrapper">
<div class="content"> CONTENT GOES HERE</div>
</div>
<div style="clear:both;"></div>
</div>
I'd personally position my center div horizontally and vertically using positioning/margin combinations with a specific liquid width and height. It would resize based on page width without the use of javascript. Here's an example.
http://jsfiddle.net/9Aw2Y/

Categories

Resources