%h4 Drag the phone right and left
.phone
.phone_frame
%canvas.grain
.guitar
.phone_inner
.phone_inner__nav
.menu
%h3 Product details
.phone_inner__cube
.face--front
.shadow
%img{:src => 'https://s3-us-west-2.amazonaws.com/s.cdpn.io/217233/gshadow.png'}
-(1..100).each do
%h1 Fender
%h2 Fender American Elite Strat
.face--left
.logo
%img{:src => 'https://s3-us-west-2.amazonaws.com/s.cdpn.io/217233/logoStrings.png'}
%ul.big
%li.active Guitars
%li Basses
%li Amps
%li Pedals
%li Other
%ul.small
%li About
%li Support
%li Terms
%li FAQ
View Compiled
$height: 489px;
$width: 245px;
$perspective: 900;
$globalTransitionmTime: .5s;
$globalTransitionEasing: cubic-bezier(0.615, 0.000, 0.280, 1.005);
@import url('https://fonts.googleapis.com/css?family=Heebo:400,500,800,900&display=swap');
:root {
--bg: #efdece;
}
h4 {
color: white;
margin: 0;
padding-top: 20px;
text-align: center;
}
canvas {
position: absolute;
z-index: 1;
opacity: 0.6;
pointer-events: none;
}
.dynamicCursor {
max-width: 50px;
min-width: 18px;
transition: width 0s;
background: transparent !important;
border: 2px solid white !important;
}
@keyframes in {
from{opacity: 0;}
to{opacity: 1;}
}
body {
padding: 0;
background: #a92913;
padding: 0;
margin: 0;
box-shadow: 50vw 0 #381313 inset;
height: 100vh;
font-family: 'Heebo', sans-serif;
user-select: none; /* Chrome all / Safari all */
user-select: none; /* Firefox all */
user-select: none; /* IE 10+ */
user-select: none; /* Likely future */
%center {
position: absolute;
left: 0;
right: 0;
margin: auto;
top: 50%;
transform: translateY(-50%);
}
.guitar {
width: 85px;
height: 175px;
z-index: 10;
position: absolute;
transition: all 0.7s 0.3s cubic-bezier(0.5, 0.005, 0.075, 0.985), transform 0.1s 0.7s, transform 0.1s;
left: 92px;
transform: scale(1.8);
top: 130px;
background-size: 1920px !important;
background: url(https://s3-us-west-2.amazonaws.com/s.cdpn.io/217233/gt.png);
animation: guitar2 $globalTransitionmTime 0s steps(23, end) forwards;
@keyframes guitar {
0% {background-position: 0 0;transform: scale(1.8)}
10% { transform: scale(1.8);}
100% {background-position: -1840px 0; transform: scale(1.8)}
}
@keyframes guitar2 {
0% {background-position: -1840px 0;transform: scale(1.8)}
10% { transform: scale(1.8);}
100% {background-position: 0 0; transform: scale(1.8)}
}
}
.phone {
@extend %center;
opacity: 0;
animation: in 1s .5s forwards;
width: $width;
height: $height;
perspective: $perspective;
border-radius: 24px;
overflow: hidden;
border-radius: 40px;
box-shadow: 0 0 40px 10px rgba(0, 0, 0, 0.3);
box-reflect: below 4px linear-gradient(to top, rgba(255, 255, 255, 1) -120%, rgba(255,255,255,0) 25%);
&.open {
.guitar {
animation: guitar $globalTransitionmTime 0s steps(23, end) forwards;
}
& .phone_inner__nav {
left: 170px;
h3 {
opacity: 0;
}
}
& .phone_inner__cube {
transform: rotateY(90deg);
left: 50px;
h2 {
opacity: 0;
transform: translateZ(50px);
}
}
}
&_frame {
width: $width;
height: $height;
position: absolute;
z-index: 2;
background: url('https://s3-us-west-2.amazonaws.com/s.cdpn.io/217233/frameIphone.png');
pointer-events: none;
}
&_inner {
width: $width - 20px;
height: $height - 14px;
position: relative;
left: 10px;
top: 6px;
overflow: hidden;
transform-style: preserve-3D;
background: #ada59c;
&__nav {
position: absolute;
z-index: 2;
text-transform: uppercase;
text-align: center;
width: 100%;
font-weight: 400;
transition: all $globalTransitionmTime $globalTransitionEasing;
top: 39px;
left: 0;
h3 {
margin: 0;
font-size: 9px;
opacity: 1;
transition: all $globalTransitionmTime $globalTransitionEasing;
}
& .menu {
width: 18px;
height: 2px;
background: #111114;
position: absolute;
left: 16px;
&:after {
content: '';
display: block;
position: relative;
top: 2px;
width: 18px;
height: 2px;
background: #111114;
}
&:before {
content: '';
display: block;
position: relative;
top: 9px;
width: 10px;
height: 2px;
background: #111114;
}
}
}
&__cube {
transform-style: preserve-3D;
height: 100%;
position: relative;
left: 0;
transition: all $globalTransitionmTime + .009s $globalTransitionEasing;
.shadow {
img {
position: absolute;
width: 210px;
top: 90px;
left: 20px;
}
}
h1 {
text-transform: uppercase;
margin: 0;
transform-origin: 0 50%;
position: absolute;
line-height: 0;
left: 47px;
letter-spacing: 3px;
top: 92px;
color: #c6bdad;
font-size: 55px;
text-shadow: 0 0 1px #bdb5ad;
transform-style: preserve-3D;
@for $i from 1 through 100 {
&:nth-of-type(#{$i}) {
transform: rotate(90deg) translateZ(($i / 24) - 1 + px);
}
}
}
h2 {
font-size: 20px;
font-weight: 500;
position: absolute;
bottom: 14px;
line-height: 20px;
left: 24px;
width: 100px;
opacity: 1;
transform: translateZ(0);
transition: all $globalTransitionmTime $globalTransitionEasing;
}
.logo {
position: absolute;
z-index: auto;
top: 64px;
left: 20px;
img {
width: 50px;
image-rendering: pixelated;
mix-blend-mode: darken;
}
}
ul {
padding: 0;
margin: 0 0 0 30px;
li {
list-style-type: none;
text-transform: uppercase;
font-weight: 900;
margin: 0 0 4px 0;
color: #111008;
cursor: pointer;
transition: all .2s;
&:hover {
color: #a23426;
}
&.active {
color: #a23426;
}
}
&.small {
font-size: 7px;
margin-top: 80px;
li {
margin: 0 0 6px 0
}
}
&.big {
margin-top: 157px;
}
}
%face {
width: 100%;
height: 100%;
transform-style: preserve-3D;
background: linear-gradient(
to right,
#f0ece5,
var(--bg) 6%,
var(--bg)
), var(--bg);
position: absolute;
transform-style: preserve-3D;
}
& .face {
&--left,
&--front {
@extend %face;
}
&--left {
transform: rotateY(-90deg) translateX(-150px);
width: 150px;
transform-origin: 0 0;
z-index: -1;
}
}
}
}
}
}
View Compiled
dragging = false;
'use strict';
///console.clear();
class Grain {
constructor (el) {
/**
* Options
* Increase the pattern size if visible pattern
*/
this.patternSize = 150;
this.patternScaleX = 1;
this.patternScaleY = 1;
this.patternRefreshInterval = 3; // 8
this.patternAlpha = 28; // int between 0 and 255,
/**
* Create canvas
*/
this.canvas = el;
this.ctx = this.canvas.getContext('2d');
this.ctx.scale(this.patternScaleX, this.patternScaleY);
/**
* Create a canvas that will be used to generate grain and used as a
* pattern on the main canvas.
*/
this.patternCanvas = document.createElement('canvas');
this.patternCanvas.width = this.patternSize;
this.patternCanvas.height = this.patternSize;
this.patternCtx = this.patternCanvas.getContext('2d');
this.patternData = this.patternCtx.createImageData(this.patternSize, this.patternSize);
this.patternPixelDataLength = this.patternSize * this.patternSize * 4; // rgba = 4
/**
* Prebind prototype function, so later its easier to user
*/
this.resize = this.resize.bind(this);
this.loop = this.loop.bind(this);
this.frame = 0;
window.addEventListener('resize', this.resize);
this.resize();
window.requestAnimationFrame(this.loop);
}
resize () {
this.canvas.width = window.innerWidth * devicePixelRatio;
this.canvas.height = window.innerHeight * devicePixelRatio;
}
update () {
const {patternPixelDataLength, patternData, patternAlpha, patternCtx} = this;
// put a random shade of gray into every pixel of the pattern
for (let i = 0; i < patternPixelDataLength; i += 4) {
// const value = (Math.random() * 255) | 0;
const value = Math.random() * 255;
patternData.data[i] = value;
patternData.data[i + 1] = value;
patternData.data[i + 2] = value;
patternData.data[i + 3] = patternAlpha;
}
patternCtx.putImageData(patternData, 0, 0);
}
draw () {
const {ctx, patternCanvas, canvas, viewHeight} = this;
const {width, height} = canvas;
// clear canvas
ctx.clearRect(0, 0, width, height);
// fill the canvas using the pattern
ctx.fillStyle = ctx.createPattern(patternCanvas, 'repeat');
ctx.fillRect(0, 0, width, height);
}
loop () {
// only update grain every n frames
const shouldDraw = ++this.frame % this.patternRefreshInterval === 0;
if (shouldDraw) {
this.update();
this.draw();
}
window.requestAnimationFrame(this.loop);
}
}
/**
* Initiate Grain
*/
const el = document.querySelector('.grain');
const grain = new Grain(el);
$('.phone').mousedown(function(e) {
initX = e.clientX;
dragging = true;
})
$('html').mouseup(function(){
dragging = false
$('.dynamicCursor').css('width', '18px')
})
$('.phone').mousemove(function(e) {
if(dragging) {
let mouseX = e.clientX;
difference = mouseX - initX;
console.log(difference)
$('.dynamicCursor').css('width', Math.abs(difference) + 'px')
if(difference > 60) {
$('.phone').addClass('open')
}
if(difference < -60) {
$('.phone').removeClass('open')
}
}
});
function drawMouseSpeedDemo() {
var mrefreshinterval = 30; // update display every 500ms
var lastmousex=-1;
var lastmousey=-1;
var lastmousetime;
var mousetravel = 0;
var mpoints = [];
var mpoints_max = 30;
var direction;
$('html').mousemove(function(e) {
var mousex = e.pageX;
var mousey = e.pageY;
if (lastmousex > -1) {
mousetravel += Math.max( Math.abs(mousex-lastmousex), Math.abs(mousey-lastmousey) );
}
// console.log(mousex-lastmousex)
if(mousex-lastmousex > 0) {
direction = '+'
} else {
direction = '-'
}
//console.log(direction);
lastmousex = mousex;
lastmousey = mousey;
});
var mdraw = function() {
var md = new Date();
var timenow = md.getTime();
if (lastmousetime && lastmousetime!=timenow) {
var pps = Math.round(mousetravel / (timenow - lastmousetime) * 1000);
mpoints.push(pps);
if (mpoints.length > mpoints_max)
mpoints.splice(0,1);
mousetravel = 0;
//console.log(pps)
if(dragging) {
}
}
lastmousetime = timenow;
setTimeout(mdraw, mrefreshinterval);
}
// We could use setInterval instead, but I prefer to do it this way
setTimeout(mdraw, mrefreshinterval);
};
drawMouseSpeedDemo()
/* -------------------------------------------------
Dynamic cursor
--------------------------------------------------- */
const cursorSettings = {
'class' : 'dynamicCursor',
'size' : '18',
'expandedSize' : '40',
'expandSpeed' : 0.4,
'background' : 'rgba(161, 142, 218, 0.25)',
'opacity' : '1',
'transitionTime' : '1.4s',
'transitionEase' : 'cubic-bezier(0.075, 0.820, 0.165, 1.000)',
'borderWidth' : '0',
'borderColor' : 'black',
'iconSize': '11px',
'iconColor': 'white',
'triggerElements': {
'trigger' : {
'className' : 'trigger',
'icon' : '<i class="fa fa-plus"></i>'
},
'trigger2' : {
'className' : 'slider_inner',
'icon' : '<i class="fa fa-arrows-h"></i>'
}
}
}
function dynamicCursor(options) {
document.write('<link rel="stylesheet" href="https://maxcdn.icons8.com/fonts/line-awesome/1.1/css/line-awesome-font-awesome.min.css">');
var hold;
cursor = document.createElement('div');
let cursorIcon = document.createElement('div');
cursorIcon.classList.add('cursorIcon');
cursorIcon.style.position = 'absolute';
cursorIcon.style.fontFamily = 'Raleway';
cursorIcon.style.textTransform = 'uppercase';
cursorIcon.style.fontWeight = '800';
cursorIcon.style.textAlign = 'center'
cursorIcon.style.top = '50%';
cursorIcon.style.width = '100%';
cursorIcon.style.transform = 'translateY(-50%)';
cursorIcon.style.color = options.iconColor;
cursorIcon.style.fontSize = options.iconSize;
cursorIcon.style.opacity = 0;
cursorIcon.style.transition = `opacity ${options.expandSpeed}s`;
cursor.classList.add(options.class);
cursor.style.boxSizing = 'border-box';
cursor.style.width = `${options.size}px`;
cursor.style.height = `${options.size}px`;
cursor.style.borderRadius = `${options.expandedSize}px`;
cursor.style.opacity = 0;
cursor.style.pointerEvents = 'none';
cursor.style.zIndex = 999;
cursor.style.transition = `transform ${options.transitionTime} ${options.transitionEase}, width 0s, height ${options.expandSpeed}s .2s, opacity 1s .2s`;
cursor.style.border = `${options.borderWidth}px solid ${options.borderColor}`;
cursor.style.position = 'fixed';
cursor.style.background = options.background;
cursor.appendChild(cursorIcon);
document.body.appendChild(cursor);
setTimeout(function() {
cursor.style.opacity = options.opacity;
}, 500)
var idle;
document.onmousemove = e => {
console.log('test')
x = e.pageX;
y = e.pageY;
cursor.style.opacity = options.opacity;
clearInterval(idle)
idle = setTimeout(function() {
cursor.style.opacity = 0;
}, 4000)
cursor.style.top = '0';
cursor.style.left = '0';
cursor.style.transform = `translateX(calc(${x}px - 50%)) translateY(calc(${y}px - 50%))`;
}
for(i in options.triggerElements) {
let trigger = $(`.${options.triggerElements[i].className}`);
console.log(trigger);
let icon = options.triggerElements[i].icon;
if(!trigger) {
console.warn('You dont have any triggers');
} else {
trigger.each(function(el){
console.log()
trigger[el].style.cursor = 'default';
trigger[el].addEventListener('mouseover', () => {
console.log('over')
cursor.style.width = `${options.expandedSize}px`;
cursor.style.height = `${options.expandedSize}px`;
cursorIcon.innerHTML = icon;
cursorIcon.style.opacity = 1;
console.log($(this))
})
trigger[el].addEventListener('mouseout', () => {
cursor.style.width = `${options.size}px`;
cursor.style.height = `${options.size}px`;
cursorIcon.style.opacity = 0;
})
})
}
}
}
dynamicCursor(cursorSettings);
$('.back').click(function(){
$(this).parent().parent().removeClass('expand')
})
View Compiled
This Pen doesn't use any external CSS resources.