过年KPI冲到了最后一篇,居然是个技术文,居然我这么菜的水平都要搞技术文了!昨天大型摸鱼一整晚,完成了这个点击撒红包动画。没错!这就是本博客现在最需要的功能。

从网址 notes.midofnowhere.link 进来的朋友可能已经看到了,现在点击网页就会从点击出放出一些红包灯笼小炮仗,没看到吗?再点一下! 这都是我抄来的,用css和js实现,非常简单,如果看到这里你也想要,请直接移步codepen 跟我一样抄上就好,接下来的内容只是我再转抄一遍。

技术力背景

本博客网站是用 Hugo 做的,因为只有这个工具我用得明白。具体Hugo是怎么生成网页的我不懂,但是我能碰到的部分除了写作时编辑的markdown, 就是单纯的html/css/js. 对这几部分我都有非常非常非常浅显的了解,css只会用plain css, 预处理完全不懂,scss我都看不懂。js基本上只会照着抄。好了铺垫就到这里,您可以另请高明或者陪伴笔者一起抄下去。

实现效果

gif image

要实现的就是这样一个简单的效果,在点击网页 body时,从鼠标或触摸点击处绽放开一些小图案。因此需要做的就是:

  1. event listner 记录点击并触发动画
  2. 动画开始:以点击处为中心产生一个装满图案的 div
  3. 动画过程:控制小图案的数量、品种、行动轨迹
  4. 动画结束:div 消失

开始抄代码!

js

这里用到jQuery.

// click event listener
$('body').on('click', function(e) {
  explode(e.pageX, e.pageY);
})

好了上一节的第一步已经完成了,那么这个explode函数里是啥样的呢?

// explosion construction
function explode(x, y) {
// 决定就放15个红包,你想多放点也可以
  var particles = 15,
  
    // explosion container and its reference to be able to delete it on animation end
    explosion = $('<div class="explosion"></div>');

  // put the explosion container into the body to be able to get it's size
  $('body').append(explosion);

  // position the container to be centered on click
  explosion.css('left', x - explosion.width() / 2);
  explosion.css('top', y - explosion.height() / 2);

  for (var i = 0; i < particles; i++) {
    // positioning x,y of the particle on the circle (little randomized radius)
    // 以稍微不规则的圆形播撒红包
    var x = (explosion.width() / 2) + rand(80, 150) * Math.cos(2 * Math.PI * i / rand(particles - 10, particles + 10)),
      y = (explosion.height() / 2) + rand(80, 150) * Math.sin(2 * Math.PI * i / rand(particles - 10, particles + 10));
        // particle element creation (could be anything other than div)
        // 此处我用了网上下载的svg图,随机产生三种图案
			var shapes = ['<img src="chinese-new-year-lamp-svgrepo-com.svg" alt="cny lamp"/>', '<img src="envelope-chinese-new-year-svgrepo-com.svg" alt="evelope"/>', '<img src="fireworks-svgrepo-com.svg" alt="firework"/>']
			var getShape = Math.floor(Math.random() * shapes.length);
      // 往div中添加图案
      var elm = $('<div class="particle" style="' +
        'top: ' + y + 'px; ' +
        'left: ' + x + 'px">' + shapes[getShape] + '</div>');

    if (i == 0) { // no need to add the listener on all generated elements
      // css3 animation end detection
      elm.one('webkitAnimationEnd oanimationend msAnimationEnd animationend', function(e) {
        explosion.remove(); 
        // remove this explosion container when animation ended
      });
    }
    explosion.append(elm);
  }
}

其中 shapes 可以是你喜欢的任何东西,比如说 <i> element , 或者在css里直接画圆形方形都可以。我这里用到的是网页矢量图 svg, 这个图如果用 text editor 打开看起来是这样的:

<?xml version="1.0" encoding="iso-8859-1"?>
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
<svg height="25px" width="25px" version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" 
	 viewBox="0 0 512 512" xml:space="preserve">
<path style="fill:#FF4B4B;" d="M363.705,6.505C362.658,2.665,359.169,0,355.189,0H192.122c-3.98,0-7.469,2.665-8.516,6.505
	l-24.71,90.599h229.517L363.705,6.505z"/>
<path style="fill:#C83741;" d="M379.586,88.276H167.724c-4.875,0-8.828,3.953-8.828,8.828v370.759c0,4.875,3.953,8.828,8.828,8.828
	h211.862c4.875,0,8.828-3.953,8.828-8.828V97.103C388.414,92.228,384.462,88.276,379.586,88.276z"/>
<path style="fill:#FF4B4B;" d="M344.276,123.586H132.414c-4.875,0-8.828,3.953-8.828,8.828v370.759c0,4.875,3.953,8.828,8.828,8.828
	h211.862c4.875,0,8.828-3.953,8.828-8.828V132.414C353.103,127.539,349.152,123.586,344.276,123.586z"/>
<g>
	<path style="fill:#FFCF65;" d="M238.345,397.241c-43.81,0-79.448-35.638-79.448-79.448s35.638-79.448,79.448-79.448
		s79.448,35.638,79.448,79.448S282.155,397.241,238.345,397.241z M238.345,256c-34.069,0-61.793,27.724-61.793,61.793
		s27.724,61.793,61.793,61.793s61.793-27.724,61.793-61.793S272.414,256,238.345,256z"/>
	<circle style="fill:#FFCF65;" cx="238.345" cy="317.793" r="35.31"/>
	<path style="fill:#FFCF65;" d="M238.345,432.552c-24.181,0-47.345-7.509-67-21.716c-3.948-2.862-4.836-8.38-1.983-12.328
		c2.845-3.957,8.371-4.836,12.328-1.983c16.621,12.019,36.216,18.371,56.655,18.371c20.423,0,40.009-6.345,56.638-18.345
		c3.939-2.862,9.465-1.974,12.319,1.992c2.854,3.948,1.965,9.465-1.992,12.319C285.664,425.053,262.509,432.552,238.345,432.552z"/>
	<path style="fill:#FFCF65;" d="M300.164,240.733c-1.793,0-3.604-0.543-5.164-1.673c-16.62-12.017-36.215-18.37-56.655-18.37
		c-20.431,0-40.009,6.345-56.621,18.345c-3.975,2.854-9.483,1.965-12.328-1.983c-2.854-3.957-1.965-9.474,1.983-12.328
		c19.647-14.189,42.803-21.689,66.966-21.689c24.181,0,47.345,7.509,67,21.716c3.948,2.862,4.836,8.38,1.983,12.328
		C305.603,239.466,302.905,240.733,300.164,240.733z"/>
</g>
</svg>

这些数字就是每个节点的坐标,如果你把这些复制到写字板里然后保存成 firecrack.svg, 然后再用浏览器打开,就可以看到图片了。用这个格式的好处显然一是矢量图,二是可以直接在 svg class 里修改图片的尺寸和颜色。

css

接下来在css文件里添加 .explosion 的样式:

.explosion {
  position: absolute;
  width: 600px;
  height: 600px;
  pointer-events: none;
}
.explosion .particle {
  position: absolute;
  animation: pop 1s reverse forwards;
}

@keyframes pop {
  from {
    opacity: 0;
  }
  to {
    top: 50%;
    left: 50%;
    opacity: 1;
  }
}

第一部分是整个 explosion div 的大小,当然啦总不能无限飞满整个页面。第二部分是动画效果,用到了关键帧,我不懂,直接抄!

链接到html文件里

如果你是单独写一个html, 那就直接链接css/js就好了,但是我用的是Hugo,所以要找一找文件放哪里。

  1. css 直接加到自定义 css 文件里了,因为这种节日气氛过段时间就会不用了,也需要方便删除啊!
  2. js 保存成一个文件比如说 animation.js, 我放在了static文件夹里面。
  3. 在你的模板里找到链接 stylesheets 和 script 的地方,一般在 /layout/partials/head.html/layout/partials/foot.html 这种地方。
  • 总的来说请参考Hugo和主题文档

参考阅读

  1. explosion effect codepen
  2. star and diamond button animation
  3. Hugo lookup order

what else had happened

  • 取消了抬头字体消失特效,搞不懂去年本人的审美到底咋回事
  • 修复了buy me a coffee链接,暗示现在可以顺利打钱
  • 修改了permalink为英文,之前分享的几篇文章可能链接会出问题,不管了,爱看看不爱看拉倒。
  • rss feed改为了全文,可以在您喜欢的rss reader中阅读全文,不再需要特地点进来看我马马虎虎的网页

todo

  • 收拾分类和标签命名,怎么被我搞得这么混乱?
  • 换个新鲜一点的头图
  • 起个中文名,目前的备选是“茫茫居”
  • 研究一下markdown的更多新鲜玩法,比如说高亮和隐藏
  • 评论区的管理账号密码我忘了(……)考虑换一个服务

Comments