preface
Win10 Metro compared to the previous generation of completely flat style Win8 Metro in animation effect and interactive experience have a relatively large difference, so want to achieve a more realistic Win10 Metro need what animation effect?
Is it really Windows 10 Metro?
Taking a look at this Demo, the seemingly complicated interaction is actually not that difficult to implement. Let’s take a look at the animation effects and implementation principles.
Metro animation effect and implementation
1. 3 d rotation
One notable feature of Win10 Metro is the 3D rotation of the tiles.
The original
implementation
We showed each magnet as a cuboid with a square cross section, and then realized 3D rotation through CSS rotation animation.
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>
Copy the code
In THE HTML structure, the main function of scene node is to serve as a scene container. With scene, we can make some adjustments to the attributes in the scene. For example, by adjusting perspective, we can enhance or weaken the three-dimensional sense of cuboid when it rotates. Box-container refers to the container node of a cuboid, which contains six surface nodes of a cuboid: front, back, top, bottom, right, and 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.5 s;
transform-origin: 50% 50% -75px;
}
.front {
background-color: rgba,0.5 (3122241);position: absolute;
width: 300px;
height: 150px;
}
.back {
background-color: rgba,3,3,0.5 (241);position: absolute;
width: 300px;
height: 150px;
transform: translateZ(-150px) rotateZ(180deg) rotateY(180deg);
}
.top {
background-color: rgba,0.5 (3241122);position: absolute;
width: 300px;
height: 150px;
transform: translate3d(0,-75px,-75px) rotateX(90deg);
}
.bottom {
background-color: rgba,3,0.5 (241241);position: absolute;
width: 300px;
height: 150px;
transform: translate3d(0,75 px, 75 px)rotateX(-90deg);
}
.left {
background-color: rgba,97,48,0.5 (270);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);
}
Copy the code
In CSS, the following points are worth noting
.box-container
The use of thetransform-style: preserve-3d
To preserve the 3D coordinates of the child nodes in 3D transformation. By using thetransform-origin: 50% 50% -75px
will.box-container
The origin of rotation is placed at the center of the cuboid.- In order to make the content on the back of cuboid not reversed after rotation, in
.back
In the definition oftransform
To add additionalrotateZ(180deg)
Reverse the reverse in advance. - In order to keep each side of the content not because
The Z axis
While zooming in or out, we always keep the current plane facing the observerZ coordinate
for0
.
Demo
3D rotation demo
2. Tilt
When the tile is clicked and held, the tile will appear an animation that tilts toward the clicked position.
The original
implementation
If you look closely at the original, you’ll see that the Angle of the face will vary depending on where you press it. When pressing close to the edge of the magnet, the tilt Angle will be larger; When pressed close to the center of the magnet, the tilt Angle will be reduced. By summarizing the above rules, we can draw the following conclusions:
In the center of the magnet as a coordinate system origin (0, 0), when click the position (x, y), on the x axis Angle Ɵ ∝ x | y |, and y axis Angle Ɵ ∝ y | | x.
html
<div class="container">
<div class="tile">
<span>Hello World</span>
</div>
</div>
Copy the code
css
.container {
width: 200px;
height: 200px;
perspective: 700px;
}
.tile {
background-color: #2d89ef;
width: 100%;
height: 100%;
transition: transform 0.5 s;
text-align: center;
color: white;
}
Copy the code
js
const maxTiltAngle = 30; // Set the maximum tilt Angle
const container = document.getElementsByClassName('container') [0];
const tile = document.getElementsByClassName('tile') [0];
const boundingRect = container.getBoundingClientRect();
const tilt = event= > {
// Calculate the mouse position relative to the container
const relativeX = event.pageX - (boundingRect.left + window.scrollX);
const relativeY = event.pageY - (boundingRect.top + window.scrollY);
// Move the origin from the upper left corner of the container to the center of the container
const normalizedX = relativeX - boundingRect.width / 2;
const normalizedY = -(relativeY - boundingRect.height / 2);
// Calculate the tilt Angle
const tiltX = normalizedY / (boundingRect.height / 2) * maxTiltAngle;
const tiltY = normalizedX / (boundingRect.width / 2) * maxTiltAngle;
/ / tilt
tile.style.transform = `rotateX(${tiltX}deg) rotateY(${tiltY}deg)`;
}
const recover = (a)= > {
// Restore the tilt
tile.style.transform = ' ';
}
container.addEventListener('mousedown', tilt);
container.addEventListener('mouseup', recover);
container.addEventListener('mouseleave', recover);
Copy the code
There are several points to note in the implementation of tilting
- The center of the magnet with length L and width W is used as the origin of the coordinate system (0, 0). When clicking position (x, y), the formula used in the realization is as follows: the inclination Angle on the X-axis Ɵx = y/(W / 2) * Ɵ Max, and the inclination Angle on the Y-axis Ɵy = x/(L / 2) * Ɵ Max.
- It is not enough to restore the tilt only during mouseup events; it also needs to restore the tilt during Mouseleave.
Demo
Tilt the demo
3. Hover halo
When the mouse hovers over the magnet, the magnet has an aperture that moves with the mouse.
The original
implementation
The color of halo gradually fades from the center to the periphery, and the position of halo center will move with the movement of the mouse.
html
<div class="container">
<div class="hoverLayer">
</div>
<div class="hoverGlare">
</div>
</div>
Copy the code
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,0.1 (255255255)100%);
transform: translate(-100px, -100px);
width: 400px;
height: 400px;
opacity: 0.4;
}
Copy the code
js
const boundingRect = document.getElementsByClassName('container') [0].getBoundingClientRect();
const hoverGlare = document.getElementsByClassName('hoverGlare') [0];
const glare = event= > {
// Calculate the mouse position relative to the container
const relativeX = event.pageX - (boundingRect.left + window.scrollX);
const relativeY = event.pageY - (boundingRect.top + window.scrollY);
// Move the origin from the upper left corner of the container to the center of the container
const normalizedX = relativeX - boundingRect.width / 2;
const normalizedY = relativeY - boundingRect.height / 2;
// Adjust the halo transparency and position
hoverGlare.style.opacity = 0.4;
hoverGlare.style.transform = `translate(${normalizedX}px, ${normalizedY}px) translate(-${boundingRect.width / 2}px, -${boundingRect.height / 2}px)`;
}
const resetGlare = (a)= > {
// Hide the halo
hoverGlare.style.opacity = 0;
}
const hoverLayer = document.getElementsByClassName('hoverLayer') [0];
hoverLayer.addEventListener('mousemove', glare);
hoverLayer.addEventListener('mouseleave', resetGlare);
Copy the code
In the implementation of halo, the following points need to be noted
- We use
z-index
for1
the.hoverLayer
As the mouse event node, to avoid the problem of inaccurate mouse positioning because the child node overwrites the parent node. - We created a halo suspension twice the width and height of the container and passed through
translate
Move the suspension layer to achieve efficient halo position shifting.
Demo
Hover halo demo
4. Click the ripple
When the mouse clicks on the magnet, a ripple animation will be formed in the clicking position and spread outwards
The original
implementation
We can see that the circular ripple starts from the click and spreads outward until it dissipates.
html
<div class="tile">
<div class="clickGlare">
</div>
</div>
Copy the code
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.3 s;
animation-timing-function: ease-in;
}
@keyframes ripple {
0% {
opacity: 0.5; 100%} {transform: scale(5);
opacity: 0; }}Copy the code
js
const tile = document.getElementsByClassName('tile') [0];
const boundingRect = tile.getBoundingClientRect();
const clickGlare = document.getElementsByClassName('clickGlare') [0];
const ripple = event= > {
// This parameter is executed only when the class of the node does not contain ripple
if (clickGlare.classList.contains('ripple')) return;
// Calculate the mouse position relative to the container
const relativeX = event.pageX - (boundingRect.left + window.scrollX);
const relativeY = event.pageY - (boundingRect.top + window.scrollY);
// Adjust the center position of the ripple according to the mouse position
clickGlare.style.top = `${relativeY - 45}px`;
clickGlare.style.left = `${relativeX - 45}px`;
// Add a ripple animation
clickGlare.classList.add('ripple');
}
const resetRipple = (a)= > {
// Remove the ripple animation
clickGlare.classList.remove('ripple');
}
tile.addEventListener('mousedown', ripple);
clickGlare.addEventListener('animationend', resetRipple);
Copy the code
There are several points to note in the implementation of the click ripple
- To make the ripple animation more similar to the original, we used
filter: blur
This CSS, this CSS may cause compatibility issues in older browsers or IE/Edge.
Demo
Click on the demo of the ripple
summary
If we put the above animations together, we can achieve a more realistic Windows 10 Metro layout. Isn’t Windows 10 Metro as simple as it looks?
The animations included in Windows 10 tiles are broken down to some of the more common animations that enhance the user experience. You can also try to imitate these simple animations in your daily projects or work to make interaction and design more friendly.
Finally, I also made a widget using Vue, which is convenient for you to implement Win 10 Metro layout in Vue. Welcome to exchange and discuss