Skip to content

Instantly share code, notes, and snippets.

@davidhellmann
Created September 17, 2018 11:30
Show Gist options
  • Save davidhellmann/3cb50ca1e394cfa340be8ac8a47c0fd5 to your computer and use it in GitHub Desktop.
Save davidhellmann/3cb50ca1e394cfa340be8ac8a47c0fd5 to your computer and use it in GitHub Desktop.
<template>
<div :class="`${cn}`">
<div :class="`${cn}__slider`" ref="sliderWrapper" @mousemove="setCursor">
<Navigation :class="`${cn}__navigation`">
asd
</Navigation>
<div :class="`${cn}__sliderSlide`"
ref="sliderSlide"
:style="`transform: translateX(${getLastXPosition}px);`">
<!-- Slider Content -->
<slot/>
</div>
<RoomWrapperFrontDeskContent v-if="currentRoom === 'frontDesk'"/>
<RoomWrapperLoungeContent v-if="currentRoom === 'lounge'"/>
<RoomWrapperMeetingHRContent v-if="currentRoom === 'meetingHR'"/>
<RoomWrapperDevOfficeContent v-if="currentRoom === 'devOffice'"/>
<RoomWrapperRocketRoofContent v-if="currentRoom === 'rocketRoof'"/>
<Link :text="siteContent.global.skipButton.text"
:link="siteContent.global.skipButton.link"
:modifiers="['primary', 'skip']"/>
<router-link to="/" :class="`${cn}__home ${cn}__home--primary ${cn}__home--home`">
<span :class="`${cn}__home__text`">
</span>
</router-link>
</div>
</div>
</template>
<script>
// @ is an alias to /src
import Navigation from '@/components/organisms/Navigation'; // eslint-disable-line
import RoomWrapperFrontDeskContent from '@/components/organisms/RoomWrapperFrontDeskContent.vue';
import RoomWrapperLoungeContent from '@/components/organisms/RoomWrapperLoungeContent.vue';
import RoomWrapperDevOfficeContent from '@/components/organisms/RoomWrapperDevOfficeContent.vue';
import RoomWrapperMeetingHRContent from '@/components/organisms/RoomWrapperMeetingHRContent.vue';
import RoomWrapperRocketRoofContent from '@/components/organisms/RoomWrapperRocketRoofContent.vue';
import Link from '@/components/atoms/Link.vue';
import {mapState, mapMutations} from 'vuex';
import throttle from 'lodash/throttle';
import {TimelineMax} from 'gsap';
export default {
name: 'RoomSlider',
props: [],
data() {
return {
cn: 'o-roomslider',
w: null,
d: null,
e: null,
g: null,
slide: null,
sliderWrapper: null,
sliderWrapperWidth: null,
resizeTimer: null,
$dude: null,
$room: null,
clickArea: 0,
clickAreaPX: 0,
offset: null,
nextDirection: 'no',
mousePosition: 0,
ww: 0,
nextDudeDirection: 'right',
walkingTime: 0,
lastRoom: null,
};
},
computed: {
...mapState([
'currentRoom',
'slideWidth',
'windowWidth',
'xPosition',
'dudeWidthPX',
'dudePosition',
'dudePositionPX',
'roomWrapperWidth',
'clientPositionX',
'navOpen',
'currentEvent',
'layerIsOpen',
'siteContent',
]),
getLastXPosition() {
return this.xPosition;
}
},
methods: {
...mapMutations([
'setSlideWidth',
'setWindowWidth',
'setXPosition',
'setDudeWidthPX',
'setDudePosition',
'setDudePositionPX',
'setRoomWrapperWidth',
'setClientPositionX',
'setNavOpen',
'setCurrentEvent'
]),
/*
|--------------------------------------------------------------------------
| setCursor
|--------------------------------------------------------------------------
*/
setCursor: throttle(function (evt) {
if (this.layerIsOpen) {
return;
}
this.mousePosition = Math.round((evt.clientX * 100) / this.windowWidth);
const targets = evt.path || (evt.composedPath && evt.composedPath());
const event = targets.find((e) => {
const id = e.id;
if (id && id.startsWith('evt')) {
return id;
}
return false;
});
document.body.classList.remove('is-funnyCursor--right');
document.body.classList.remove('is-funnyCursor--left');
document.body.classList.remove('is-funnyCursor--hand');
if (this.mousePosition <= this.clickArea) {
document.body.classList.remove('is-funnyCursor--right');
if (this.xPosition < 0) {
document.body.classList.add('is-funnyCursor--left');
}
} else if (this.mousePosition >= (100 - this.clickArea)) {
document.body.classList.remove('is-funnyCursor--left');
if ((Math.abs(this.xPosition) + this.windowWidth) < this.slideWidth) {
document.body.classList.add('is-funnyCursor--right');
}
} else {
document.body.classList.remove('is-funnyCursor--right');
document.body.classList.remove('is-funnyCursor--left');
}
if (event) {
document.body.classList.add('is-funnyCursor--hand');
if (
document.body.classList.contains('is-funnyCursor--left')
|| document.body.classList.contains('is-funnyCursor--right')
) {
document.body.classList.remove('is-funnyCursor--hand');
}
}
}, 250),
/*
|--------------------------------------------------------------------------
| setSlideWidth
|--------------------------------------------------------------------------
*/
setSlideWidth() {
this.$store.commit('setSlideWidth', Math.round(this.slide.clientWidth));
},
/*
|--------------------------------------------------------------------------
| setWindowWidth
|--------------------------------------------------------------------------
*/
setWindowWidth() {
const setWindowWidth = Math.round(this.w.innerWidth) || Math.round(this.e.clientWidth);
this.$store.commit('setWindowWidth', setWindowWidth);
const roomWrapperWidth = Math.round(this.sliderWrapper.getBoundingClientRect().width);
this.$store.commit('setRoomWrapperWidth', roomWrapperWidth);
// this.offset = Math.round(this.windowWidth * 0.04);
this.offset = 0;
},
/*
|--------------------------------------------------------------------------
| setSliderWidth
|--------------------------------------------------------------------------
*/
setSliderWidth() {
if (this.roomWrapperWidth >= this.slideWidth) {
this.sliderWrapper.style.width = `${this.slideWidth}px`;
} else {
this.sliderWrapper.style.width = '100%';
}
},
/*
|--------------------------------------------------------------------------
| setClickArea
|--------------------------------------------------------------------------
*/
setClickArea() {
this.clickArea = 24;
if (this.windowWidth >= 1000) {
this.clickArea = 12;
}
this.clickAreaPX = (this.roomWrapperWidth * this.clickArea) / 100;
},
/*
|--------------------------------------------------------------------------
| getDomElements
|--------------------------------------------------------------------------
*/
getDomElements() {
this.slide = this.$refs.sliderSlide;
this.sliderWrapper = this.$refs.sliderWrapper;
this.w = window;
this.d = document;
this.e = this.d.documentElement;
[this.g] = this.d.getElementsByTagName('body');
this.$dude = document.querySelector('.o-roomWrapper__dude');
},
/*
|--------------------------------------------------------------------------
| setVariables
|--------------------------------------------------------------------------
*/
setVariables() {
this.setWindowWidth();
this.setSlideWidth();
this.setClickArea();
this.setSliderWidth();
this.getDudeWidth();
document.body.setAttribute('data-currentRoom', this.currentRoom);
document.body.removeAttribute('data-action');
},
/*
|--------------------------------------------------------------------------
| setNextSlideDirection
|--------------------------------------------------------------------------
*/
setNextSlideDirection() {
const leftArea = Math.round(Math.abs(this.xPosition) + this.clickAreaPX);
const rightArea = Math.round((Math.abs(this.xPosition) + this.roomWrapperWidth) - this.clickAreaPX);
if (this.clientPositionX <= leftArea && this.xPosition < 0) {
this.nextDirection = 'left';
} else if (this.clientPositionX >= rightArea && (Math.abs(this.xPosition) + this.windowWidth) < this.slideWidth) {
this.nextDirection = 'right';
} else {
this.nextDirection = 'no';
}
},
/*
|--------------------------------------------------------------------------
| moveSlid
|--------------------------------------------------------------------------
*/
moveSlide(direction, value, skip) {
let xPosition = this.xPosition;
if (!skip) {
if (direction === 'left') {
if (this.xPosition >= 0) {
return;
}
xPosition = this.xPosition + (this.roomWrapperWidth / 4);
if (Math.abs(this.xPosition) < this.roomWrapperWidth / 4) {
xPosition = 0;
}
}
if (direction === 'right') {
if (Math.abs(this.xPosition) >= this.sliderWrapper) {
return;
}
if (this.slideWidth - (Math.abs(this.xPosition) + (this.roomWrapperWidth / 4)) <= this.roomWrapperWidth) {
xPosition = -(this.slideWidth - this.roomWrapperWidth);
} else {
xPosition = this.xPosition - (this.roomWrapperWidth / 4);
}
}
}
this.slide.style.transitionDuration = '1s';
if (value) {
this.slide.style.transitionDuration = '0s';
xPosition = value;
}
this.slide.style.transform = `translateX(${xPosition}px)`;
this.$store.commit('setXPosition', xPosition);
},
/*
|--------------------------------------------------------------------------
| resetSlider
|--------------------------------------------------------------------------
*/
resetSlider() {
// this.moveDude(50, true);
this.$store.commit('setXPosition', 0);
this.slide.style.transitionDuration = '0s';
this.slide.style.transform = `translateX(${this.xPosition}px)`;
this.slide.style.transitionDuration = '1s';
},
/*
|--------------------------------------------------------------------------
| getDudeWidth
|--------------------------------------------------------------------------
*/
getDudeWidth() {
this.$store.commit('setDudeWidthPX', Math.round(this.$dude.getBoundingClientRect().width));
},
getVisibleRoomRange() {
const fromValue = Math.round(((Math.abs(this.xPosition) * 100) / this.slideWidth));
const toValue = Math.round((((Math.abs(this.xPosition) + this.roomWrapperWidth) * 100) / this.slideWidth));
return {
"from": fromValue,
"to": toValue
};
},
/*
|--------------------------------------------------------------------------
| HandleTimeline
|--------------------------------------------------------------------------
*/
handleWalking(tl, dude) {
tl.to(dude, 0, {x: "0%"});
},
/*
|--------------------------------------------------------------------------
| HandleTimeline
|--------------------------------------------------------------------------
*/
getWalkingTiming(tempPosition) {
let timing = 4;
let walkingPercent = Math.abs(tempPosition - this.dudePosition);
timing = timing * walkingPercent / 100;
if (timing < 1) {
timing = 1;
}
this.walkingTime = Math.round(timing);
return this.walkingTime
},
/*
|--------------------------------------------------------------------------
| moveDude
|--------------------------------------------------------------------------
*/
moveDude(value, skip) {
const tl = new TimelineMax();
const dudeWrapper = document.querySelector('.o-roomWrapper__dude');
const dude = dudeWrapper.querySelector('svg');
this.handleWalking(tl, dude);
if (!skip) {
this.setNextSlideDirection();
}
let {dudePositionPX} = this;
if (this.nextDirection !== 'no') {
this.moveSlide(this.nextDirection);
}
dudePositionPX = this.clientPositionX - (this.dudeWidthPX / 2);
if (this.roomWrapperWidth + Math.abs(this.xPosition) === this.slideWidth) {
this.nextDirection = 'no';
}
if (this.clientPositionX <= this.dudeWidthPX) {
dudePositionPX = 50;
}
if (
this.clientPositionX >= Math.abs(this.xPosition) + this.roomWrapperWidth - (this.dudeWidthPX / 2)) {
if (Math.abs(this.xPosition) > 0) {
dudePositionPX = this.slideWidth - this.dudeWidthPX - 50;
}
}
this.$dude.style.transitionDuration = `${this.getWalkingTiming(Math.round(dudePositionPX * 100 / this.slideWidth))}s`;
this.$dude.style.transitionDelay = '0s';
// TODO: Better Walking Animation
if (
this.nextDirection === 'left'
&& this.clientPositionX > Math.round(this.clickArea * this.roomWrapperWidth / 100)
) {
dudePositionPX = (Math.abs(this.xPosition) + this.roomWrapperWidth) - (this.dudeWidthPX * 1.5);
const dudePositionTemp = Math.round(dudePositionPX * 100 / this.slideWidth);
this.$dude.style.transitionDelay = '0s';
if (dudePositionTemp >= this.getVisibleRoomRange().from && dudePositionTemp <= this.getVisibleRoomRange().to) {
dudePositionPX = this.clientPositionX - (this.dudeWidthPX / 2);
}
if (dudePositionPX <= 50) {
dudePositionPX = 50;
}
}
if (this.nextDirection === 'right') {
dudePositionPX = Math.abs(this.xPosition) + (this.dudeWidthPX / 2);
const dudePositionTemp = Math.round(dudePositionPX * 100 / this.slideWidth);
this.$dude.style.transitionDelay = '0s';
if (dudePositionTemp >= this.getVisibleRoomRange().from && dudePositionTemp <= this.getVisibleRoomRange().to) {
dudePositionPX = this.clientPositionX - (this.dudeWidthPX / 2);
}
}
if (value && skip) {
this.$dude.style.transitionDuration = '0s';
dudePositionPX = value;
}
let oldDudePositionPX = this.dudePositionPX;
this.nextDudeDirection = 'right';
if (dudePositionPX < oldDudePositionPX) {
this.nextDudeDirection = 'left';
}
this.$store.commit('setDudePositionPX', dudePositionPX);
if (this.lastRoom === this.currentRoom) {
console.log('foo');
let scaleX = 1;
if (this.nextDudeDirection === 'left') {
scaleX = -1
}
let repeating = 0;
let timing = this.walkingTime;
if (this.walkingTime > 0.5 && this.walkingTime <= 1) {
repeating = 1;
timing = this.walkingTime / 2;
} else if (this.walkingTime > 1 && this.walkingTime <= 1.5) {
repeating = 2;
timing = this.walkingTime / 3;
} else if (this.walkingTime > 1.5 && this.walkingTime <= 2) {
repeating = 3;
timing = this.walkingTime / 4;
} else if (this.walkingTime > 2 && this.walkingTime <= 3) {
repeating = 4;
timing = this.walkingTime / 5;
} else if (this.walkingTime > 3) {
repeating = 5;
timing = this.walkingTime / 6;
}
tl
.to(dude, 0, {x: "0", scaleX: scaleX,})
.to(dude, timing, {
x: "-81.818181818%", scaleX: scaleX, ease: SteppedEase.config(9), repeat: repeating
})
.to(dude, 0, {
x: "0", scaleX: scaleX, onComplete: this.handleWalking(tl, dude)
});
}
this.lastRoom = this.currentRoom;
this.$store.commit('setDudePosition', Math.round(dudePositionPX * 100 / this.slideWidth));
},
/*
|--------------------------------------------------------------------------
| firstTimeInRoom
|--------------------------------------------------------------------------
*/
firstTimeInRoom() {
this.moveDude(this.dudePositionPX, true);
let position = this.dudePositionPX;
if (this.roomWrapperWidth + position > this.slideWidth) {
position = Math.round(this.slideWidth - this.roomWrapperWidth);
}
this.moveSlide('left', -position, true);
},
/*
|--------------------------------------------------------------------------
| hideSlider
|--------------------------------------------------------------------------
*/
hideSlider() {
this.slide.style.transitionDuration = '0s';
this.slide.style.opacity = 0;
},
/*
|--------------------------------------------------------------------------
| showSlider
|--------------------------------------------------------------------------
*/
showSlider() {
this.slide.style.transitionDuration = '1s';
this.slide.style.opacity = 1;
},
/*
|--------------------------------------------------------------------------
| triggerResize
|--------------------------------------------------------------------------
*/
triggerResize() {
window.addEventListener('resize', () => {
if (this.ww !== (Math.round(this.w.innerWidth) || Math.round(this.e.clientWidth))) {
clearTimeout(this.resizeTimer);
this.hideSlider();
this.resizeTimer = setTimeout(() => {
setTimeout(() => {
this.setVariables();
}, 250);
setTimeout(() => {
this.resetSlider();
}, 500);
setTimeout(() => {
this.showSlider();
}, 750);
}, 1000);
}
});
},
},
watch: {
currentRoom(newValue, oldValue) {
if (oldValue !== newValue) {
this.lastRoom = oldValue;
this.resetSlider();
this.firstTimeInRoom();
}
},
},
mounted() {
// Get Elements
this.getDomElements();
// Set WW For Resize Event to handle Mobile Safari
this.ww = Math.round(this.w.innerWidth) || Math.round(this.e.clientWidth);
// Set Variables
this.setVariables();
// Resizing
this.triggerResize();
// GetRoom
this.$room = document.querySelector('.o-roomWrapper');
if (!this.$room) {
return;
}
this.$room.addEventListener('click', (evt) => {
document.body.classList.remove('is-open--navigation');
this.$store.commit('setNavOpen', false);
this.$store.commit('setClientPositionX', evt.clientX + Math.abs(this.xPosition));
const targets = evt.path || (evt.composedPath && evt.composedPath());
const event = targets.find((e) => {
const id = e.id;
if (id && id.startsWith('evt')) {
console.log(id);
return id;
}
return false;
});
this.setNextSlideDirection();
if (event) {
if (this.nextDirection === 'no') {
this.$store.commit('setCurrentEvent', event.id);
} else {
this.moveDude();
}
} else {
this.$store.commit('setCurrentEvent', false);
this.moveDude();
}
});
},
created() {
},
components: {
Navigation,
RoomWrapperFrontDeskContent,
RoomWrapperLoungeContent,
RoomWrapperMeetingHRContent,
RoomWrapperDevOfficeContent,
RoomWrapperRocketRoofContent,
Link,
},
};
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped lang="scss">
.o-roomslider {
$root: &;
width: 100%;
height: 100vh;
// padding: 0 4vw;
position: relative;
background-color: c('black');
[data-currentroom='house'] & {
height: calc(100vh - 76px);
@include media('>=1160px') {
height: calc(100vh - 120px);
}
}
[data-currentroom='frontDesk'] & {
background-color: c('room', 'front');
}
[data-currentroom='lounge'] & {
background-color: c('room', 'lounge');
}
[data-currentroom='meetingHR'] & {
background-color: c('room', 'meetingHR');
}
[data-currentroom='devOffice'] & {
background-color: c('room', 'dev');
}
[data-currentroom='rocketRoof'] & {
background-color: c('room', 'rocket');
}
&__slider {
width: 100%;
height: 100%;
overflow: hidden;
position: absolute;
left: 50%;
top: 50%;
// max-width: 92vw;
transform: translate(-50%, -50%);
// border: 1vh solid #454646;
&:hover {
cursor: url(~@/assets/images/svg/global/pointer.svg) 22 22, auto;
// cursor: pointer;
.is-funnyCursor--left & {
cursor: url(~@/assets/images/svg/global/arrowLeft.svg) 22 22, auto;
// cursor: w-resize;
}
.is-funnyCursor--hand & {
cursor: url(~@/assets/images/svg/global/hand.svg) 22 22, auto;
// cursor: w-resize;
}
.is-funnyCursor--right & {
cursor: url(~@/assets/images/svg/global/arrowRight.svg) 22 22, auto;
// cursor: e-resize;
}
}
&::before,
&::after {
content: '';
position: absolute;
z-index: 100000;
top: 0;
bottom: 0;
background-color: transparent;
opacity: 0.25;
// width: calc((100vw * 0.92) * 0.24);
width: calc(100vw * 0.24);
pointer-events: none;
@include media('>=l') {
// width: calc((100vw * 0.92) * 0.12);
width: calc(100vw * 0.12);
}
}
&::before {
left: 0;
}
&::after {
right: 0;
}
}
&__sliderSlide {
height: 100vh;
width: 400vh;
transform: translateX(0);
transition-property: all;
transition-duration: 1s;
transition-timing-function: linear;
position: absolute;
left: 0;
bottom: 0;
z-index: 100;
.is-open--navigation & {
opacity: 0.2;
}
/*@media screen and (orientation: landscape) {
width: calc(100% * 4);
height: 100%;
}*/
}
&__sliderControls {
position: absolute;
left: 0;
right: 0;
top: 0;
z-index: 1000;
height: 50px;
display: none;
}
&__sliderButton {
font-size: 13px;
font-weight: 700;
width: 50%;
line-height: 54px;
height: 50px;
cursor: pointer;
position: absolute;
background-color: c('red');
color: c('white');
transition: all 0.5s ease('out-cubic');
&--prev {
display: none;
left: 0;
}
&--next {
right: 0;
}
&:hover {
background-color: mix(c('black'), c('red'), 20%);
}
}
@mixin a-link() {
margin-left: s(1);
margin-right: s(1);
line-height: 2;
@include f(13px, 17px, padding-top);
@include f(11px, 15px, padding-bottom);
@include f(24px, 32px, padding-left padding-right);
@include ms-respond(font-size, 0);
border-radius: 3px;
white-space: nowrap;
}
&__home {
$root: &;
@include make-vr();
display: inline-flex;
flex-direction: row;
align-items: center;
justify-content: center;
position: relative;
-webkit-appearance: none; // stylelint-disable-line
transition: all 0.25s ease('out-cubic');
&--primary {
@include a-link();
background-color: mix(black, c('room', 'rocket'), 20%);
border: 1px solid c('white');
color: c('white');
[data-currentroom='lounge'] & {
background-color: mix(black, c('room', 'lounge'), 20%);
}
[data-currentroom='meetingHR'] & {
background-color: mix(black, c('room', 'meetingHR'), 20%);
}
[data-currentroom='devOffice'] & {
background-color: mix(black, c('room', 'dev'), 20%);
}
[data-currentroom='rocketRoof'] & {
background-color: mix(black, c('room', 'rocket'), 20%);
}
}
&:hover {
color: c('white');
background-color: mix(black, c('room', 'rocket'), 40%);
cursor: url(~@/assets/images/svg/global/hand.svg) 22 22, auto;
[data-currentroom='lounge'] & {
background-color: mix(black, c('room', 'lounge'), 40%);
}
[data-currentroom='meetingHR'] & {
background-color: mix(black, c('room', 'meetingHR'), 40%);
}
[data-currentroom='devOffice'] & {
background-color: mix(black, c('room', 'dev'), 40%);
}
[data-currentroom='rocketRoof'] & {
background-color: mix(black, c('room', 'rocket'), 40%);
}
}
&--home {
position: absolute;
z-index: 1000000;
left: s(1);
bottom: s(2);
border: 2px solid rgba(c('white'), 0.9);
font-size: ms(-1);
font-weight: 700;
border-radius: 3px;
@include f(9px, 13px, padding-top);
@include f(7px, 11px, padding-bottom);
@include f(12px, 16px, padding-left padding-right);
box-shadow: 0 10px 50px rgba(c('black'), 0.2);
&:hover {
transform: translate(0, 2px);
box-shadow: 0 2px 5px rgba(c('black'), 0.2);
}
}
&:focus {
outline: none;
}
&__text {
display: inline-block;
line-height: 1;
order: 1;
}
}
}
</style>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment