前言
Hello,掘友们好!又是一年新春之际,祝福大家兔年快乐!给大家介绍一个有趣的动效(兼容 IE),页面右下角有一只搞怪的兔子,鼠标在页面中悬停时,兔子会跟着做出不同的动作和表情。然后可以在页面中任意位置(离兔子太近不能发射,会伤到兔子😆)点击鼠标,将从兔子眼睛👀里发射炮弹,随之击中爆破的是你的霉 运、压 力、贫 穷、疾 病😮💨。
实现
- 定义一个随机文本块。 - 1 - <p id="p1"></p> 
- 定义兔子的构造函数。 - 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19- function HoverRabbit() { 
 this.explodeImage = new Image();
 this.explodeImage.src = "img/explode.png";
 for (var i = 1; i <= 6; i++) {
 this.images[i] = new Image();
 this.images[i].src = "img/s" + i + ".png";
 }
 if (typeof(CanvasGradient) != 'undefined') {
 this.canvas = document.createElement("canvas");
 this.canvas.width = screen.width + 100;
 this.canvas.height = screen.height;
 this.canvas.style.position = 'absolute';
 this.canvas.style.left = '0px';
 this.canvas.style.top = '0px';
 this.canvas.style.display = 'none';
 document.body.appendChild(this.canvas);
 this.canvas.style.position = 'fixed';
 }
 }
- 定义兔子原型的属性和方法。 - 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
 100
 101
 102
 103
 104
 105
 106
 107
 108
 109
 110
 111
 112
 113
 114
 115
 116
 117
 118
 119
 120
 121
 122
 123
 124
 125
 126
 127
 128
 129
 130
 131- HoverRabbit.prototype = { 
 images: [],
 explodeImage: null,
 eyePositions: [],
 current: 1,
 frame: 1,
 canvas: null,
 interval: null,
 start: function() {
 var me = this;
 this.eyePositions[1] = {
 eye1x: 123,
 eye1y: 47,
 eye2x: 104,
 eye2y: 53
 };
 this.eyePositions[2] = {
 eye1x: 120,
 eye1y: 50,
 eye2x: 101,
 eye2y: 54
 };
 this.eyePositions[3] = {
 eye1x: 119,
 eye1y: 54,
 eye2x: 97,
 eye2y: 56
 };
 this.eyePositions[4] = {
 eye1x: 112,
 eye1y: 61,
 eye2x: 90,
 eye2y: 61
 };
 this.eyePositions[5] = {
 eye1x: 105,
 eye1y: 64,
 eye2x: 85,
 eye2y: 61
 };
 this.eyePositions[6] = {
 eye1x: 98,
 eye1y: 68,
 eye2x: 79,
 eye2y: 56
 };
 document.onmousemove = function(e) {
 me.onmousemove(e);
 }
 if (this.canvas) {
 document.addEventListener("click", function(e) {
 me.ondblclick(e);
 });
 }
 },
 onmousemove: function(e) {
 var event = e || window.event;
 var deg = Math.abs(screen.height - event.screenY) / (Math.abs(screen.width - event.screenX) + 1);
 var n = 1;
 if (deg > 2) n = 6;
 else if (deg > 1.4) n = 5;
 else if (deg > 0.7) n = 4;
 else if (deg > 0.45) n = 3;
 else if (deg > 0.2) n = 2;
 this.deg = n;
 if (this.current != n) {
 document.body.style.backgroundImage = "url(" + this.images[n].src + ")";
 this.current = n;
 }
 },
 drawBomb: function(ctxt, n, x, y) {
 var sx = 64 * (n % 4);
 var sy = 64 * (Math.floor(n / 4));
 ctxt.drawImage(this.explodeImage, sx, sy, 64, 64, x - 32, y - 32, 64, 64);
 },
 ondblclick: function(e) {
 if (this.canvas.style.display != 'none') return;
 var me = this;
 if (e.clientX > window.innerWidth - 200 && e.clientY > window.innerHeight - 200) return;
 var ctxt = this.canvas.getContext("2d");
 this.frame = 1;
 this.interval = setInterval(function(e2) {
 ctxt.clearRect(0, 0, me.canvas.width, me.canvas.height);
 switch (me.frame) {
 case 1:
 ctxt.strokeStyle = 'rgba(247,166,71,1)';
 me.canvas.style.display = 'block';
 case 2:
 if (me.frame == 2) {
 ctxt.strokeStyle = 'rgba(247,166,71,0.5)';
 me.drawBomb(ctxt, 0, e.clientX, e.clientY);
 }
 case 3:
 if (me.frame == 3) {
 ctxt.strokeStyle = 'rgba(247,166,71,0.1)';
 me.drawBomb(ctxt, 1, e.clientX, e.clientY);
 }
 var eye1x = window.innerWidth - me.eyePositions[me.current].eye1x;
 var eye1y = window.innerHeight - me.eyePositions[me.current].eye1y;
 ctxt.lineWidth = 3;
 ctxt.beginPath();
 ctxt.moveTo(eye1x, eye1y);
 ctxt.lineTo(e.clientX, e.clientY);
 ctxt.stroke();
 var eye2x = window.innerWidth - me.eyePositions[me.current].eye2x;
 var eye2y = window.innerHeight - me.eyePositions[me.current].eye2y;
 ctxt.beginPath();
 ctxt.moveTo(eye2x, eye2y);
 ctxt.lineTo(e.clientX, e.clientY);
 p1.textContent = ['霉 运', '压 力', '贫 穷', '疾 病'][Math.floor(Math.random() * 4)];
 p1.style.display = 'block';
 p1.style.transform = 'rotate(' + (-150 + me.deg * 30) + 'deg)';
 p1.style.left = e.clientX - 30 + 'px';
 p1.style.top = e.clientY - 30 + 'px';
 fade(p1);
 ctxt.stroke();
 break;
 case 4:
 me.drawBomb(ctxt, 2, e.clientX, e.clientY);
 break;
 case 14:
 me.canvas.style.display = 'none';
 window.clearInterval(me.interval);
 break;
 default:
 me.drawBomb(ctxt, me.frame - 2, e.clientX, e.clientY);
 }
 me.frame++;
 }, 50);
 }
 };- 各个属性和方法说明: 
- images - 兔子不同的动作的图片数组。
- explodeImage - 炮弹图片元素。
- eyePositions - 兔子眼睛位置的数组。
- current - 整型数字,兔子当前动作的指针。
- frame - 整型数字,发射炮弹动画的帧数指针。
- canvas - 画布元素。
- interval - 发射炮弹动画时间间隔定时器的 interval ID。
- start - 启动页面交互的方法,在这里初始化了兔子眼睛位置的数组数据,绑定页面鼠标移动事件、点击事件。
- onmousemove - 定义页面鼠标移动的实现方法。
- ondblclick - 定义页面鼠标点击的实现方法。
- drawBomb - 定义绘制和更新炮弹动画的方法。
- 定义文字淡出的动画。 - 1 
 2
 3
 4
 5
 6
 7- function fade(e) { 
 var s = e.style;
 s.opacity = 1;
 (function hide() {
 (s.opacity -= .01) < 0 ? s.display = "none" : requestAnimationFrame(hide);
 })();
 }
- 创建兔子对象,调用启动交互方法。 - 1 
 2- var s = new HoverRabbit(); 
 s.start();
码上掘金
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 张坤的博客!
 评论