предисловие
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 стоит отметить следующие моменты
-
.box-container
используется вtransform-style: preserve-3d
для сохранения 3D-координат дочерних узлов во время 3D-преобразования. и используетсяtransform-origin: 50% 50% -75px
Буду.box-container
Начало вращения находится в центре прямоугольного параллелепипеда. - Чтобы содержимое обратной стороны кубоида не переворачивалось после поворота, в
.back
В определении нам нужноtransform
дополнительно добавлено вrotateZ(180deg)
Содержание ранее обратно обратно. - Для того, чтобы сохранить содержимое каждой стороны от
Z轴
Увеличение или уменьшение масштаба координат, мы всегда сохраняем текущее лицо наблюдателяZ坐标
для0
.
Demo
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);
В наклонной реализации есть место, чтобы обратить внимание на
- Когда длина от L до ширины W в качестве центра системы координат плитки (0, 0), нажмите на положение (x, y), оно используется для достижения формулы: Ɵx Угол наклона оси X = y / ( W / 2) * Ɵмакс, угол наклона Ɵy по оси Y = x / (L / 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);
При реализации ореола следует обратить внимание на следующие моменты.
- мы использовали
z-index
для1
из.hoverLayer
Чтобы события мыши были узлами, избегайте дочерних узлов покрытия родительского узла, сгенерированного позиционированием мыши, неточным. - Создаем слой подвески гало в 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);
При реализации кликовой пульсации следует обратить внимание на следующие моменты.
- Чтобы сделать пульсирующую анимацию более похожей на оригинал, мы использовали
filter: blur
Этот css, этот css может вызвать проблемы совместимости в старых браузерах или IE/Edge.
Demo
Нажмите на демонстрацию Ripple
резюме
Если мы объединим приведенные выше анимации, мы сможем добиться более реалистичного макета Windows 10 Metro. Казалось бы, сложная Windows 10 Metro на самом деле довольно проста, не так ли?
Анимации, включенные в плитки Windows 10, разобраны и являются одними из наиболее распространенных анимаций, которые могут улучшить взаимодействие с пользователем. Вы также можете попробовать имитировать эти простые анимации в своих обычных проектах или поработать над тем, чтобы сделать взаимодействие и дизайн более дружелюбным.
Наконец, я также сделал использование Vueвиджет, который удобен для всех, чтобы реализовать макет Win 10 Metro в Vue. Добро пожаловать на ваши обмены и обсуждения ~