Why does sometimes some of cards doesn't rotate at all? - javascript

example: http://codepen.io/anon/pen/mEoONW
Cards at least heave minimum 180 degree rotation, set in CSS with JS, but in multiple run some of it doesn't rotate at all. Can anyone please explain why?
<div class="flip-container">
<div class="flipper">
<div class="front"></div>
<div class="back">?</div>
</div>
</div>
...
<button onclick="rotate();">Rotate</button>
<style>
.flip-container {
perspective: 1000px;float:left;
}
.flip-container, .front, .back {
width: 160px;height: 220px;
}
.flipper {
transform-style:preserve-3d;position: relative;
}
.front, .back {
backface-visibility: hidden;position: absolute; top: 0; left: 0;
}
.front {
z-index: 2; transform: rotateY(0deg);background-color: blue;
}
.back {
transform: rotateY(180deg); background-color: grey;font-size: 13em; text-align: center; vertical-align: middle;
}
</style>
<script>
function rnd(){
var randNum = Math.floor((Math.random() * 20) + 1);
if(randNum %2 == 0){//generated number is even
randNum = randNum +1 ;
}
return randNum;
}
function rotate(){
$('.flipper').each(function(i, obj) {
var rn = rnd();
var nn = 180 * rn;
var sp = 0.2 * rn;
console.log(rn);
$(this).css("transition", sp+"s").css("transform", "rotateY("+nn+"deg)");
});
}
</script>

Easy.
To start rotating in this pen, card has to receive new css.
If the number, that was generated by rnd() function is the same as previous one, css of the element is not changed, so browser doesnt start the animation, it thinks that's it already been played (and it was).
To 'restart animation' if it has SAME params you have two ways - or remove element from DOM and get it back there (ugly, ah?) OR you can clear style and then set it back in time out. That trick will help 'restart' animation.
$element.attr('style', null); //remove old style before setting new
setTimeout(function(){
$element.css("transition", "0.6s");
$element.css("transform", "rotateY("180deg)");
}, 100);
I've forked you pen and made all cards spin here.

You could create an extra checker to prevent the same card from recieing the exact number as before:
function rotate() {
$('.flipper').each(function(i, obj) {
var rn = rnd();
if ( $(this).data('rn') == rn ) { rn = rn + 2; }
var nn = 180 * rn;
var sp = 0.2 * rn;
$(this).data('rn', rn);
$(this).css("transition", sp + "s");
$(this).css("transform", "rotateY(" + nn + "deg)");
console.log(i + ': ' + rn + ' -d: ' + $(this).data('rn'));
});
}
Working Demo:
function rnd() {
var randNum = Math.floor((Math.random() * 20) + 1);
if (randNum % 2 == 0) { randNum = randNum + 1; }
return randNum;
}
function rotate() {
$('.flipper').each(function(i, obj) {
var rn = rnd();
if ( $(this).data('rn') == rn ) { rn = rn + 2; }
var nn = 180 * rn;
var sp = 0.2 * rn;
$(this).data('rn', rn);
$(this).css("transition", sp + "s");
$(this).css("transform", "rotateY(" + nn + "deg)");
//console.log(i + ': ' + rn + ' -d: ' + $(this).data('rn'));
});
}
rotate();
$('body').on('click', '#rotate', function(){rotate();});
.cards::after { clear:both; content: ''; display: table;}
/* entire container, keeps perspective */
.flip-container {
perspective: 1000px;
float: left;
margin: 2px;
}
.flip-container,.front,.back {
width: 160px;
height: 220px;
}
/* flip speed goes here */
.flipper {
transition: 0.6s;
transform-style: preserve-3d;
position: relative;
}
/* hide back of pane during swap */
.front, .back {
backface-visibility: hidden;
position: absolute;
top: 0;
left: 0;
}
/* front pane, placed above back */
.front {
z-index: 2;
/* for firefox 31 */
transform: rotateY(0deg);
background-color: blue;
}
/* back, initially hidden pane */
.back {
transform: rotateY(180deg);
background-color: grey;
font-size: 13em;
text-align: center;
vertical-align: middle;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="cards">
<div class="flip-container">
<div class="flipper">
<div class="front">
<!-- front content -->
</div>
<div class="back">
?
</div>
</div>
</div>
<div class="flip-container">
<div class="flipper">
<div class="front">
<!-- front content -->
</div>
<div class="back">
?
</div>
</div>
</div>
<div class="flip-container">
<div class="flipper">
<div class="front">
<!-- front content -->
</div>
<div class="back">
?
</div>
</div>
</div>
<div class="flip-container">
<div class="flipper">
<div class="front">
<!-- front content -->
</div>
<div class="back">
?
</div>
</div>
</div>
<div class="flip-container">
<div class="flipper">
<div class="front">
<!-- front content -->
</div>
<div class="back">
?
</div>
</div>
</div>
<div class="flip-container">
<div class="flipper">
<div class="front">
<!-- front content -->
</div>
<div class="back">
?
</div>
</div>
</div>
</div>
<button id="rotate">Rotate</button>
jsFiddle: https://jsfiddle.net/azizn/9v6340fd/

Related

how to show text on the same cell containing an image on the top of it after an onclick event

I have an onclick event on every cell which contains an image.
After clicking on the cell, the image scales up an rotates by some angle specified.
I want the image to fade out and I want the description of the anime which is text to appear on the image. If I click again the same cell the text should fade out and the cell must return back as it was in the first place.
(I will accept it even if it can be done through a button event, but the button should be in the same cell. PLEASE TRY TO SOLVE THIS USING JAVASCRIPT WITHOUT USING ANY LIBRARIES OR FRAMEWORKS IF U CAN.)
<!--BODY OF THE HTML PAGE-->
<body>
<div class="c1" onclick="f(this)">
<img src="https://picsum.photos/200">
</div>
</body>
<!--CSS AND SCRIPT OF THE HTML PAGE-->
<style type="text/css">
.c1
{
background-color: blue;
width: 200px;
height: 200px;
position: absolute;
left:40%;
top: 30%;
transform: rotateZ(-45deg);
}
</style>
<script type="text/javascript">
timesclicked = 0;
function f(obj) {
timesclicked+=1;
if(timesclicked%2!=0)
{
obj.style.transform = 'scale(2) rotateZ(-90deg) ';
obj.style.transition = 'all 1s 0.3s';
}
else
{
obj.style.transform = 'scale(1) rotateZ(-45deg)';
obj.style.transition = 'all 1s 0.3s';
}
}
</script>
let timesclicked = 0;
function f(containerObj, spinningTime) {
timesclicked += 1;
for(let cell of containerObj.getElementsByTagName('div')){
if (timesclicked % 2 != 0) {
cell.style.transform = 'scale(1.2) rotateZ(0deg) ';
cell.style.transition = 'all 1s ' + spinningTime + 's';
setTimeout(() => {
cell.innerHTML = '<div> Data about the image Data about the image Data about the image Data about the image Data about the image Data about the image Data about the image Data about the image Data about the image Data about the image</div>'
}, spinningTime * 1000);
} else {
cell.style.transform = 'scale(1) rotateZ(-315deg)';
cell.style.transition = 'all 1s ' + spinningTime + 's';
setTimeout(() => {
cell.innerHTML = '<img src="https://picsum.photos/200">';
}, spinningTime * 1000);
}
}
}
.c1 {
background-color: blue;
width: 150px;
height: 150px;
margin: 10px;
transform: rotateZ(-45deg);
}
.container {
display: flex;
}
<div class="container" id="container">
<div class="c1" onclick="f(container,0.3)">
<img src="https://picsum.photos/200">
</div>
<div class="c1" onclick="f(container,0.3)">
<img src="https://picsum.photos/200">
</div>
<div class="c1" onclick="f(container,0.3)">
<img src="https://picsum.photos/200">
</div>
</div>
HTML:
<div class="container c1" onclick="f(this)">
<img src="https://picsum.photos/200">
<div style="display:none; color:white;" class="centered">Your info</div>
</div>
CSS:
/* Centered text */
.centered {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
.c1 {
background-color: blue;
width: 200px;
height: 200px;
position: absolute;
left: 40%;
top: 30%;
transform: rotateZ(-45deg);
}
JS:
let timesclicked = 0;
function f(obj) {
timesclicked += 1;
if (timesclicked % 2 != 0) {
obj.style.transform = 'scale(2) rotateZ(-90deg) ';
obj.style.transition = 'all 1s 0.3s';
obj.children[1].style.transform = 'scale(2) rotateZ(-270deg) ';
obj.children[1].style.display = "";
} else {
obj.style.transform = 'scale(1) rotateZ(-45deg)';
obj.style.transition = 'all 1s 0.3s';
obj.children[1].style.display = "none";
}
}

RotateY of a group of divs dynamically

I'm working on this script since 9 days, I found the script online, and from there I tried to add some code.
The point of the script is to rotate the Div dynamically based on the distance they have between each other.
In a way it works, if you resize the page at some point the divs turn their Y axes.
I have mainly 2 problems, the first one is that if I add new divs they just are shown in a new line.
The second problem is that those divs position should change, they need to get closer and they should move to the left side of the div.
I hope somebody can help because I spent already 10 days on this and I can't find a solution.
Thank you so much
function myFunction(distance) {
//add browser check currently it set for safari
// Code for Safari
var degree = 0;
if (distance <= -1 && distance >= -5) {
degree = 15;
} else if (distance < -5 && distance >= -10) {
degree = 25;
} else if (distance < -10 && distance >= -15) {
degree = 30;
} else if (distance < -15 && distance >= -20) {
degree = 35;
} else if (distance < -20) {
degree = 45;
}
document.getElementById("panel").style.WebkitTransform = "rotateY(" + degree + "deg)";
document.getElementById("panel2").style.WebkitTransform = "rotateY(" + degree + "deg)";
document.getElementById("panel3").style.WebkitTransform = "rotateY(" + degree + "deg)";
document.getElementById("panel4").style.WebkitTransform = "rotateY(" + degree + "deg)";
// document.getElementById("panel").style.marginRight= "100px";
document.getElementById("panel2").style.marginRight = "300px";
document.getElementById("panel3").style.marginRight = "30px";
document.getElementById("panel4").style.marginRight = "30px";
// document.getElementById("panel5").style.WebkitTransform = "rotateY(45deg)";
// document.getElementById("panel6").style.WebkitTransform = "rotateY(45deg)";
// Code for IE9
// document.getElementById("asd").style.msTransform = "rotateY(20deg)";
// Standard syntax
// document.getElementById("asd").style.transform = "rotateY(20deg)";
}
function myFunctionb() {
document.getElementById("panel").style.WebkitTransform = "rotateY(0deg)";
document.getElementById("panel2").style.WebkitTransform = "rotateY(0deg)";
document.getElementById("panel3").style.WebkitTransform = "rotateY(0deg)";
document.getElementById("panel4").style.WebkitTransform = "rotateY(0deg)";
// document.getElementById("panel5").style.WebkitTransform = "rotateY(0deg)";
// document.getElementById("panel6").style.WebkitTransform = "rotateY(0deg)";
}
// need to find a better solution
var first = document.getElementById("panel");
var second = document.getElementById("panel2");
var lastpanel = document.getElementById("panel4");
var lastbox = document.getElementById("last");
var container = document.getElementById("wrapper");
var notcongainer = container.offsetLeft;
var distance = container.offsetWidth - (lastpanel.offsetWidth + lastbox.offsetLeft + 4) + notcongainer;
console.log(distance);
var myVar;
var minDistance = 10;
function check() {
myVar = setInterval(testcheck, 100);
}
// First I check that the boxes lenght are as much as the container
// Then I check the distance between 2 boxes
function testcheck() {
if (distance < minDistance) {
myFunction(distance);
} else {
myFunctionb();
}
distance = container.offsetWidth - (lastpanel.offsetWidth + lastbox.offsetLeft + 4) + notcongainer;
/*console.log(distance)*/
}
//ADD NEW DIV
function addDiv() {
var div = document.createElement('div');
div.className = "col-box";
div.id = "newId";
div.innerHTML = '<div class="hover panel"><div id= "panel3" class="front"><div class="box1"><p>New Div</p></div></div></div>';
document.getElementById('wrapper').appendChild(div);
}
body {
background-color: #ecf0f1;
margin: 20px;
font-family: Arial, Tahoma;
font-size: 20px;
color: #666666;
text-align: center;
}
p {
color: #ffffff;
}
.col-box {
width: 22%;
position: relative;
display: inline;
display: inline-block;
margin-bottom: 20px;
z-index: 1;
}
.end {
margin-right: 0 !important;
}
/*-=-=-=-=-=-=-=-=-=-=- */
/* Flip Panel */
/*-=-=-=-=-=-=-=-=-=-=- */
.wrapper {
width: 80%;
height: 200px;
margin: 0 auto;
background-color: #bdd3de;
hoverflow: hidden;
border: 1px;
}
.panel {
margin: 0 auto;
height: 130px;
position: relative;
-webkit-perspective: 600px;
-moz-perspective: 600px;
}
.panel .front {
text-align: center;
}
.panel .front {
height: inherit;
position: absolute;
top: 0;
z-index: 900;
text-align: center;
-webkit-transform: rotateX(0deg) rotateY(0deg);
-moz-transform: rotateX(0deg) rotateY(0deg);
-webkit-transform-style: preserve-3d;
-moz-transform-style: preserve-3d;
-webkit-backface-visibility: hidden;
-moz-backface-visibility: hidden;
-webkit-transition: all .4s ease-in-out;
-moz-transition: all .4s ease-in-out;
-ms-transition: all .4s ease-in-out;
-o-transition: all .4s ease-in-out;
transition: all .4s ease-in-out;
}
.panel.flip .front {
-webkit-transform: rotateY(45deg);
-moz-transform: rotateY(180deg);
}
.col-box:hover {
z-index: 1000;
}
.box1 {
background-color: #14bcc8;
width: 160px;
height: 60px;
margin-left: 5px;
padding: 20px;
border-radius: 10px;
-moz-border-radius: 10px;
-webkit-border-radius: 10px;
}
<body onload="check()">
<div id="wrapper" class="wrapper">
<div id="first" class="col-box">
<div class="hover panel">
<div id="panel" class="front">
<div class="box1">
<p>Div 1</p>
</div>
</div>
</div>
</div>
<div id="second" class="col-box">
<div class="hover panel">
<div id="panel2" class="front">
<div class="box1">
<p>Div 2</p>
</div>
</div>
</div>
</div>
<div id="third" class="col-box">
<div class="hover panel">
<div id="panel3" class="front">
<div class="box1">
<p>Div 3</p>
</div>
</div>
</div>
</div>
<div id="last" class="col-box">
<div class="hover panel">
<div id="panel4" class="front">
<div class="box1">
<p>Last Div</p>
</div>
</div>
</div>
</div>
<button onclick="addDiv()">Add New Div</button>
</div>
9 days... that's too long. Time to step back and break this up into smaller things.
This isn't an 'answer' yet... but I need to post an image for you. Your question wasn't that clear, but it's not an easy thing to explain. In your case, I would show an image.
Now that I can see what you're doing - it doesn't sound like an arbitrary and completely silly task.
You have a list of 'things' or 'cards' or whatever... so, first things first... how do you insert new DOM into the page - and / into that list - and have the list all on one line. A few ways - but most likely you can just use flexbox -
https://jsfiddle.net/sheriffderek/8eLggama -> https://jsfiddle.net/sheriffderek/pztvhn3L (this is an example - but it's pretty naive - and the further you take this, the closer you'll get to building what most frameworks - like Vue could do way better... but good for learning! Start with something small - to just do that.
// will take an object with the list name and the card id
// eventuallly - you'd want the card to have more info sent in...
function addCard(infoObject) {
var targetList = document.getElementById(infoObject.list);
var li = document.createElement('li');
li.classList.add('item');
// ug! why aren't I using jQuery...
var component = document.createElement('aside');
component.classList.add('card');
var title = document.createElement('h2');
var uniqueId = idMaker.create();
var id = document.createTextNode(uniqueId);
title.appendChild(id);
component.appendChild(title)
li.appendChild(component);
targetList.appendChild(li);
// woah... this part is really boring...
// this is why templating engines and JSON are so popular
// you could also add 'remove' button etc... right?
var removeButton = document.createElement('button');
var removeText = document.createTextNode('x');
removeButton.appendChild(removeText);
removeButton.classList.add('remove-card');
component.appendChild(removeButton);
//
removeButton.addEventListener('click', function() {
var parent = document.getElementById(infoObject.list);
idMaker.removed.push(uniqueId);
parent.removeChild(li);
idMaker.read();
});
}
// start out with a few?
addCard({list: 'exampleTarget'});
addCard({list: 'exampleTarget'});
addCard({list: 'exampleTarget'});
// start a UI to add cards
var addCardButton = document.querySelector('[data-trigger="add-card"]');
addCardButton.addEventListener('click', function() {
addCard({list: 'exampleTarget'});
});
...and then you maybe absolute position the card inside of that list item? It's certainly a unique thing to do, and wont be easy. Then, you can check the number of items - of the width of each item - and make a calculation for transform based on that? Good luck!

Javascript - Trying to Add images to slideshow with JS but it doesn't work?

Hey I'm trying to make a function that fills an empty container of a slideshow with images, with each image being contained in it's own div.
My webpage have an undetermined amount of modal images which , when clicked, open a slideshow album of images. I got this working for 1 image then realized that to have it work for an undetermined amount of slideshows of undetermined size I should make a function that fills the slideshow div. I planned to have each modal image to have a data attribute of "1,2,3...etc" and have a bunch an array with multiple objects each named similarly "1,2,3...etc" then I'd use this information to create and append the correct divs and images to the slideshow container. I will post what I want the slideshow container div to look like, my existing code, and a fiddle of what is supposed to happen. I am new to javascript and appreciate the help. I'm not certain what I've done incorrectly here, and If I haven't explained well enough then I will add more.
Edit:
I have noticed that in my modal image, if in the onClick I put fillSlides first, the other two functions won't work (or won't be called), but if I put it at the end it opens an empty slideshow. I don't get why.
https://jsfiddle.net/nhk3o0m1/26/
Current HTML:
<body >
<h2 id="title" style="text-align:center">hellkkko</h2>
<div class="row">
<div class="column">
<img id="modal-1" src="https://www.yosemitehikes.com/images/wallpaper/yosemitehikes.com-bridalveil-winter-1200x800.jpg" style="max-width:100%" data-modal="1" onclick="openModal();currentSlide(1); fillSlides(this);" class="hover-shadow cursor">
</div>
</div>
<div id="myModal" class="modal">
<span class="close cursor" onclick="closeModal()">×</span>
<div class="modal-content">
<a class="prev" onclick="plusSlides(-1)">❮</a>
<a class="next" onclick="plusSlides(1)">❯</a>
</div>
</div>
What I want my .modal-content div to look like after the function runs:
<div class="modal-content">
<div class="mySlides">
<img src="Images/LS_01.jpg" class="img">
</div>
<div class="mySlides">
<img src="Images/LS_02.jpg" class="img">
</div>
<div class="mySlides">
<img src="Images/LS_03.jpg" class="img">
</div>
<div class="mySlides">
<img src="Images/LS_04.jpg" class="img">
</div>
<a class="prev" onclick="plusSlides(-1)">❮</a>
<a class="next" onclick="plusSlides(1)">❯</a>
</div>
Javascript:
function fillSlides(modalID) {
var container = document.getElementsByClassName("modal-content");
var slides = {
"1": ["Images/LS_01.jpg", "Images/LS_02.jpg", "Images/LS_03.jpg", "Images/LS_04.jpg"],
"2": ["Images/LS_05.jpg", "Images/LS_06.jpg", "Images/LS_07.jpg", "Images/LS_08.jpg"],
"3": ["Images/LS_09.jpg", "Images/LS_10.jpg", "Images/LS_11.jpg", "Images/LS_12.jpg"]
};
var modal_num = modalID.getAttribute('data-modal');
for (var i = slides[modal_num].length; i > 0; i--) {
var the_divs = document.createElement('div');
var s_img = document.createElement('img');
the_divs.className = 'mySlides';
s_img.src = slides[modal_num][i];
the_divs.appendChild(s_img);
container.appendChild(the_divs);
}
}
<h2 id="title" style="text-align:center">hellkkko</h2>
<div class="row">
<div class="column">
<img id="modal-1" src="https://www.yosemitehikes.com/images/wallpaper/yosemitehikes.com-bridalveil-winter-1200x800.jpg" style="max-width:100%" data-modal="1" onclick="openModal();currentSlide(1); fillSlides(this);" class="hover-shadow cursor">
</div>
</div>
<div id="myModal" class="modal">
<span class="close cursor" onclick="closeModal()">×</span>
<div class="modal-content">
<a class="prev" onclick="plusSlides(-1)">❮</a>
<a class="next" onclick="plusSlides(1)">❯</a>
</div>
</div>
Added a function that generates slides on the fly. There are no slides in HTML and arrow controls are in #content. You gave no details on how album exists so I made a thumbnail for 2 extra albums. Also, there's a solution to your problem concerning the removal of everything with the arrows being the exception. The CSS is a little wonky but I'm sure you can rectify it easily enough.
Details commented in demo
Demo
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1, user-scalable=no">
<title></title>
<style>
html,
body {
height: 100%;
width: 100%
}
body {
font-family: Verdana, sans-serif;
margin: 0;
}
* {
box-sizing: border-box;
}
.img {
max-width: 100%;
max-height: 100%;
width: auto;
height: auto;
object-fit: contain;
}
.row {
display:flex;
justify-content:space-between;
}
.column {
width: 25%;
padding: 0 8px;
}
/* The Modal (background) */
.modal {
display: none;
position: fixed;
z-index: 1;
padding-top: 100px;
left: 0;
top: 0;
width: 100%;
height: 100%;
overflow-x: hidden;
overflow-y: scroll;
background: rgba(0, 0, 0, 0.9);
}
/* Modal Content */
.modal-content {
position: relative;
background-color: rgba(0, 0, 0, 0.9);
margin: auto;
padding: 0;
width: 100%;
max-width: 1200px;
}
/* The Close Button */
.close {
color: white;
position: absolute;
top: 10px;
right: 25px;
font-size: 35px;
font-weight: bold;
}
.close:hover,
.close:focus {
color: #999;
text-decoration: none;
cursor: pointer;
}
/* Next & previous buttons */
.prev,
.next {
cursor: pointer;
position: absolute;
top: 50%;
width: auto;
padding: 16px;
margin-top: -50px;
color: white;
font-weight: bold;
font-size: 20px;
transition: 0.6s ease;
border-radius: 0 3px 3px 0;
user-select: none;
-webkit-user-select: none;
}
/* Position the "next button" to the right */
.next {
right: 0;
border-radius: 3px 0 0 3px;
}
/* On hover, add a black background color with a little bit see-through */
.prev:hover,
.next:hover {
background-color: rgba(0, 0, 0, 0.8);
text-decoration: none;
}
/* Number text (1/3 etc) */
.nth {
color: #f2f2f2;
font-size: 12px;
padding: 8px 12px;
position: absolute;
right: 0;
}
img {
margin-bottom: -4px;
cursor: pointer
}
img.hover-shadow {
transition: all .2s ease-in-out;
}
.hover-shadow:hover {
transform: scale(1.1);
}
.modal-content {
-webkit-animation-name: zoom;
-webkit-animation-duration: 0.6s;
animation-name: zoom;
animation-duration: 0.6s;
}
#-webkit-keyframes zoom {
from {
-webkit-transform: scale(0)
}
to {
-webkit-transform: scale(1)
}
}
#keyframes zoom {
from {
transform: scale(0)
}
to {
transform: scale(1)
}
}
.slide img {
display: block;
height: 100%;
margin: 0 auto;
margin-bottom: 50px;
}
.slide {
text-align: center;
height: 80vh;
display: none;
}
.cap {
font-size: 1.5em;
background: rgba(0, 0, 0, .4);
position: absolute;
z-index: 2;
left: 0;
top: 0;
right: 0;
text-align: center;
color: #fff
}
.act {
display: block
}
</style>
</head>
<body>
<header>
<div class="row">
<div class="column"> <img src="https://www.yosemitehikes.com/images/wallpaper/yosemitehikes.com-bridalveil-winter-1200x800.jpg"
style="max-width:100%" onclick="album(img0, cap0);openModal();"
class="hover-shadow"> </div>
<div class="column"> <img src="https://www.yosemitehikes.com/images/wallpaper/yosemitehikes.com-bridalveil-winter-1200x800.jpg"
style="max-width:100%" onclick="album(img1, cap1);openModal();"
class="hover-shadow"> </div>
<div class="column"> <img src="https://www.yosemitehikes.com/images/wallpaper/yosemitehikes.com-bridalveil-winter-1200x800.jpg"
style="max-width:100%" onclick="album(img2, cap2);openModal();"
class="hover-shadow"> </div>
</div>
</header>
<section id="box">
<div id="xModal" class="modal"> <span class="close cursor" onclick="closeModal()">×</span>
<div class="modal-content" id='content'> <a class="prev" onclick="plusSlides(-1)">❮</a> <a class="next"
onclick="plusSlides(1)">❯</a> </div>
</div>
</section>
<footer> </footer>
<script>
/* 3 arrays are required:
|= 1. An array of strings.
|| Each represents a src of an image
|= 2. An array of strings. Each represents the
|| text of a figcaption
|= 3. An empty array
|| For each additional album add #1 and #2, #3
|| is emptied and reused at the beginning of
|| a new cycle.
*/
// Album 0
var img0 = [
"http://www.catholicevangelism.org/wp-content/uploads/2013/06/1200x800.gif",
"http://chasingseals.com/wp-content/uploads/2014/02/greenlandBanner2000x800.jpg",
"http://www.a1carpet-to.com/wp-content/uploads/2015/08/600x400.png",
"https://support.kickofflabs.com/wp-content/uploads/2016/06/800x1200.png"
];
var cap0 = ['caption1', 'caption2', 'caption3', 'caption4'];
// Album 1
var img1 = [
'https://d3i6fh83elv35t.cloudfront.net/newshour/app/uploads/2016/05/729665main_A-BlackHoleArt-pia16695_full-1024x576.jpg',
'http://cdn.newsapi.com.au/image/v1/85fb305132eb20ebbb01af386983c8a1',
'http://science.nationalgeographic.com/staticfiles/NGS/Shared/StaticFiles/Science/Images/Content/neptune-pia01492-ga.jpg',
'https://cdn.spacetelescope.org/archives/images/wallpaper1/heic1509a.jpg',
'https://i.giphy.com/media/JCUyexH8Zaf8k/giphy.webp'
];
var cap1 = ['Title I', 'Title II', 'Title III', 'Title IV',
'Title V'
];
// Album 2
var img2 = [
'https://i.ytimg.com/vi/YeQnLnRvZ9Y/maxresdefault.jpg',
'https://www.thesun.co.uk/wp-content/uploads/2017/08/nintchdbpict000319076839.jpg?strip=all&w=960',
'https://i0.wp.com/www.sketchysloth.com/wp-content/uploads/2016/07/Legendary-Hanging-Garden-Of-Babylon.jpg?fit=710%2C495&ssl=1',
'https://i.ytimg.com/vi/YoRvJcgSDE4/maxresdefault.jpg',
'https://www.realmofhistory.com/wp-content/uploads/2017/01/mausoleum-at-halicarnassus-restored_1.jpg',
'http://www.ancient-origins.net/sites/default/files/field/image/statue-of-Zeus-Olympia.jpg',
'https://i.ytimg.com/vi/F2yYkbinGnc/maxresdefault.jpg'
];
var cap2 = ['Colossus of Rhodes', 'Great Pyramid of Giza',
'Hanging Gardens of Babylon', 'Lighthouse of Alexandria',
'Mausoleum at Halicarnassus', 'Statue of Zeus at Olympia',
'Temple of Artemis at Ephesus'
];
// Declare a empty array
var data = [];
// Declare some counters outside of loop (or inside of loop using let)
var i, b, x;
// Reference the node that will contain the slides
var con = document.getElementById('content');
/* On each iteration...
|= Empty the data array
|= Create an object...
|| add a value from img[] to the src property
|| add a value from cap[] to the cap property
|| add the current value of index +1 to pos property
|| push the object into data array
*/
// Get the total length of data array
// Call genSlides()
function album(img, cap) {
data.length = 0;
for (i = 0; i < img.length; i++) {
var ele = new Object;
ele.src = img[i];
ele.cap = cap[i];
ele.pos = i + 1;
data.push(ele);
}
var qty = data.length;
genSlides(qty)
}
console.log(data);
/* Pass qty through...
|= On each iteration...
|= Create a documentFragment
|| it will allow us to append new elements to
|| it while still not in the DOM
|| which is faster because tasks within the DOM
|| are slow for the browser in comparison.
|= Notice that the data array is being used
|| to assign unique values.
*/
function genSlides(qty) {
for (b = 0; b < qty; b++) {
var frag = document.createDocumentFragment();
var slide = document.createElement('figure');
slide.id = 's' + b;
slide.className = 'slide';
var cap = document.createElement('figcaption');
cap.className = 'cap';
cap.textContent = data[b].cap;
var img = document.createElement('img');
img.classsName = 'img';
img.src = data[b].src;
var nth = document.createElement('b');
nth.className = 'nth';
nth.textContent = data[b].pos + '/' + data.length;
slide.appendChild(cap);
cap.appendChild(nth);
slide.appendChild(img);
frag.appendChild(slide);
con.appendChild(frag);
}
return false;
}
/* To avoid redundancy call sub functions within an initiating function
|| currentSlide() should start at 0, remember that all indexes by
|| default start at 0 and that the last index is .length - 1
|| showSlides() has ben corrected.
*/
function openModal() {
document.getElementById('xModal').style.display = "block";
showSlides(slideIndex);
currentSlide(0);
}
/* To remove what's in #content with the exception of the arrows we
|| gather all .slides in a NodeList and use a loop to remove them.
*/
function closeModal() {
document.getElementById('xModal').style.display = "none";
var slides = document.querySelectorAll(".slide");
for (x = 0; x < slides.length; x++) {
con.removeChild(slides[x]);
}
}
var slideIndex = 0;
function plusSlides(n) {
showSlides(slideIndex += n);
}
function currentSlide(n) {
showSlides(slideIndex = n);
}
function showSlides(n) {
var i;
var slides = document.querySelectorAll(".slide");
if (n > slides.length - 1) {
slideIndex = 0
}
if (n < 0) {
slideIndex = slides.length - 1
}
// Flipping a class is much cleaner than relying on style
for (i = 0; i < slides.length; i++) {
slides[i].classList.remove('act');
}
slides[slideIndex].classList.add('act');
}
</script>
</body>
</html>

Parallax based on mousemove has different offset

How can I have the same parallax offset in all the sections? Right now the offset increases as you add more sections. Note that in section .two and .three the parallax is different from section .one. I want section .two and .three to have the same parallax as in section .one. I am unsure what's causing the divs to go wider in section .two and .three.
Why is this happening and how can I fix it?
JSFiddle
Thank you in advance.
JS
var currentX = '';
var currentY = '';
var movementConstant = .05;
$(document).mousemove(function(e) {
var xToCenter = e.pageX - window.innerWidth/2;
var yToCenter = e.pageY - window.innerHeight/2;
$('.parallax div').each( function(i) {
var $el = $(this);
var newX = (i + 1) * (xToCenter * movementConstant);
var newY = (i + 1) * (yToCenter * movementConstant);
$el.css({left: newX + 'px', top: newY + 'px'});
});
});
HTML
<section class="one">
<div class="parallax">
<div class="asset asset-layer4">4</div>
<div class="asset asset-layer3">3</div>
<div class="asset asset-layer2">2</div>
<div class="asset asset-layer1">1</div>
</div>
</section>
<section class="two">
<div class="parallax">
<div class="asset asset-layer4">4</div>
<div class="asset asset-layer3">3</div>
<div class="asset asset-layer2">2</div>
<div class="asset asset-layer1">1</div>
</div>
</section>
<section class="three">
<div class="parallax">
<div class="asset asset-layer4">4</div>
<div class="asset asset-layer3">3</div>
<div class="asset asset-layer2">2</div>
<div class="asset asset-layer1">1</div>
</div>
</section>
CSS
.one,
.two,
.three {
position: relative;
width: 100%;
height: 200px;
}
.one { background-color: pink; }
.two { background-color: lightgray; }
.three { background-color: orange; }
.parallax {
position: absolute;
left: 50%;
top: 50%;
bottom: 50%;
right: 50%;
overflow: visible;
}
.asset {
position: absolute;
}
.asset-layer1 {
background-color: yellow;
}
.asset-layer2 {
background-color: green;
}
.asset-layer3 {
background-color: blue;
}
.asset-layer4 {
background-color: red;
}
body {
overflow:hidden;
}
the issue is that you are doing an each over ALL over the children div of .parallax. This means you are looping about 11 times. Each time you multiply by a larger i value, so it starts to look off.
Instead, what I have done is within each Parallax container, you will loop through it's children, giving you a value from 0-3. Now they are in sync!
https://jsfiddle.net/p4hrbdge/2/
$('.parallax').each( function(i) {
$(this).find('div').each(function(i) {
var $el = $(this);
var newX = (i + 1) * (xToCenter * movementConstant);
var newY = (i + 1) * (yToCenter * movementConstant);
$el.css({left: newX + 'px', top: newY + 'px'});
})
});

CSS Transform Math - Calculate height of div caused by skew

I'm having difficulty figuring out how I could calculate the extra height of a div container caused by skewing it. I am masking an image inside the container and resizing it using a plugin.
The containers will not always have the same height and width so using fixed dimensions will not work.
Please see my demo.
http://jsfiddle.net/RyU9W/6/
HTML
<div id="profiles" class="container">
<div class="profile">
<div class="image">
<img src="http://placekitten.com/g/750/750" alt="">
</div>
<div class="detail">
</div>
</div>
<div class="profile">
<div class="image">
<img src="http://placekitten.com/g/750/750" alt="">
</div>
<div class="detail">
</div>
</div>
<div class="profile">
<div class="image">
<img src="http://placekitten.com/g/750/750" alt="">
</div>
<div class="detail">
</div>
</div>
<div class="profile">
<div class="image">
<img src="http://placekitten.com/g/750/750" alt="">
</div>
<div class="detail">
</div>
</div>
<div class="profile">
<div class="image">
<img src="http://placekitten.com/g/750/750" alt="">
</div>
<div class="detail">
</div>
</div>
<div class="profile">
<div class="image">
<img src="http://placekitten.com/g/750/1200" alt="">
</div>
<div class="detail">
</div>
</div>
</div>
CSS
#profiles {
margin-top: 300px;
transform:skewY(-30deg);
-ms-transform:skewY(-30deg); /* IE 9 */
-webkit-transform:skewY(-30deg); /* Safari and Chrome */
}
.profile {
cursor: pointer;
float: left;
width: 32.25%;
margin: 0.5%;
position: relative;
}
.profile .image {
position: relative;
overflow: hidden;
height: 400px;
background: #000;
backface-visibility:hidden;
-webkit-backface-visibility:hidden; /* Chrome and Safari */
-moz-backface-visibility:hidden; /* Firefox */
-ms-backface-visibility:hidden; /* Internet Explorer */
}
.profile .image * {
position: relative;
transform:skew(0deg,30deg);
-ms-transform:skew(0deg,30deg); /* IE 9 */
-webkit-transform:skew(0deg,30deg); /* Safari and Chrome */
}
In skew we have a case of Right-angled triangle and the skew new width is equal to "Opposite" and we've the angle and the opposite so by this equation we can get the adjacent Opposite = Adjacent * tan(angle); Where opposite in case of skewX is the div height and in case of skewY will be the div width
Check this https://codepen.io/minaalfy/pen/exgvjb
function calculateSkew(){
var el = document.getElementById('bluebox');
var skewX = document.getElementById('skewX');
skewX.value = skewX.value || 0;
var skewY = document.getElementById('skewY');
skewY.value = skewY.value || 0;
var yRadians = skewY.value * Math.PI / 180;
var newHeight = el.offsetWidth * Math.tan(yRadians);
var calculatedHeight = el.offsetHeight + newHeight;
var xRadians = skewX.value * Math.PI / 180;
var newWidth = calculatedHeight * Math.tan(xRadians);
var calculatedWidth = el.offsetWidth + newWidth;
el.style.transform = ("skewX(" + skewX.value + "deg ) skewY(" + skewY.value + "deg )");
var output = document.getElementById('output');
output.innerHTML = "skewY by "+skewY.value+ " and new height calculated is "+calculatedHeight+ "<br> skewX by "+skewX.value+ " and the new calculated width is "+ calculatedWidth;
}
body {text-align:center}
#bluebox {width:100px;height:100px;background:blue;margin: 20px auto;}
<h4>Enter any numeric value for skewX or skewY to calculate the new width&height for the box</h4>
<div id="bluebox"></div>
<input type="number" placeholder="skewX" id="skewX" onkeyup="calculateSkew()" />
<input type="number" placeholder="skewY" id="skewY" onkeyup="calculateSkew()" />
<h1 id="output"></h1>
I got it using this solution.
var degrees = 30;
var radians= degrees*Math.PI/180;
var newHeight = parentWidth*Math.tan(radians);
var newOffset = newHeight / 2;
var parentHeight = parentHeight + newHeight;
Here is my updated fiddle with option to select degrees
http://jsfiddle.net/bhPcn/5/
Two functions that could help you.
function matrixToArray(matrix) {
return matrix.substr(7, matrix.length - 8).split(', ');
}
function getAdjustedHeight(skewedObj){
var jqElement = $(skewedObj);
var origWidth= jqElement.width();
var origHeight= jqElement.height();
var matrix = matrixToArray(jqElement.css('transform'))
var alpha = matrix[2];
var adjusted = Math.sin(alpha)*origWidth/Math.sin(Math.PI/2-alpha);
return origHeight+Math.abs(adjusted);
}
function getAdjustedWidth(skewedObj){
var jqElement = $(skewedObj);
var origWidth= jqElement.width();
var origHeight= jqElement.height();
var matrix = matrixToArray(jqElement.css('transform'))
var alpha = matrix[1];
var adjusted = Math.sin(alpha)*origHeight/Math.sin(Math.PI/2-alpha);
return origWidth+Math.abs(adjusted);
}
Usage (http://jsfiddle.net/x5her/18/):
// if you use scewY
console.log(getAdjustedWidth($(".image")[0]))
// if you use scewX
console.log(getAdjustedHeight($(".image")[0]))
Example of dynamic skew angle depending on the height.
In angular:
// We use a mathematical expression to define the degree required in skew method
// The angle depend on the height and width of the container
// We turn the answer from atan which is in radian into degrees
//
// DEGREES = RADIAN * 180 / PI
const degrees = Math.atan(
parent.nativeElement.clientWidth / parent.nativeElement.clientHeight
) * 180 / Math.PI;
parent.nativeElement.children[0].style.transform = `skew(${degrees}deg)`;
parent.nativeElement.children[1].style.transform = `skew(${degrees}deg)`;
In Jquery for the snippet :
$(document).ready(() => {
const parent = $('.duo:first');
const degrees = Math.atan(parent.width() / parent.height()) * 180 / Math.PI;
$('.first').css('transform', `skew(${degrees}deg)`);
$('.second').css('transform', `skew(${degrees}deg)`);
});
.container {
width: 10em;
height: 10em;
display: flex;
flex-direction: row;
flex-wrap: nowrap;
}
.one-square {
height: 100%;
width: 0;
flex-grow: 1;
display: flex;
}
.duo {
height: 100%;
width: 0;
flex-grow: 1;
display: flex;
flex-direction: row;
position: relative;
overflow: hidden;
}
.first {
width: 100%;
height: 100%;
background-color: red;
transform: skew(0deg);
transform-origin: 0 0;
position: absolute;
}
.second {
width: 100%;
height: 100%;
background-color: yellow;
transform: skew(0deg);
transform-origin: 100% 100%;
position: absolute;
}
.a {
background-color: grey;
}
.b {
background-color: green;
}
.c {
background-color: lightgrey;
}
.d {
background-color: #444444;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="container">
<div class="one-square a"></div>
<div class="one-square b"></div>
<div class="duo">
<div class="first">
</div>
<div class="second">
</div>
</div>
<div class="one-square c"></div>
<div class="one-square d"></div>
</div>
Now that it's 2021, just use el.getBoundingClientRect().height. It takes css transform into its calculations.

Categories

Resources