Восстановление макета Windows 10 Metro

внешний интерфейс контейнер Windows CSS
Восстановление макета Windows 10 Metro

предисловие

Win10 Metro имеет относительно большую разницу в анимационном эффекте и интерактивном опыте по сравнению с предыдущим поколением полного плоского стиля, тогда какие анимационные эффекты вы хотите добиться относительно реалистичного Win10 Metro?

Это действительно Windows 10 Metro?

Давайте взглянемэто демоКазалось бы сложное взаимодействие реализовать не сложно, давайте посмотрим на анимацию в которой разборка и реализация принципа ее.

Эффект и реализация анимации метро

1. 3D-вращение

Одной из наиболее примечательных особенностей Win10 Metro является трехмерное вращение плиток.

оригинальный

выполнить

Каждая плитка показана в виде квадратного поперечного сечения прямоугольного параллелепипеда и достигается вращением css 3D-анимации вращения.

html

<div class="scene">
  <div class="box-container">
    <div class="front">
    </div>
    <div class="back">
    </div>
    <div class="top">
    </div>
    <div class="bottom">
    </div>
    <div class="right">
    </div>
    <div class="left">
    </div>
  </div>
</div>

В структуре html,sceneОсновная роль узла — контейнер сцены, сsceneЗатем мы можем внести некоторые коррективы в свойства сцены, например, отрегулировавperspective, вы можете усилить или ослабить трехмерный эффект прямоугольного параллелепипеда при его вращении.box-containerявляется контейнерным узлом всего прямоугольного параллелепипеда, который содержит 6 узлов граней прямоугольного параллелепипеда.front, back, top, bottom, right, left.

css

.scene {
  position: relative;
  width: 300px;
  height: 150px;
  perspective: 700px;
}
.box-container {
  position: relative;
  width: 100%;
  height: 100%;
  transform-style: preserve-3d;
  transition: transform 0.5s;
  transform-origin: 50% 50% -75px;
}
.front {
  background-color: rgba(3,122,241,0.5);
  position: absolute;
  width: 300px;
  height: 150px;
}
.back {
  background-color: rgba(241,3,3,0.5);
  position: absolute;
  width: 300px;
  height: 150px;
  transform: translateZ(-150px) rotateZ(180deg) rotateY(180deg);
}
.top {
  background-color: rgba(3,241,122,0.5);
  position: absolute;
  width: 300px;
  height: 150px;
  transform: translate3d(0,-75px,-75px) rotateX(90deg);
}
.bottom {
  background-color: rgba(241,241,3,0.5);
  position: absolute;
  width: 300px;
  height: 150px;
  transform: translate3d(0,75px,-75px) rotateX(-90deg);
}
.left {
  background-color: rgba(270,97,48,0.5);
  position: absolute;
  width: 150px;
  height: 150px;
  transform: translate3d(-75px,0,-75px) rotateY(-90deg);
}
.right {
  background-color: rgba(30,97,48,0.5);
  position: absolute;
  width: 150px;
  height: 150px;
  transform: translate3d(225px,0,-75px) rotateY(90deg);
}

В css стоит отметить следующие моменты

  1. .box-containerиспользуется вtransform-style: preserve-3dдля сохранения 3D-координат дочерних узлов во время 3D-преобразования. и используетсяtransform-origin: 50% 50% -75pxБуду.box-containerНачало вращения находится в центре прямоугольного параллелепипеда.
  2. Чтобы содержимое обратной стороны кубоида не переворачивалось после поворота, в.backВ определении нам нужноtransformдополнительно добавлено вrotateZ(180deg)Содержание ранее обратно обратно.
  3. Для того, чтобы сохранить содержимое каждой стороны отZ轴Увеличение или уменьшение масштаба координат, мы всегда сохраняем текущее лицо наблюдателяZ坐标для0.

Demo

Демонстрация 3D-вращения







2. Наклон

Когда вы нажимаете и удерживаете плитку, плитка будет иметь анимацию, которая наклоняется в сторону положения касания.

оригинальный

выполнить

Если вы внимательно посмотрите на оригинал, то обнаружите, что угол наклона лица меняется в зависимости от положения нажатия. Когда положение нажатия находится рядом с краем плитки, угол наклона увеличивается; когда положение нажатия находится рядом с центром плитки, угол наклона соответственно уменьшается. Суммируя вышеизложенные правила, мы можем получить:

В центре тайла система координат как начало координат (0, 0), при щелчке по положению (x, y), угол наклона оси X Ɵx α |y |, угол наклона оси Y и Ɵy α| х | .

html

<div class="container">
  <div class="tile">
    <span>Hello World</span>
  </div>
</div>

css

.container {
  width: 200px;
  height: 200px;
  perspective: 700px;
}
.tile {
  background-color: #2d89ef;
  width: 100%;
  height: 100%;
  transition: transform 0.5s;
  text-align: center;
  color: white;
}

js

const maxTiltAngle = 30; // 设置最大倾斜角度

const container = document.getElementsByClassName('container')[0];
const tile = document.getElementsByClassName('tile')[0];
const boundingRect = container.getBoundingClientRect();

const tilt = event => {
  // 计算鼠标相对于容器的位置
  const relativeX = event.pageX - (boundingRect.left + window.scrollX);
  const relativeY = event.pageY - (boundingRect.top + window.scrollY);
  // 将原点从容器左上角移至容器中心
  const normalizedX = relativeX - boundingRect.width / 2;
  const normalizedY = -(relativeY - boundingRect.height / 2);
  // 计算倾斜角
  const tiltX = normalizedY / (boundingRect.height / 2) * maxTiltAngle;
  const tiltY = normalizedX / (boundingRect.width / 2) * maxTiltAngle;
  // 倾斜
  tile.style.transform = `rotateX(${tiltX}deg) rotateY(${tiltY}deg)`;
}

const recover = () => {
  // 恢复倾斜
  tile.style.transform = '';
}

container.addEventListener('mousedown', tilt);
container.addEventListener('mouseup', recover);
container.addEventListener('mouseleave', recover);

В наклонной реализации есть место, чтобы обратить внимание на

  1. Когда длина от L до ширины W в качестве центра системы координат плитки (0, 0), нажмите на положение (x, y), оно используется для достижения формулы: Ɵx Угол наклона оси X = y / ( W / 2) * Ɵмакс, угол наклона Ɵy по оси Y = x / (L / 2) * Ɵмакс.
  2. Мало восстановить наклон только в событии mouseup, его нужно восстановить еще и в mouseleave.

Demo

наклонная демонстрация







3. Парящий ореол

Когда мышь наводится на магнит, на плитке появляется отверстие, которое следует за движением мыши.

оригинальный

выполнить

Цвет ореола постепенно бледнеет от центра к периферии, а положение центра ореола перемещается вместе с движением мыши.

html

<div class="container">
  <div class="hoverLayer">
  </div>
  <div class="hoverGlare">
  </div>
</div>

css

.container {
  position: relative;
  background-color: #000;
  width: 200px;
  height: 200px;
  overflow: hidden;
}

.hoverLayer {
  position: absolute;
  z-index: 1;
  width: 100%;
  height: 100%;
}

.hoverGlare {
  position: absolute;
  background-image: radial-gradient(circle at center, rgba(255,255,255, 0.7) 0%, rgba(255,255,255,0.1) 100%);
  transform: translate(-100px, -100px);
  width: 400px;
  height: 400px;
  opacity: 0.4;
}

js

const boundingRect = document.getElementsByClassName('container')[0].getBoundingClientRect();

const hoverGlare = document.getElementsByClassName('hoverGlare')[0];

const glare = event => {
  // 计算鼠标相对于容器的位置
  const relativeX = event.pageX - (boundingRect.left + window.scrollX);
  const relativeY = event.pageY - (boundingRect.top + window.scrollY);
  // 将原点从容器左上角移至容器中心
  const normalizedX = relativeX - boundingRect.width / 2;
  const normalizedY = relativeY - boundingRect.height / 2;
  // 调整光晕透明度及位置
  hoverGlare.style.opacity = 0.4;
  hoverGlare.style.transform = `translate(${normalizedX}px, ${normalizedY}px) translate(-${boundingRect.width / 2}px, -${boundingRect.height / 2}px)`;
}

const resetGlare = () => {
  // 隐藏光晕
  hoverGlare.style.opacity = 0;
}

const hoverLayer = document.getElementsByClassName('hoverLayer')[0];

hoverLayer.addEventListener('mousemove', glare);
hoverLayer.addEventListener('mouseleave', resetGlare);

При реализации ореола следует обратить внимание на следующие моменты.

  1. мы использовалиz-indexдля1из.hoverLayerЧтобы события мыши были узлами, избегайте дочерних узлов покрытия родительского узла, сгенерированного позиционированием мыши, неточным.
  2. Создаем слой подвески гало в 2 раза больше ширины и высоты контейнера, и пропускаемtranslateПереместите этот слой подвески, чтобы добиться эффективного преобразования положения ореола.

Demo

Замедленная демонстрация Демонстрация







4. Нажмите на рябь

Когда мышь щелкнет по плитке, в месте щелчка будет сформирована анимация круговой ряби.

оригинальный

выполнить

Мы можем видеть, что круглые волны постепенно распространяются наружу от места щелчка, пока не исчезнут.

html

<div class="tile">
  <div class="clickGlare">
  </div>
</div>

css

.tile {
  position: relative;
  width: 200px;
  height: 200px;
  background-color: #000;
  overflow: hidden;
}

.clickGlare {
  position: absolute;
  width: 90px;
  height: 90px;
  border-radius: 50%;
  opacity: 0;
  filter: blur(5px);
  background-image: radial-gradient(rgba(255, 255, 255, 0.7) 0%, rgba(255, 255, 255, 0) 100%);
}

.ripple {
  animation-name: ripple;
  animation-duration: 1.3s;
  animation-timing-function: ease-in;
}

@keyframes ripple {
  0% {
    opacity: 0.5;
  }

  100% {
    transform: scale(5);
    opacity: 0;
  }

}

js

const tile = document.getElementsByClassName('tile')[0];
const boundingRect = tile.getBoundingClientRect();
const clickGlare = document.getElementsByClassName('clickGlare')[0];

const ripple = event => {
  // 仅当节点的class中不含ripple时执行
  if (clickGlare.classList.contains('ripple')) return;
  // 计算鼠标相对于容器的位置
  const relativeX = event.pageX - (boundingRect.left + window.scrollX);
  const relativeY = event.pageY - (boundingRect.top + window.scrollY);
  // 根据鼠标位置调整波纹的中心位置
  clickGlare.style.top = `${relativeY - 45}px`;
  clickGlare.style.left =  `${relativeX - 45}px`;
  // 添加波纹动画
  clickGlare.classList.add('ripple');
}

const resetRipple = () => {
  // 移除波纹动画
  clickGlare.classList.remove('ripple');
}

tile.addEventListener('mousedown', ripple);
clickGlare.addEventListener('animationend', resetRipple);

При реализации кликовой пульсации следует обратить внимание на следующие моменты.

  1. Чтобы сделать пульсирующую анимацию более похожей на оригинал, мы использовалиfilter: blurЭтот css, этот css может вызвать проблемы совместимости в старых браузерах или IE/Edge.

Demo

Нажмите на демонстрацию Ripple







резюме

Если мы объединим приведенные выше анимации, мы сможем добиться более реалистичного макета Windows 10 Metro. Казалось бы, сложная Windows 10 Metro на самом деле довольно проста, не так ли?

Анимации, включенные в плитки Windows 10, разобраны и являются одними из наиболее распространенных анимаций, которые могут улучшить взаимодействие с пользователем. Вы также можете попробовать имитировать эти простые анимации в своих обычных проектах или поработать над тем, чтобы сделать взаимодействие и дизайн более дружелюбным.

Наконец, я также сделал использование Vueвиджет, который удобен для всех, чтобы реализовать макет Win 10 Metro в Vue. Добро пожаловать на ваши обмены и обсуждения ~