页面点击特效源码解析

大家好,我是石璞东。

关注我的小伙伴都知道,我的个人网站从2018年年底开通之后,历经四次改版升级,由最初的酷炫到现如今的简洁大气,给大家看看我审美的变化过程吧:

网站变化过程

  • haha 1.0
    在这里插入图片描述

  • haha 2.0在这里插入图片描述

  • haha 3.0
    在这里插入图片描述

  • haha 4.0
    在这里插入图片描述

点击特效源代码分析

自从着手搭建以来,一心想着说要集成各方面优秀的开源资源,并将其融合在自己的网站中,让用户在学习知识的时候能有超乎其他网站平台的舒适体验,我也在一直奋力做这件事,在这一期中我们就说说 haha 2.0 中 点击特效 这回事。

在这里插入图片描述
我们简单来介绍一下:就是当用户点击操作时,会从用户点击处生成一个心形,让后慢慢向上移动,并且伴随着透明度的减小和面积的放大,最终消失。同样适用于PC端和移动端(手机、ipad等终端设备)

其实这个效果的实现,相信学过 JavaScript 的小伙伴稍微看下源码就会发现也没有很难。

咱们先不看我网站实现这个效果的源码,咱们先思考一个问题,如果要你实现一个效果:点击页面,出现的不是心形,而是出现一些关于 石璞东 的关键词,就像这样:
在这里插入图片描述
我们来说下思路:页面监听用户操作,当用户执行点击时,在用户当前点击的位置附近(具体位置涉及到用户群对于样式的要求)生成一个标签(我用的是span),里面包裹着对于博主的描述关键词,然后执行一系列动画效果,执行完毕后,移除此标签。

var a_idx = 0;
jQuery(document).ready(function($) {
	$("body").click(function(e) {
		var a = new Array("萌萌哒","帅气","阳光","八块腹肌","治愈系","无敌暖男","运动狂魔","软件开发","酷爱外语");
		var $i = $("<span/>").text(a[a_idx]);
//		        	a_idx = (a_idx + 1) % a.length;
        			a_idx = Math.round(Math.random()*a.length);
		var x = e.pageX,
		        y = e.pageY;
        $i.css({
			"z-index": 999999999999999999999999999999999999999999999999999999999999999999999,
			"top": y - 20,
			"left": x,
			"position": "absolute",
			"color":`rgba(${Math.random()*255},${Math.random()*255},${Math.random()*255},1)`
    	});
		$("body").append($i);
		$i.animate({
			"top": y - 180,
			"opacity": 0
		 },1500,function() {
		 	$i.remove();
		 });
		});
});

代码很简单,就不逐行解释了,这里说几个注意的点就行:

  1. 在使用的时候记着引入 jQuery 源代码;
  2. 代码中监听的是 body 元素内的所有内容,所以在使用的时候读者务必在 body 标签内部添加些内容,这样才能保证结果的正确显示。
    <p>石璞东好帅</p>
    <p>石璞东好帅</p>
    <p>石璞东好帅</p>
    <p>石璞东好帅</p>
    <p>石璞东好帅</p>
    <p>石璞东好帅</p>

第二个问题,来咱们说下我网站心形效果的事:

首先贴出源代码:

! function(e, t, a) {
	 //对当前页面由用户点击产生的心进行操作,若产生的心的透明度小于零了,则移除该元素,若不小于零,则该心继续向上移动,并慢慢放大
	function r() {
		for(var e = 0; e < n.length; e++) 
			n[e].alpha <= 0 ? (t.body.removeChild(n[e].el), n.splice(e, 1)) : (n[e].y--, n[e].scale += .004, 
			n[e].alpha -= .013, 
			n[e].el.style.cssText = "left:" + n[e].x + "px;top:" + n[e].y + "px;opacity:" + n[e].alpha + ";transform:scale(" + n[e].scale + "," + n[e].scale + ") rotate(45deg);background:" + n[e].color + ";z-index:99999");
		requestAnimationFrame(r)
	}
	//存放页面心的数组
	var n = [];
	//对于不同浏览器做兼容处理
	e.requestAnimationFrame =
		e.requestAnimationFrame || 
		e.webkitRequestAnimationFrame || 
		e.mozRequestAnimationFrame || 
		e.oRequestAnimationFrame || 
		e.msRequestAnimationFrame || 
		function(e) {
			setTimeout(e, 1e3 / 60)
	},
	//创建style标签并写入css样式
	function(e) {
		var a = t.createElement("style");
		a.type = "text/css";
		try {
			a.appendChild(t.createTextNode(e))
		} catch(t) {
			a.styleSheet.cssText = e
		}
		t.getElementsByTagName("head")[0].appendChild(a)
	}(".heart{width: 10px;height: 10px;position: fixed;background: #f00;transform: rotate(45deg);-webkit-transform: rotate(45deg);-moz-transform: rotate(45deg);}.heart:after,.heart:before{content: '';width: inherit;height: inherit;background: inherit;border-radius: 50%;-webkit-border-radius: 50%;-moz-border-radius: 50%;position: fixed;}.heart:after{top: -5px;}.heart:before{left: -5px;}"),
	//将用户点击操作产生的心push进n数组之内
	function() {
		var a = "function" == typeof e.onclick && e.onclick;
		e.onclick = function(e) {
			a && a(),
			function(e) {
				var a = t.createElement("div");
				a.className = "heart", 
				n.push({
					el: a,
					x: e.clientX - 5,
					y: e.clientY - 5,
					scale: 1,
					alpha: 1,
					color: "rgb(" + ~~(255 * Math.random()) + "," + ~~(255 * Math.random()) + "," + ~~(255 * Math.random()) + ")"
					}), 
					t.body.appendChild(a)
				}(e)
			}
		}(), 
	r()
}(window, document);

几个注意点:

  • 自执行函数的几种写法:

  • 几个API

    • requestAnimationFrame:接受一个回调函数作为参数,当浏览器下次要执行动画时会调用该函数执行动画;
    • createTextNode:接受字符串作为参数,并将其放入节点中。
  • 源代码中的写法:

    • 最外层是!function(e,t,a){/内层代码块/}(window,document)
    • 内层代码块中的部分通过 , 即逗号运算符,并列了四个函数:requestAnimationFrame、创建style标签并写入样式的函数、初始化并将产生的心push进数组的函数、r函数的调用。
      在这里插入图片描述

重点解释一下:

1. function(){/*code*/}()
   function fn(){/*code*/}()
   以上两种写法并不是自调用函数的正确写法,而且会报错的呢~
2. var fn ='aaa',function(a){alert(a)}(1)
   YY想出来该行代码的执行结果应该是弹出1,但是毫无意外的又报错了~
3. fn = 'aaa',function(a){alert(a)}(1)/*弹出1*/
   
   fn = function(a){alert(a)}(1),function(b){alert(b)(2)/*先弹1在弹2*/
   
   function r (){alert(1)}
   fn = function(a){alert(a)}(2),r()
   /*先弹2在弹1*/

了解了基础知识,我们接下来进行具体分析一下:

首先,对内部代码做下说明,根据函数功能将其分为5部分:

  1. function r(){/code/}:对当前页面由用户点击产生的心进行操作,若产生的心的透明度小于零了,则移除该元素,若不小于零,则该心继续向上移动,并慢慢放大;
  2. e.requestAnimationFrame = /code/, : 对于不同浏览器做兼容处理;
  3. e.requestAnimationFrame = function(e){/code/}() :创建style标签并写入css样式;
  4. e.requestAnimationFrame = function(){/code/}():初始化,并将用户点击操作产生的心push进n数组之内;
  5. r():简单的函数调用。

分别在如下图中位置打断点:
在这里插入图片描述

首先,里面是5个并列的函数,它们的执行效果等同于自执行函数的执行效果(但这不是自执行函数),其次 onclick 回调函数会监听用户的点击事件,当用户点击页面时,函数会进入39行的断点处,然后逐步执行并初始化页面中原始的心形,执行至51行,初始化完毕,后续执行r函数,根据当前的心形的透明度是否小于0决定该心形是否需要从当前页面移除。

其实function r(){/code/}这个函数有一点递归函数的意思:当第一次执行全部代码的时候,r函数会被初步调用,之后进入r函数内部逐行执行代码,只要当前页面中有心形元素,即数组n.length>0,慢慢向上移动并且伴随着面积的增大,当且仅当该当前元素的透明度小于0时,才会从数组中移除该元素,此时跳出for循环,进而执行requestAnimationFrame函数,该函数将r函数作为参数,无限循环下去。

写在最后

为方便读者了解更为详细的信息,我为小伙伴们提供了三个我的官方渠道:

  • hahaCoder(微信公众号)
  • hahaAI(微信小程序)
  • hahaWebsite. (个人网站)
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

hahaCoderX

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值