The effect is shown below:
View the demo Download the source code
HTML structure
Apple TV is a high-definition TV set-top box product launched by Apple after Airport Express. If you have ever used it, you will definitely be attracted by the cool movie poster visual effects.
The HTML structure of this visual difference effect uses a
<div class="poster"> <div class="shine"></div> <div class="layer-1"></div> <div class="layer-2"></div> <div class="layer-3"></div> <div class="layer-4"></div> <div class="layer-5"></div> </div> <div.shine>是用于制作流光效果的图层。
CSS style
In order for the wrapped element .poster to create a 3D rotation effect, its parent element needs to set perspective and transform-style.
body { background: linear-gradient(to bottom, #f6f7fc 0%,#d5e1e8 40%); transform-style: preserve-3d; transform: perspective(800px); }
The poster size here is set to a fixed 320x500 pixels, centered relative to the page, giving it a rounded corner effect and some shadow effects.
.poster { width: 320px; height: 500px; position: absolute; top: 50%; left: 50%; margin: -250px 0 0 -160px; border-radius: 5px; box-shadow: 0 45px 100px rgba(0, 0, 0, 0.4); overflow:hidden; }
The poster is centered using the absolute positioning method: left and top are 50% respectively, and then margin-left and margin-top are set to negative width and height values.
All "layers" in the poster can be selected through the div[class*="layer-"] selector. All layers are set to absolute positioning, the background image is not repeated, background-position is set to the upper left corner, and the size of the background is set to 100% width and automatic height.
div[class*="layer-"] { position: absolute; top: -10px; left: -10px; right: -10px; bottom: -10px; background-size: 100% auto; background-repeat: no-repeat; background-position: 0 0; transition:0.1s; }
Note that the values of the top, left, right and bottom attributes in the above code are all -10 pixels. They are used to make the layer's dimensions 20 pixels larger than the dimensions of the poster. The reason for this is to hide the edges of the layer when creating a visual difference effect.
Finally set a background image for each layer.
.layer-1 { background-image: url('images/1.png'); } .layer-2 { background-image: url('images/2.png'); } .layer-3 { top: 0; bottom: 0; left: 0; right: 0; background-image: url('images/3.png'); } .layer-4 { background-image: url('images/4.png'); } .layer-5 { background-image: url('images/5.png'); }
JavaScript
The principle of this visual difference effect is that every time the user moves the mouse, the transforms: translateY, rotate and rotateY properties of .poster will change according to the position of the mouse. The farther the mouse is from the upper left corner, the more area the animation will be visible.
The calculation formula is similar to offsetX = 0.5 – mouse position / width of the window.
In order to give different animation speeds to each layer, it needs to be multiplied by a custom animation speed value. This value is provided by data-offset="number" on the HTML tag.
<div data-offset="-2" class="layer-1"></div> <div class="layer-2"></div> <div data-offset="1" class="layer-3"></div> <div data-offset="3" class="layer-4"></div> <div data-offset="10" class="layer-5"></div>
The larger the value of data-offset, the larger the visible animation area.
The JS code for the entire visual difference effect is as follows:
var $poster = $('.poster'), $shine = $('.shine'), $layer = $('div[class*="layer-"]'); $(window).on('mousemove', function(e) { var w = $(window).width(), //窗口宽度 h = $(window).height(), /窗口高度 offsetX = 0.5 - e.pageX / w, //鼠标X坐标 offsetY = 0.5 - e.pageY / h, //鼠标Y坐标 dy = e.pageY - h / 2, //@h/2 = 海报容器中心 dx = e.pageX - w / 2, //@w/2 = 海报容器中心 theta = Math.atan2(dy, dx), //鼠标和海报中心的RAD角度 angle = theta * 180 / Math.PI - 90, //转换 rad 为 degrees offsetPoster = $poster.data('offset'), transformPoster = 'translateY(' + -offsetX * offsetPoster + 'px) rotateX(' + (-offsetY * offsetPoster) + 'deg) rotateY(' + (offsetX * (offsetPoster * 2)) + 'deg)'; //get angle between 0-360 if (angle < 0) { angle = angle + 360; } //gradient angle and opacity $shine.css('background', 'linear-gradient(' + angle + 'deg, rgba(255,255,255,' + e.pageY / h * .5 + ') 0%,rgba(255,255,255,0) 80%)'); //poster transform $poster.css('transform', transformPoster); //parallax foreach layer $layer.each(function() { var $this = $(this), offsetLayer = $this.data('offset') || 0, transformLayer = 'translateX(' + offsetX * offsetLayer + 'px) translateY(' + offsetY * offsetLayer + 'px)'; $this.css('transform', transformLayer); });