-
const ITEMS = [
//- {
//- identifier: 'kody-yellow',
//- backgroundPositionX: 53.15,
//- backgroundPositionY: 50,
//- size: 739,
//- config: {
//- positionX: 50,
//- positionY: 54,
//- moveX: 0.15,
//- moveY: -0.25,
//- height: 58,
//- width: 55,
//- rotate: 0.01,
//- },
//- },
//- {
//- identifier: 'kody-red',
//- backgroundPositionX: 100,
//- backgroundPositionY: 50,
//- size: 739,
//- config: {
//- positionX: 50,
//- positionY: 54,
//- moveX: 0.15,
//- moveY: -0.25,
//- height: 58,
//- width: 55,
//- rotate: 0.01,
//- },
//- },
//- {
//- identifier: 'kody-white',
//- backgroundPositionX: 68.8,
//- backgroundPositionY: 50,
//- size: 739,
//- config: {
//- positionX: 50,
//- positionY: 54,
//- moveX: 0.15,
//- moveY: -0.25,
//- height: 58,
//- width: 55,
//- rotate: 0.01,
//- },
//- },
{
identifier: 'kody-blue',
backgroundPositionX: 84.4,
backgroundPositionY: 50,
size: 739,
config: {
positionX: 50,
positionY: 54,
moveX: 0.15,
moveY: -0.25,
height: 58,
width: 55,
rotate: 0.01,
},
},
{
identifier: 'battery',
size: 2620,
backgroundPositionX: -0.075,
backgroundPositionY: 0,
config: {
positionX: 74,
positionY: 15,
positionZ: -1,
moveX: 1.5,
moveY: -0.85,
height: 17,
width: 17,
},
},
{
identifier: 'leaf-one',
size: 10000,
backgroundPositionX: 3.75,
backgroundPositionY: -1,
config: {
positionX: 35,
positionY: 94,
moveX: 1.5,
moveY: -0.85,
height: 7,
width: 4,
rotate: 0.6,
},
},
{
identifier: 'leaf-two',
size: 5800,
backgroundPositionX: 10.15,
backgroundPositionY: -0.25,
config: {
positionX: 97,
positionY: 63,
moveX: 1.5,
moveY: -0.85,
height: 4,
width: 8,
rotate: -0.5,
},
},
{
identifier: 'leaf-three',
size: 8000,
backgroundPositionX: 8.85,
backgroundPositionY: -0.5,
config: {
positionX: 84,
positionY: 21,
moveX: 1.5,
moveY: -0.85,
height: 7,
width: 6,
rotate: 0.75,
},
},
{
identifier: 'leaf-four',
size: 13500,
backgroundPositionX: 19.125,
backgroundPositionY: -0.5,
config: {
positionX: 57,
positionY: 18,
moveX: 1.5,
moveY: -0.85,
height: 7,
width: 3,
rotate: 0.35,
},
},
{
identifier: 'leaf-five',
size: 6500,
backgroundPositionX: 16,
backgroundPositionY: -1,
config: {
positionX: 55,
positionY: 94,
moveX: 1.5,
moveY: -0.85,
height: 10,
width: 6,
rotate: 0.6,
},
},
{
identifier: 'leaf-six',
size: 5000,
backgroundPositionX: 14,
backgroundPositionY: -0.5,
config: {
positionX: 9,
positionY: 22,
moveX: 1.5,
moveY: -0.85,
height: 8,
width: 8,
rotate: 1,
},
},
{
identifier: 'leaf-seven',
size: 5100,
backgroundPositionX: 11.975,
backgroundPositionY: -0.5,
config: {
positionX: 4,
positionY: 83,
moveX: 1.5,
moveY: -0.85,
height: 8,
width: 8,
rotate: -0.5,
},
},
{
identifier: 'leaf-eight',
size: 5000,
backgroundPositionX: 20.15,
backgroundPositionY: -0.5,
config: {
positionX: 10,
positionY: 74,
moveX: 1.5,
moveY: -0.85,
height: 5,
width: 8,
rotate: 0.25,
},
},
{
identifier: 'leaf-nine',
size: 5000,
backgroundPositionX: 4.8,
backgroundPositionY: -0.25,
config: {
positionX: 83,
positionY: 64,
moveX: 1.5,
moveY: -0.85,
height: 9,
width: 9,
rotate: -0.6,
},
},
{
identifier: 'leaf-ten',
size: 5000,
backgroundPositionX: 6.85,
backgroundPositionY: 0,
config: {
positionX: 56,
positionY: 4,
moveX: 1.5,
moveY: -0.85,
height: 8,
width: 8,
rotate: 0.8,
},
},
{
identifier: 'leaf-eleven',
size: 6200,
backgroundPositionX: 17.65,
backgroundPositionY: -0.5,
config: {
positionX: 28,
positionY: 32,
moveX: 1.5,
moveY: -0.85,
height: 4,
width: 8,
rotate: 0.6,
},
},
{
identifier: 'one-wheel',
size: 1250,
backgroundPositionX: 27.5,
backgroundPositionY: -8,
config: {
positionX: 80,
positionY: 83,
positionZ: 2,
rotate: 0.2,
moveX: 1.5,
moveY: -0.85,
height: 26,
width: 32,
},
},
{
identifier: 'speaker',
size: 2150,
backgroundPositionX: 35,
backgroundPositionY: 0,
config: {
positionX: 12,
positionY: 51,
positionZ: 2,
moveX: 1.5,
moveY: -0.85,
height: 24,
width: 19,
},
},
{
identifier: 'skis',
size: 1240,
backgroundPositionX: 41.3,
backgroundPositionY: -2,
config: {
positionX: 80,
positionY: 40,
positionZ: 10,
moveX: 1.5,
moveY: -0.85,
height: 30,
width: 30,
},
},
{
identifier: 'recycle',
size: 2850,
backgroundPositionX: 22.55,
backgroundPositionY: 0,
config: {
positionX: 28,
positionY: 10,
rotate: -2,
moveX: 1.5,
moveY: -0.85,
height: 15,
width: 15,
},
},
]
.parallax(style="--rx: 0.1; --ry: 0.25; --rotate: 0.02;")
- for (const ITEM of ITEMS)
.parallax__item(style=`--pos-x: ${ITEM.backgroundPositionX}; --pos-y: ${ITEM.backgroundPositionY}; --size: ${ITEM.size}; --width: ${ITEM.config.width}; --height: ${ITEM.config.height}; --x: ${ITEM.config.positionX}; --y: ${ITEM.config.positionY}; --z: ${ITEM.config.positionZ || 0}; --r: ${ITEM.config.rotate || 0}; --rx: ${ITEM.config.rotateX || 0}; --ry: ${ITEM.config.rotateY || 0}; --mx: ${ITEM.config.moveX || 0}; --my: ${ITEM.config.moveY || 0};`)
View Compiled
*
box-sizing border-box
transform-style preserve-3d
body
min-height 100vh
display grid
place-items center
background hsl(210, 20%, 20%)
overflow hidden
transform-style preserve-3d
perspective 50vmin
img
position fixed
top 50%
left 50%
height 50vmin
transform translate(-50%, -50%)
opacity 0.5
.parallax
height 50vmin
width calc(50 * (484 / 479) * 1vmin)
position relative
perspective 50vmin
transform rotateX(calc((var(--rx, 0) * var(--ratio-y, 0)) * 1deg)) rotateY(calc((var(--ry, 0) * var(--ratio-x, 0)) * 1deg)) rotate(calc((var(--r, 0) * var(--ratio-x, 0)) * 1deg))
&__item
position absolute
left calc(var(--x, 50) * 1%)
top calc(var(--y, 50) * 1%)
height calc(var(--height, auto) * 1%)
width calc(var(--width, auto) * 1%)
transform translate(-50%, -50%) translate3d(calc((var(--mx, 0) * var(--ratio-x, 0)) * 1%), calc((var(--my, 0) * var(--ratio-y, 0)) * 1%), calc(var(--z, 0) * 1vmin)) rotateX(calc((var(--rx, 0) * var(--ratio-y, 0)) * 1deg)) rotateY(calc((var(--ry, 0) * var(--ratio-x, 0)) * 1deg)) rotate(calc((var(--r, 0) * var(--ratio-x, 0)) * 1deg))
transform-style preserve-3d
background-image url("https://assets.codepen.io/605876/kody-sprite.png")
background-position calc(var(--pos-x, 0) * 1%) calc(var(--pos-y, 0) * 1%)
background-size calc(var(--size, 0) * 1%)
View Compiled
import gsap from 'https://cdn.skypack.dev/[email protected]'
const CONTAINER = document.querySelector('.parallax')
const generateHandler = (element, proximity, cb) => ({x, y}) => {
const bounds = 100
const elementBounds = element.getBoundingClientRect()
const centerX = elementBounds.left + elementBounds.width / 2
const centerY = elementBounds.top + elementBounds.height / 2
const boundX = gsap.utils.mapRange(centerX - proximity, centerX + proximity, -bounds, bounds, x)
const boundY = gsap.utils.mapRange(centerY - proximity, centerY + proximity, -bounds, bounds, y)
cb(boundX / 100, boundY / 100)
}
const UPDATE = (x, y) => {
CONTAINER.style.setProperty('--ratio-x', Math.floor(gsap.utils.clamp(-60, 60, x * 100)))
CONTAINER.style.setProperty('--ratio-y', Math.floor(gsap.utils.clamp(-60, 60, y * 100)))
}
document.addEventListener('pointermove', generateHandler(CONTAINER, window.innerWidth * 0.5, UPDATE))
This Pen doesn't use any external CSS resources.
This Pen doesn't use any external JavaScript resources.