2019独角兽企业重金招聘Python工程师标准>>>

今天我要和大家一起来学习一个酷炫的鼠标Hover效果。主要将会涉及到CSS3中3D效果的使用,以及在实现过程中我们使用到的一些简单的转换算法,我会尽量以图解的形式让理论变得更容易理解。废话不多说,我们先看一下最终效果:Hover特效。打开连接,鼠标进入图片列表区域并移动鼠标,观察对应区域中内容浮层的变化效果,注意:请使用高级浏览器预览(推荐Chrome浏览器)。

预备

我们先来做一些预备工作,我们在理解三维效果的时候,通常需要发挥一下自己的空间想象力,在二维的屏幕上看到三维的深度(立体几何中的Z轴)。除此之外我们也需要了解一些基本理论知识,比如透视点/观察点(perspective),比如远小近大等。当然我们还需要掌握一点点简单的数据转换能力,根据变换过程中的一些数据,利用一些简单的数学换算公式,计算得到我们在效果实现过程中需要的数据。再啰嗦一句:空间想象力是非常重要的,好吧,这就够了!

效果分析

为了帮助大家构建一个三维空间,我们现在一起来想想一下,正在阅读本文的自己,你的眼睛距离屏幕是有一定距离的,这个距离就相当于示例中的透视点(鼠标位置)到内容浮层的距离,只是案例为了做出内容区与背景之间的视差感,而将透视的终点定在了背景上,而背景距离内容层之间还有一定的距离。能想象出这三者的关系吗?透视点 - 内容浮层 - 背景,他们是有一个纵向深度的,就像你的眼睛到屏幕的距离。当我们移动我们的头将眼睛靠近屏幕的一边的时候,你会发现另一端的文字显得很小(远小近大),而且看着比较吃力,所以这个时候我们会希望旋转一下屏幕,让屏幕正对我们的眼睛,这就好比示例中鼠标移动到区域的一边,内容浮层发生小角度旋转,转向鼠标位置的方向一样(这里需要注意的是示例涉及X,Y两个方向)。

现在我们将这个模型从正中间剖开然后延Y轴旋转90度,我们来分步看看几种不同的情况:

情形一,没有内容层,眼睛直达背景:

情形二,有内容层,但内容层不跟随观察点变化:

情形三,有内容层,且内容层会根据观察点发生角度偏移:

至此,我们示例的静态模型基本上就展示完成了,唯一的区别在于,我们的案例中内容层的扭转角度并没达到与观察点始终垂直,不过也只是参数上的差异而已,下面我们通过一个完gif动画,看看内容层随观察点变化的全过程:

有了这个模型,我们实现示例的时候就轻松多了。

打码

第一步,背景层和内容层布局(以单个容器为例)

<div class="wrap" id="J_Wrap"><!-- 背景层 --><div class="bg"><img src="imgs/bg.png"></div><!-- 内容层 --><div class="up"><img src="imgs/text.png"></div>
</div>

然后通过CSS样式,将他们层叠起来,并设置观察点距背景的距离:

.wrap {position: relative;float: left;margin-top: 20px;margin-left: 20px;width: 400px;height: 600px;/* 观察点距离背景的距离为400像素,即图示中眼睛到黑色竖线的距离 */perspective: 400px;/* 默认眼睛的观察点在wrap的中心 */perspective-origin: 50% 50%;overflow: hidden;
}
.wrap .up {position: absolute;top: 0;left: 0;width: 100%;height: 100%;/** 内容层距背景层80像素,内容层距眼睛近,看起来会变大* 所以设置显示比例0.8,以保证内容显示完整*/transform: scale(.8) translateZ(80px);
}

第二步,分析鼠标移动过程中所需数据的计算公式:

我们先来看一个图例:

图示已然非常清晰,但是看起来还有很多未知数。我们知道在JS中,我们很容易获取到一个节点(容器)相对于浏览器可视区域左上角的相对坐标,所以[x1, y1]实为已知。而容器中心位置正是容器的x、y坐标分别加上容器自身宽高的一半,即[x0, y0]亦为已知。最后鼠标在移动过程中,我们可以通过事件对象本身轻松获取到鼠标相对于浏览器左上角的坐标,很显然[x2, y2]也可以得到,而尚不可知的[rx, ry],我可以在实际应用中为他设定较为合理的值,所以已知数据代入公式,最后dx1, dy1, rx0, ry0就很容易计算出来了。

第三步,理论结合实践,实践检验真理:

(function(){var c = [], // center: 鼠标move区域中心点坐标m = [], // mouseCoordinates: 鼠标当前位置坐标w = [], // wrapCoordinates: 鼠标move区域左上角坐标d = [3, 3]; // X/Y方向的最大扭转角度(deg)document.getElementById('J_Wrap').onmousemove = function(ev){ev.preventDefault();var _this = this, r, z;m[0] = ev.clientX + window.scrollX;m[1] = ev.clientY + window.scrollY;w[0] = _this.getBoundingClientRect().left + window.scrollX;w[1] = _this.getBoundingClientRect().top + window.scrollY;c[0] = w[0] + _this.offsetWidth / 2;c[1] = w[1] + _this.offsetHeight / 2;// rotate: 根据当前鼠标位置相对于区域中心位置百分比计算出当前X/Y方向的扭转角度(deg)r = [-(c[0] - m[0]) / (c[0] - w[0]) * d[0], (c[1] - m[1]) / (c[1] - w[1]) * d[1]];// perspectiveOrigin: 视觉观察点相对于鼠标move区域左上角的百分比(0-1)p = [0.5 + (c[0] - m[0]) / (c[0] - w[0]) * 0.5, 0.5 + (c[1] - m[1]) / (c[1] - w[1]) * 0.5];z = 80;_this.style['perspectiveOrigin'] = p[0] * 100 + '%' + ' ' + p[1] * 100 + '%';_this.getElementsByTagName('div')[1].style['transform'] = 'scale(.8) translateZ(' + Math.abs(z) + 'px) rotateX(' + r[1] + 'deg) rotateY(' + r[0] + 'deg)';};
})();

将数组r和数组p的计算过程与上图公式对比,是不是一模一样,而图例中位置的d数组,我们使用前已经将他指定为了[3, 3],当然你也可以根据你的喜好指定成你喜欢的数字,至此整个效果实现基本就完成了。

整理与封装

前面的代码虽然已经实现了功能,但是代码编写可谓极不规范:随意的变量命名、完全没考虑代码复用性,未考虑多实例情况,鼠标移出后显示效果未复原等等。所以基本不可能用于生产环境,我们还需要对它略作加工:

(function(window, $){var _default = {target: '.up',deg: [3, 3],translateZ: 80,scale: .8};$.fn.magicHover = function(cfg) {var config = $.extend({}, _default, cfg),center = [], // center: 鼠标move区域中心点坐标mouseCoord = [], // mouseCoordinates: 鼠标当前位置坐标wrapCoord = [], // wrapCoordinates: 鼠标move区域左上角坐标deg = config.deg; // X/Y方向的最大扭转角度(deg)return this.each(function(idx, wrap){$(wrap).on('mousemove', function(ev){ev.preventDefault();var _this = $(this), rotate;mouseCoord[0] = ev.clientX + $(window).scrollLeft();mouseCoord[1] = ev.clientY + $(window).scrollTop();wrapCoord[0] = _this.offset().left;wrapCoord[1] = _this.offset().top;center[0] = wrapCoord[0] + _this.width() / 2;center[1] = wrapCoord[1] + _this.height() / 2;// rotate: 根据当前鼠标位置相对于区域中心位置百分比计算出当前X/Y方向的扭转角度(deg)rotate = [-(center[0] - mouseCoord[0]) / (center[0] - wrapCoord[0]) * deg[0], (center[1] - mouseCoord[1]) / (center[1] - wrapCoord[1]) * deg[1]];// perspectiveOrigin: 视觉观察点相对于鼠标move区域左上角的百分比(0-1)perspectiveOrigin = [0.5 + (center[0] - mouseCoord[0]) / (center[0] - wrapCoord[0]) * 0.5, 0.5 + (center[1] - mouseCoord[1]) / (center[1] - wrapCoord[1]) * 0.5];_this.css('perspectiveOrigin', perspectiveOrigin[0] * 100 + '%' + ' ' + perspectiveOrigin[1] * 100 + '%');_this.find(config.target).css('transform', 'scale(' + config.scale + ') translateZ(' + Math.abs(config.translateZ) + 'px) rotateX(' + rotate[1] + 'deg) rotateY(' + rotate[0] + 'deg)');}).on('mouseout', function(ev){var _this = $(this);_this.css('perspectiveOrigin', '50% 50%');_this.find(config.target).css('transform', 'scale(' + config.scale + ') translateZ(' + Math.abs(config.translateZ) + 'px) rotateX(0) rotateY(0)');});});};
})(window, jQuery);

而最终调用的方式也非常简单:

$(function(){$('.wrap').magicHover({target: '.up',deg: [3, 3],translateZ: 80});
});

最后,有一个比较迷惑的点就是CSS3旋转(rotate)中的(rotateX、rotateY、rotateZ)是相对于坐标轴而言的,例使用rotateX时,实际是围绕X轴做旋转,变化的效果作用在Y方向上,其余同理,所以仔细看以上代码,你会发现在设置style的时候rotate中的x和y我刻意交换了位置。你可以试试修改deg和translateZ参数,对比一下浏览效果,更容易理解其中的原理!行啦,大功告成,今晚可以睡个安稳觉了~~

作者博客:百码山庄

转载于:https://my.oschina.net/mailzwj/blog/529691

CSS3中3D综合应用及分析相关推荐

  1. css3中3D变换的景深和灭点

    景深 概念 简单的理解,景深就是我们的肉眼距离显示器的距离,景深越大,元素离我们越远,效果就不好,在我们CSS3中,perspective用于激活一个3D空间,属性值就是景深大小(默认none无景深) ...

  2. css3中3D转换动画效果---transform: rotate3d(x,y,z,) 3D 旋转

    CSS3 允许您使用 3D 转换来对元素进行格式化. 转换属性 属性 描述 CSS transform 向元素应用 2D 或 3D 转换. 3 transform-origin 允许你改变被转换元素的 ...

  3. css33d图片轮播_1.Web前端之CSS3中3D立方体以及3D轮播图

    1.3D坐标系 3D坐标可以用左手来模拟,其中大拇指方向默认是X轴正方向,食指方向是Y轴正方向,中指方向是Z轴正方向.注意:当设置transform:rotateX(90deg)时,相当于将X轴转动9 ...

  4. 1.Web前端之CSS3中3D立方体以及3D轮播图

    1.3D坐标系 3D坐标可以用左手来模拟,其中大拇指方向默认是X轴正方向,食指方向是Y轴正方向,中指方向是Z轴正方向.注意:当设置transform:rotateX(90deg)时,相当于将X轴转动9 ...

  5. CSS -- CSS3中3D转换相关属性讲解(translate3d,rotate3d,perspective,transform-style)

    文章目录 3D转换 1 三维坐标系 2 3D移动 translate3d 3 透视 perspective 4 3D 旋转 rotate3d 5 3D旋转 rotate3d 6 3D呈现 transf ...

  6. CSS3 中3D转换--旋转正方体,滚动照片墙的写法

    首先给父元素加两个属性,把父元素变成3D空间. (1)transform-style:preserve-3d; (观察的场所 3D空间) (2)perspective:1000px;(近大远小–景深p ...

  7. css3中的3d元素

    景深 perspective(n)为 3D 转换元素定义透视视图 perspective的中文意思是:透视,视角. 没有透视定义,不成3D. 下图为透视的一张图: CSS3中3D transform的 ...

  8. CSS3中的2D和3D转换知识介绍

    一  2D转换 转换是CSS3中具有颠覆性的特征之一,可以实现元素的位移.旋转.变形.缩放,甚至支持矩阵方式,配合即将学习的过渡和动画知识,可以取代大量之前只能靠Flash才可以实现的效果. 1.移动 ...

  9. CSS3中的3D变换与简易立方体的制作

    大家好,这里是demo软件园,今天为大家分享的是css3中的3d变换. 我们首先要知道在浏览器中,X轴是从左到右,Y轴是从上到下,Z轴是从里到外.CSS的3d变换中,有以下属性: A.3D旋转: CS ...

最新文章

  1. ArcGIS API for Silverlight 入门学习笔记(三):基础地图实例
  2. 用一个创业故事串起操作系统原理(二)
  3. java编程笔记8 面向对象三 内部类
  4. android 文字控件闪烁
  5. discuz 二次开发文章
  6. PIC单片机入门_框架与存储器
  7. 增加mysql的sortbuffer_Mysql设置sort_buffer_size
  8. 这张磁盘有写保护_u盘被写保护怎么解除 磁盘被写保护怎么解除
  9. 如何使用windbg查看C#某个线程的栈大小 ?
  10. [ARC073C] Ball Coloring(贪心)
  11. PHP单选框实现的方法,jQuery简单实现遍历单选框的方法
  12. 牛客网刷题 --- 输入输出数据处理
  13. C语言课后习题(3)
  14. 大数据_Flink_数据处理_资源的分配和并行度测试---Flink工作笔记0013
  15. lintcode-87-删除二叉查找树的节点
  16. 自学了三个月的软件测试,从小白到自动化测试工程师,我是如何从零拿到大厂offer的
  17. mysql-备份和还原(普通还原和binlog还原)
  18. 售前工程师是做什么的?
  19. Sketch一站式设计开发工具 Dapollo插件 for mac v2.0.9破解版
  20. caffe源码解析by薛云峰

热门文章

  1. 小明用计算机算出58十35,人教版三年级数学下册第三四单元测试卷.docx
  2. 20200127:(leetcode)四数之和(动态图解)
  3. java 相同字符不连续_Java中字符串中连续相同字符去重方法
  4. Mysql数据库 自动增长 重新从0开始
  5. VB Listview导出到CSV文件函数
  6. 比CopyMemory还要快的函数SuperCopyMemory
  7. 二度整理交换机有感(续)
  8. 8种寻找机器学习数据集的方法 | 附数据集资源
  9. 谷歌CEO皮猜:我们想服务中国用户,但是没想好提供何种服务
  10. 数据载入过慢?这里有一份TensorFlow加速指南