最近在学习TS,所以将去年写的鼠标移动淡入淡出Canvas小球效果_特炫又以ts的形式再重新写一遍,让自己记得更牢固。
从下面的小案例中可以学到
1.ts中的数据类型 2.泛型的定义 3.函数的定义 4.接口的定义 5.类的定义、类实现接口 6.类作为接口的使用 7.枚举以及枚举的特点
按照代码的顺序展开介绍:
首先我们需要准备一个html,我们引入一个js文件(这个js文件为ts文件转义之后的)。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>小球淡入淡出TS</title>
<style>
html,
body {
width: 100%;
height: 100%;
}
canvas{
background: black;
}
</style>
</head>
<body>
<canvas id="canvas" width="100%" height="100%"></canvas>
<script src="./ts1.js"></script>
</body>
上面主要做的是引入js,创建一个canvas元素,给定宽高和默认的背景颜色。
下面我们开始书写ts文件:
1.获取元素:
let canvas: HTMLCanvasElement = <HTMLCanvasElement>(
document.getElementById("canvas")
);
window.onresize = canvasOnresize;
function canvasOnresize(): void {
canvas.width = document.getElementsByTagName("body")[0].clientWidth;
canvas.height = document.getElementsByTagName("body")[0].clientHeight;
}
canvasOnresize();
上面做的就是初始化操作,获取元素,将onresize事件重新,为了canvas大小可以随浏览器client大小不断变化。
2.创建小球的类:
let ctx = canvas.getContext("2d");
enum colorList {
"red"=2,
"green",
"yellow",
"blue",
"black",
"#ccc"
}
interface BallInterFace {
x: number;
y: number;
color: string;
xv: number;
yv: number;
Alpha1: number;
Alpha2: number;
update: () => void;
move: () => void;
mathRandom: (a: number, b: number) => void;
}
class Ball implements BallInterFace {
x: number;
y: number;
color: string;
xv: number;
yv: number;
Alpha1: number;
Alpha2: number;
constructor(x: number, y: number) {
this.x = x;
this.y = y;
this.color = colorList[Math.floor(this.mathRandom(2, 8))];
this.xv = this.mathRandom(-5, 5);
this.yv = this.mathRandom(-5, 5);
this.Alpha1 = 1;
this.Alpha2 = 0.85;
}
update = function(): void {
ctx.save();
ctx.beginPath();
ctx.fillStyle = this.color;
ctx.arc(this.x, this.y, 30, 0, Math.PI * 2, false);
ctx.fill();
ctx.closePath();
};
move = function(): void {
this.Alpha1 *= this.Alpha2;
ctx.globalAlpha = this.Alpha1;
this.x += this.xv;
this.y += this.yv;
};
mathRandom = function(min: number, max: number): number {
return (max - min) * Math.random() + min;
};
}
😊上面使用到了枚举 enum,用来获取小球的颜色。 枚举可以参考这篇文章:typeScript进阶(12)_枚举类型 🤔上面使用到了接口,来定义类的形状。 可以参考这两篇文章:typeScript基础(5)_对象的类型-interfaces接口、typeScript进阶(13)_类与注意事项(八项特性)
3.事件动画:
let ballList: Array<Ball> = [];
canvas.addEventListener("mousemove", function(e) {
ballList.push(new Ball(e.clientX, e.clientY));
});
changeBall();
function changeBall(): void {
ctx.clearRect(0, 0, canvas.width, canvas.height);
if (ballList.length > 100) {
ballList.splice(1);
}
ballList.map(item => {
item.update();
item.move();
});
requestAnimationFrame(changeBall);
}
上面主要做的事情是: 将鼠标移动的点位收集,并创建Ball实例,定时移动位置。
🤣上面使用到泛型:let ballList: Array<Ball> = []; 这里将Ball作为了一种类型;是ts中类的一种特性。 泛型可以参考这篇文章:typeScript进阶(14)_泛型和注意事项
总体思路就是:
1.获取canvas元素; 2.使用canvas画笔实现生成小球的方法; 3.将小球的属性和方法在类中定义好; 4.通过鼠标移动事件捕捉实践对象中的鼠标坐标; 5.鼠标坐标作为每一个新生成小球的坐标,然后随机向各个方向不同速度移动,由x方向和y方向的数值控制,随后改变的就是透明度; 6.使用window自带的动画方法进行循环函数。控制小球数量,不然多的话会造成页面卡顿。 😃上面的Ball类,我们也可以通过抽象类中的抽象方法来约束这个类,而不是直接使用interFace接口, 因为抽象类中的抽象方法在派生类中是必须实现的 。 到此就实现了上面的动画效果。
ts部分全部代码
let canvas: HTMLCanvasElement = <HTMLCanvasElement>(
document.getElementById("canvas")
);
window.onresize = canvasOnresize;
function canvasOnresize(): void {
canvas.width = document.getElementsByTagName("body")[0].clientWidth;
canvas.height = document.getElementsByTagName("body")[0].clientHeight;
}
canvasOnresize();
let ctx = canvas.getContext("2d");
enum colorList {
"red"=2,
"green",
"yellow",
"blue",
"black",
"#ccc"
}
interface BallInterFace {
x: number;
y: number;
color: string;
xv: number;
yv: number;
Alpha1: number;
Alpha2: number;
update: () => void;
move: () => void;
mathRandom: (a: number, b: number) => void;
}
class Ball implements BallInterFace {
x: number;
y: number;
color: string;
xv: number;
yv: number;
Alpha1: number;
Alpha2: number;
constructor(x: number, y: number) {
this.x = x;
this.y = y;
this.color = colorList[Math.floor(this.mathRandom(2, 8))];
this.xv = this.mathRandom(-5, 5);
this.yv = this.mathRandom(-5, 5);
this.Alpha1 = 1;
this.Alpha2 = 0.85;
}
update = function(): void {
ctx.save();
ctx.beginPath();
ctx.fillStyle = this.color;
ctx.arc(this.x, this.y, 30, 0, Math.PI * 2, false);
ctx.fill();
ctx.closePath();
};
move = function(): void {
this.Alpha1 *= this.Alpha2;
ctx.globalAlpha = this.Alpha1;
this.x += this.xv;
this.y += this.yv;
};
mathRandom = function(min: number, max: number): number {
return (max - min) * Math.random() + min;
};
}
let ballList: Array<Ball> = [];
canvas.addEventListener("mousemove", function(e) {
ballList.push(new Ball(e.clientX, e.clientY));
});
changeBall();
function changeBall(): void {
ctx.clearRect(0, 0, canvas.width, canvas.height);
if (ballList.length > 100) {
ballList.splice(1);
}
ballList.map(item => {
item.update();
item.move();
});
requestAnimationFrame(changeBall);
}
六卿
见贤思齐焉,见不贤内自省
个人见解,不对之处还请斧正。
|