Живая галерея

Разработка Живая галерея

Нет прав для скачивания
Живая галерея.
Пишем нашу разметку HTML:
HTML:
<div class="gallery-container">
  <div class="gallery">
    <div class="frame"><img class="image" src="https://s3-us-west-2.amazonaws.com/s.cdpn.io/544318/pumpernickel.png"/>
      <div class="info">Pumpernickel</div>
    </div>
    <div class="frame"><img class="image" src="https://s3-us-west-2.amazonaws.com/s.cdpn.io/544318/rye.png"/>
      <div class="info">Rye</div>
    </div>
    <div class="frame"><img class="image" src="https://s3-us-west-2.amazonaws.com/s.cdpn.io/544318/wheat.png"/>
      <div class="info">Wheat</div>
    </div>
    <div class="frame"><img class="image" src="https://s3-us-west-2.amazonaws.com/s.cdpn.io/544318/ciabatta.png"/>
      <div class="info">Ciabatta</div>
    </div>
    <div class="frame"><img class="image" src="https://s3-us-west-2.amazonaws.com/s.cdpn.io/544318/baguette.png"/>
      <div class="info">Baguette</div>
    </div>
  </div>
</div><a id="codepen-link" href="https://www.codepen.io/seanfree" target="_blank"></a>
Далее пишем стиль:
CSS:
body {
  height: 100vh;
  overflow: hidden;
  background: palegoldenrod;
}

.gallery-container {
  position: relative;
  height: 100vh;
  width: 100vw;
  overflow: hidden;
}

.gallery {
  position: absolute;
  top: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100vw;
  height: 200px;
  -webkit-perspective: 800px;
          perspective: 800px;
  -webkit-transform-style: preserve-3d;
          transform-style: preserve-3d;
  -webkit-transform-origin: center center;
          transform-origin: center center;
  -webkit-transform: translateY(-50%);
          transform: translateY(-50%);
}

.frame {
  display: flex;
  flex-flow: column;
  align-items: center;
  justify-content: center;
  border: 2px solid white;
  border-radius: 4px;
  position: relative;
  height: 100%;
  width: 200px;
  background: white;
  -webkit-transform-style: preserve-3d;
          transform-style: preserve-3d;
  -webkit-transform-origin: center center;
          transform-origin: center center;
  cursor: pointer;
  overflow: hidden;
  background: radial-gradient(#cfaf7f, #6a4a0f);
}
.frame .image {
  display: block;
  position: relative;
  height: auto;
  width: 90%;
  pointer-events: none;
}
.frame .info {
  color: white;
  text-shadow: 0 0 2px rgba(0, 0, 0, 0.8);
  font-family: "Source Sans Pro", serif;
  font-size: 1.2em;
}

#codepen-link {
  position: absolute;
  bottom: 20px;
  right: 30px;
  height: 40px;
  width: 40px;
  z-index: 10;
  border-radius: 50%;
  box-sizing: border-box;
  background-image: url("https://s3-us-west-2.amazonaws.com/s.cdpn.io/544318/logo.jpg");
  background-position: center center;
  background-size: cover;
  opacity: 0.4;
  transition: all 0.25s;
}
#codepen-link:hover {
  opacity: 0.8;
  box-shadow: 0 0 6px #000000;
}
И придаем динамики:
JavaScript:
const $ = selector => document.querySelector(selector);
const $$ = selector => document.querySelectorAll(selector);
let tick = 0;

function lerp(n1, n2, speed) {
    return (1 - speed) * n1 + speed * n2;
}

function angle(from, to) {
    return Math.atan2(
        to[1] - from[1],
        to[0] - from[0]
    );
}

function distance(from, to) {
    return Math.sqrt(
        Math.pow(to[0] - from[0], 2),
        Math.pow(to[1] - from[1], 2)
    );
}

function distNorm(from, to, xMax, yMax) {
    return Math.sqrt(
        Math.pow((to[0] - from[0]) / xMax, 2),
        Math.pow((to[1] - from[1]) / yMax, 2)
    );
}

Array.prototype.lerp = function(target, speed) {
    this.forEach((n, i) => this[i] = lerp(n, target[i], speed));
};

class Frame {
    constructor(node) {
        this.node = node;
        this.scale = 1;
        this.maxScale = 1.25;
        this.rotation = [0, 0, 0];
        this.translation = [0, 0, 0];
        this.center = [0, 0];
        this.target = [
            0.5 * window.innerWidth,
            0.5 * window.innerHeight
        ];
        this.padding = [
            0.5 * this.node.clientWidth,
            0.5 * this.node.clientHeight
        ];
        this.focus = false;
        this.mouseover = false;
        this.distance = 0;
        this.node.addEventListener('mousemove', this.hover.bind(this));
        this.node.addEventListener('mouseleave', this.hover.bind(this));
        this.setCenter();
    }
    setCenter() {
        let rect = this.node.getBoundingClientRect();
        this.center[0] = rect.left + this.padding[0];
        this.center[1] = rect.top + this.padding[1];
        return this;
    }
    setTarget(target) {
        this.target[0] = target[0];
        this.target[1] = target[1];
        return this;
    }
    setDistance() {
        this.distNorm = distNorm(this.center, this.target, window.innerWidth, 0.5 * window.innerHeight);
        return this;
    }
    translate() {
        this.translation.lerp([
            0,
            0,
            this.mouseover ? 300 : 200 - this.distNorm * 400
        ], 0.15);
        return this;
    }
    rotate() {
        let theta = angle(this.center, this.target);
        this.rotation.lerp([
            Math.sin(-theta) * 60 * this.distNorm,
            Math.cos(theta) * 90 * this.distNorm
        ], 0.15);
        return this;
    }
    update() {
        this.node.style.transform = `
            translate3d(${this.translation[0]}px,${this.translation[1]}px,${this.translation[2]}px)
            rotateX(${this.rotation[0]}deg) rotateY(${this.rotation[1]}deg)
        `;
    }
    hover(e) {
        this.mouseover = e.type === 'mousemove';
    }
}

class Gallery {
    constructor() {
        this.container = $('.gallery');
        this.center = [
            0.5 * window.innerWidth,
            0.5 * window.innerHeight
        ];
        this.mouse = this.center.slice(0);
        this.target = this.mouse.slice(0);
        this.container.addEventListener('mousemove', this.hover.bind(this));
        this.container.addEventListener('mouseleave', this.hover.bind(this));
        window.addEventListener('resize', this.resize.bind(this));
        this.initFrames();
        this.update();
    }
    initFrames() {
        this.frames = [];
        $$('.frame').forEach(node => this.frames.push(new Frame(node)));
    }
    resize() {
        this.center = [
            0.5 * window.innerWidth,
            0.5 * window.innerHeight
        ]
        this.frames.forEach(frame => frame.setCenter());
    }
    hover(e) {
        this.mouseover = e.type === 'mousemove';
        this.target[0] = e.clientX;
        this.target[1] = e.clientY;
    }
    update() {
        this.mouse.lerp(
            this.mouseover ? this.target : this.center,
            0.125
        );
        this.frames.forEach(frame => {
            frame.setTarget(this.mouse)
                .setDistance()
                .translate()
                .rotate()
                .update();
        });
        this.container.style.perspectiveOrigin = `${this.mouse[0]}px 50%`;
        window.requestAnimationFrame(this.update.bind(this));
    }
}

const gallery = new Gallery();
Смотрим наш результат:
45w12.gif
Автор
baltun
Скачиваний
0
Просмотры
1.135
Первый выпуск
Обновление
Рейтинг
0.00 звёзд Оценок: 0

Ещё ресурсы от baltun

Назад
Верх Низ