How to combine a hidden/functional scrollbar with parallax elements? - javascript

I have a problem with a parallax page.
the scrollbar is hidden (by pushing it to the side with inner&outer divs and "right: -17px;")
got some parallax div elements which should float over the page with different speed
The code for the hidden scrollbar separately works and also the code for the the parallax elements separately does work.
My Problem: I tried to combine these codes but only the hidden scrollbar works. I haven't figured out the problem ... Maybe the js code of the parallax cannot work with the "inner div" hidden scrollbar? The "inner div" have to be a kinda <body>. If I give the body a height of for example 3000px, then the parallax does work, but then I get a 2nd scrollbar.
I'd prefer to solve this without using 3rd party libraries.
var elementOne = document.querySelector("#elementOne");
var elementTwo = document.querySelector("#elementTwo");
var elementThree = document.querySelector("#elementThree");
function setTranslate(xPos, yPos, el)
{
el.style.transform = "translate3d(" + xPos + ", " + yPos + "px, 0)";
}
window.addEventListener("DOMContentLoaded", scrollLoop, false);
var xScrollPosition;
var yScrollPosition;
function scrollLoop()
{
xScrollPosition = window.scrollX;
yScrollPosition = window.scrollY;
setTranslate(0, yScrollPosition * -0.2, elementOne);
setTranslate(0, yScrollPosition * -1.5, elementTwo);
setTranslate(0, yScrollPosition * .5, elementThree);
requestAnimationFrame(scrollLoop);
}
*
{
margin: 0px;
padding: 0px;
font-family: Arial;
}
#outer
{
height: 100%;
width: 100%;
overflow: hidden;
position: absolute;
}
#inner
{
top: 0px;
right: -17px;
bottom: 0px;
left: 0px;
position: absolute;
overflow-x: hidden;
}
#frame_1
{
top: 0px;
height: 100%;
width: 100%;
position: absolute;
background-image: linear-gradient(-225deg, #22E1FF 0%, #1D8FE1 48%, #625EB1 100%);
}
#frame_2
{
top: 100%;
height: 100%;
width: 100%;
position: absolute;
background-image: linear-gradient(-225deg, #D4FFEC 0%, #57F2CC 48%, #4596FB 100%);
}
#frame_3
{
top: 200%;
height: 100%;
width: 100%;
position: absolute;
background-image: linear-gradient(-225deg, #473B7B 0%, #3584A7 51%, #30D2BE 100%);
}
#elementOne
{
width: 400px;
height: 300px;
top: 150%;
left: 50%;
position: fixed;
z-index: 10;
background-image: linear-gradient(-225deg, #22E1FF 0%, #1D8FE1 48%, #625EB1 100%);
opacity: .75;
}
#elementTwo
{
width: 300px;
height: 300px;
top: 350%;
left: 55%;
position: fixed;
z-index: 8;
background-image: linear-gradient(-225deg, #D4FFEC 0%, #57F2CC 48%, #4596FB 100%);
opacity: .75;
}
#elementThree
{
width: 300px;
height: 300px;
top: 50%;
left: 25%;
position: fixed;
z-index: 9;
background-image: linear-gradient(-225deg, #473B7B 0%, #3584A7 51%, #30D2BE 100%);
opacity: .75;
}
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8"/>
</head>
<body>
<div id="outer">
<div id="inner">
<div id="frame_1"></div>
<div id="frame_2"></div>
<div id="frame_3"></div>
<div id="elementOne"></div>
<div id="elementTwo"></div>
<div id="elementThree"></div>
</div>
</div>
</body>
</html>

Related

object rotation resets on new click with javascript

I have created a simple cube in CSS and would like to be able to rotate it around with click and drag to display text on the sides etc, but every time you click and drag, it resets to the original position. How could I store the last rotated angle to be able to ensure it starts where it left off? I appreciate any help. Here is the code:
// Select the Cube
const cube = document.querySelector(".cube");
const body = document.querySelector("body");
// Get the x, y position when click
window.addEventListener("mousedown", function(e) {
const x = e.clientX;
const y = e.clientY;
// rotate
window.addEventListener("mousemove", moveRotate);
function moveRotate(e) {
cube.style.transform = `
rotateX(${-(e.clientY - y) / 2}deg)
rotateY(${(e.clientX - x) / 2}deg)`;
body.style.cursor = "grabbing";
}
window.addEventListener("mouseup", function() {
window.removeEventListener("mousemove", moveRotate);
body.style.cursor = "context-menu";
});
});
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
background: rgb(0, 0, 0);
}
.cube {
position: absolute;
width: 300px;
height: 300px;
transform-style: preserve-3d;
}
.cube div {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
transform-style: preserve-3d;
}
.cube div span {
color: azure;
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: linear-gradient(black, rgb(0, 255, 0));
transform: rotateY(calc(90deg * var(--i))) translateZ(150px);
}
.top {
position: absolute;
top: 0;
left: 0;
width: 300px;
height: 300px;
background: #222;
transform: rotateX(90deg) translateZ(150px);
}
.top div {
color: white;
position: absolute;
top: 45%;
left: 35%
}
.bottom {
position: absolute;
top: 0;
left: 0;
width: 300px;
height: 300px;
background: rgba(0, 255, 0);
transform: rotateX(90deg) translateZ(-150px);
}
<body>
<div class="cube">
<div class="top"></div>
<div class="bottom"></div>
<div class="sides">
<span class=front style="--i:0;">0</span>
<span class=left style="--i:1;">1</span>
<span class=back style="--i:2;">2</span>
<span class=right style="--i:3;">3</span>
</div>
</div>
</body>
You need to store the last calculated rotation value on the mouseUp event. Then add it to the value of the new calculated rotation in the mouseMove listener. The initial value must be set to zero outside both events.
// Select the Cube
const cube = document.querySelector(".cube");
const body = document.querySelector("body");
let last_x = 0,
last_y = 0
// Get the x, y position when click
window.addEventListener("mousedown", function (e)
{
const x = e.clientX;
const y = e.clientY;
let new_x = 0,
new_y = 0;
// rotate
window.addEventListener("mousemove", moveRotate);
function moveRotate(e)
{
new_x = ((e.clientX - x) / 2) + last_x
new_y = (-(e.clientY - y) / 2) + last_y
cube.style.transform =`
rotateX(${new_y}deg)
rotateY(${new_x}deg)`;
body.style.cursor = "grabbing";
}
window.addEventListener("mouseup",function ()
{
last_x = new_x
last_y = new_y
window.removeEventListener("mousemove", moveRotate);
body.style.cursor = "context-menu";
});
});
*{
margin: 0;
padding: 0;
box-sizing: border-box;
}
body
{
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
background: rgb(0, 0, 0);
}
.cube
{
position: absolute;
width: 300px;
height: 300px;
transform-style: preserve-3d;
}
.cube div
{
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
transform-style: preserve-3d;
}
.cube div span
{
color:azure;
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: linear-gradient(black, rgb(0, 255, 0));
transform: rotateY(calc(90deg * var(--i))) translateZ(150px);
}
.top
{
position: absolute;
top:0;
left: 0;
width: 300px;
height: 300px;
background: #222;
transform: rotateX(90deg) translateZ(150px);
}
.top div
{
color: white;
position: absolute;
top: 45%;
left: 35%
}
.bottom
{
position: absolute;
top: 0;
left: 0;
width: 300px;
height: 300px;
background:rgba(0, 255,0);
transform: rotateX(90deg) translateZ(-150px);
}
<div class="cube">
<div class="top"></div>
<div class="bottom"></div>
<div class="sides">
<span class=front style="--i:0;">0</span>
<span class=left style="--i:1;">1</span>
<span class=back style="--i:2;">2</span>
<span class=right style="--i:3;">3</span>
</div>
</div>

Assigning custom scrollbar CSS to div instead of body

I am setting up a custom scrollbar that works across browsers, but my problem is that it is only being applied to the body (which is static), instead of the div scroll area, listed as 'content'. I believe the problem is in the javascript that lies at the end of the HTML, but I cannot unravel it.
The HTML is as follows:
<body>
<div class="banner">
<video autoplay="" muted="false" loop="">
<source src="Media/BackgroundClip.mp4" type="video/mp4">
</video>
<div class="content">
<header> <img src="Media/DOE_TMP.gif"> </header>
<div class="content-wrapper">
<div id="progressbar"></div>
<div id="scrollPath"></div>
<img src="Media/Dialogue4.png">
<div class="text-wrapper">
>>>CONTENT
</div>
</div>
</div>
<script type="text/javascript">
let progress = document.getElementById('progressbar');
let totalHeight = document.body.scrollHeight - window.innerHeight;
window.onscroll = function(){
let progressHeight = (window.pageYOffset / totalHeight) * 100;
progress.style.height = progressHeight + "%";
}
</script>
</body>
And the CSS used looks like:
::-webkit-scrollbar{
width: 0;
}
#scrollpath {
position: fixed;
top: 0;
right: 0;
width: 10px;
height: 100%;
background: rgba(255,255,255,0.05);
}
#progressbar {
position: fixed;
top: 0;
right: 0;
width: 10px;
height: 100%;
background: linear-gradient(to top, #008aff, #00ffe6);
animation: animate 5s linear infinite;
}
#keyframes animate {
0%,100%
{
filter: hue-rotate(0deg);
}
50%
{
filter: hue-rotate(360deg);
}
}
#progressbar:before {
content: '';
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: linear-gradient(to top, #008aff, #00ffe6);
filter: blur(10px);
}
#progressbar:after {
content: '';
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: linear-gradient(to top, #008aff, #00ffe6);
filter: blur(30px);
}
Thanking you in advance,
Betty.
you are using the position : 'fixed' for the progressbar. It should be absolute and the parent (.content) must be none static element (ex: relative). You can check it here: custom scrollbar
::-webkit-scrollbar{
width: 0;
}
#scrollpath {
position: fixed;
top: 0;
right: 0;
width: 10px;
height: 100%;
background: rgba(255,255,255,0.05);
}
#progressbar {
position: absolute;
top: 0;
right: 0;
width: 10px;
height: 100%;
background: linear-gradient(to top, #008aff, #00ffe6);
animation: animate 5s linear infinite;
}
#keyframes animate {
0%,100%
{
filter: hue-rotate(0deg);
}
50%
{
filter: hue-rotate(360deg);
}
}
#progressbar:before {
content: '';
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: linear-gradient(to top, #008aff, #00ffe6);
filter: blur(10px);
}
#progressbar:after {
content: '';
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: linear-gradient(to top, #008aff, #00ffe6);
filter: blur(30px);
}
.content {
position: relative
}

CSS3. VueJS. Dynamic Transitioning Background Gradients

Now I change the gradient based on some logic in the application.
<template>
<div :style="`background-image: ${backgroundImage}`" class="background">
<snackbar />
<nuxt />
<default-footer />
</div>
</template>
<style lang="scss">
.background {
min-height: 100vh;
padding-top: 35px;
padding-bottom: 75px;
text-align: center;
background-image: radial-gradient(circle at 50% 95%, #ffa400, #fd6e6a);
}
</style>
But I need to get the gradient changed gradually from one combination of two colors to another.
What is the best way to do this?
Another way to think about it
<div id="app"></div>
#app {
height: 300px;
width: 300px;
min-height: 50vh;
padding-top: 35px;
padding-bottom: 75px;
text-align: center;
background-image: radial-gradient(circle at 50% 95%, #ffa400ff 0%, #fd6e00ff 33.3333%, black 60%, black 100%);
background-size: 100% 300%;
background-position: 50% 100%;
transition: background-position 1s;
}
#app:hover {
background-position: 50% 0%;
}
Or two layers of background
<div id="app"></div>
#app {
height: 300px;
width: 300px;
min-height: 50vh;
padding-top: 35px;
padding-bottom: 75px;
text-align: center;
background-color: red;
background-image: linear-gradient(180deg, #ffa400ff 0%, #ffa400ff 50%, #ffa40000 100%), radial-gradient(circle at 50% 95%, #ffa400ff, #fd6e00ff);
background-size: 100% 200%, 100% 100%;
background-position: 0 200%, 0 0;
background-repeat: no-repeat;
transition: background-position 1s;
}
#app:hover {
background-position: 0 0, 0 0;
}
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style type="text/css">
html,body,ul,li{
height: 100%;
margin: 0;
padding: 0;
}
.flip-list-enter-active, .flip-list-leave-active {
transition: all 1s;
}
.flip-list-enter, .flip-list-leave-active {
opacity: 0;
}
.demo {
position: relative;
height: 100%;
}
.demo > ul {
position: absolute;
z-index: 0;
height: 100%;
width: 100%;
}
.demo .bg-color-li {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
}
.demo .bg-color-li div {
height: 100%
}
.content {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
text-shadow: 0 0 3px #ffffff;
}
</style>
<script src="https://unpkg.com/vue/dist/vue.js"></script>
</head>
<body>
<div id="app" class="demo">
<transition-group name="flip-list" tag="ul">
<li v-for="curColor in curColors" v-bind:key="curColor" class="bg-color-li">
<div :style="`background-image: ${curColor}`"></div>
</li>
</transition-group>
<div class="content">
content...
</div>
</div>
<script type="text/javascript">
new Vue({
el: '#app',
data: {
curColors: [],
colors: [
'linear-gradient(45deg, blue, black)',
'linear-gradient(45deg, red, orange)',
'linear-gradient(45deg, pink, purple)',
'linear-gradient(45deg, green, brown)'
],
index: 0
},
mounted: function () {
this.curColors = [this.colors[0]];
this.startChange();
},
methods: {
startChange () {
setInterval(() => {
if (this.index < this.colors.length - 1) {
this.index++
} else {
this.index = 0
}
this.curColors.splice(0, 1, this.colors[this.index]);
}, 2000);
}
}
})
</script>
</body>
</html>
I've done that by creating a computer property that returns the style that you need, by creating a string with it. In the template you use that property on the style of the component, and that's it!
<v-card-title primary-title :style="productStyle">
<h3 class="headline text-capitalize word-break-none mb-0">{{title.toLowerCase()}}</h3>
</v-card-title>
computed: {
productStyle () {
return 'background-image:linear-gradient(to top, rgba(0,0,0,1) 0%, rgba(0,0,0,0.75) 40%, rgba(255,255,255,0) 60%)'
}
}
Like that you can build your style with whatever logic you want and return it. Remember that a computer property always is calculated when one of its dependencies gets updated, so you'll get that style updated right away!

Parent div to change dimension when inner image rotate

I have a modal containing one or more images and these images can rotate.
My issue is when image rotate it overflow the parent div. I wish to have the container to change dimension to always fit the image (images).
I created a codepen to have a look.
I tried to change many and many css properties without success...
Jade:
.overlay
.fake-modal
.content
img.img(src='http://lorempixel.com/output/abstract-q-c-300-200-2.jpg')
.wrapper
button.left rotate left
button.right rotate right
Less:
.overlay {
background-color: rgba(0, 0, 0, .7);
position: absolute;
width: 100%;
height: 100%;
z-index: 0;
}
.fake-modal {
background-color: #fff;
padding: 10px;
position: fixed;
top: 50%;
left: 50%;
transform: translateX(-50%) translateY(-50%);
width: auto;
height: auto;
z-index: 1;
.content {
position: relative;
.wrapper {
position: absolute;
top: 10px;
right: 10px;
}
}
}
js:
var angle = 0;
var btnLeft = $('.left');
var btnRight = $('.right');
btnLeft.on('click', function (e) {
e.preventDefault();
angle = angle - 90;
rotate(angle);
});
btnRight.on('click', function (e) {
e.preventDefault();
angle = angle + 90;
rotate(angle);
});
function rotate(rotateDegrees) {
var r = 'rotate(' + rotateDegrees + 'deg)';
var img = $('.img');
img.css({
'-moz-transform': r,
'-webkit-transform': r,
'-o-transform': r,
'-ms-transform': r
});
}
Solved using getBoundingClientRect()
Codepen: http://codepen.io/anon/pen/BNENge
you may set fixed width and height to div contaning image.
http://codepen.io/anon/pen/XbQXJP
`.overlay {
background-color: rgba(0, 0, 0, .7);
position: absolute;
width: 100%;
height: 100%;
z-index: 0;
}
.fake-modal {
background-color: #fff;
padding: 10px;
position: fixed;
top: 50%;
left: 50%;
transform: translateX(-50%) translateY(-50%);
width: auto;
height: auto;
z-index: 1;
.content {
position: relative;
.imgContainer {
position: relative;
width: 300px;
height: 200px;
.img {
position: absolute;
margin-left: -150px;
margin-top: -100px;
top: 50%;
left: 50%;
}
}
.wrapper {
position: absolute;
top: 10px;
right: 10px;
}
}
}`

horizontally repeated picture twitches when using .animate() to move it in y direction

I am coding a loading screen with a div that slowly moves out of the screen. But it is twitching for reasons I do not know.
This is the code I am talking about:
function fadeLoadingScreen() {
$('#loadingBanner').animate({
bottom: "-15%",
opacity: 0
},
2000,
function() {
$('#loadingDiv').hide();
});
}
$(document).ready(function() {
fadeLoadingScreen();
});
#loadingDiv {
position: fixed;
width: 100%;
height: 100%;
background-color: white;
z-index: 10000;
}
#loadingBanner {
background-image: url("http://images.gofreedownload.net/thumps/crown-pattern-banner-erected-europeanstyle-vector-89228.jpg");
background-size: auto 100%;
background-repeat: repeat-x;
position: fixed;
bottom: 0;
height: 15%;
width: 100%;
z-index: 10000;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="loadingDiv">
<div id="loadingBanner"></div>
</div>
https://jsfiddle.net/71btwr2j/
can anyone explain this behavior?

Categories

Resources