前言
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
19function 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
131HoverRabbit.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
7function fade(e) {
var s = e.style;
s.opacity = 1;
(function hide() {
(s.opacity -= .01) < 0 ? s.display = "none" : requestAnimationFrame(hide);
})();
}创建兔子对象,调用启动交互方法。
1
2var s = new HoverRabbit();
s.start();
码上掘金
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 张坤的博客!
评论