最近在学习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.获取元素:
/**
* ts实现 小球单独淡出
*/
// 获取canvas标签
let canvas: HTMLCanvasElement = <HTMLCanvasElement>(
document.getElementById("canvas")
);
window.onresize = canvasOnresize;
//页面大小改变 canvans大小改变
function canvasOnresize(): void {
canvas.width = document.getElementsByTagName("body")[0].clientWidth;
canvas.height = document.getElementsByTagName("body")[0].clientHeight;
}
//初始化canvas的高度 宽度 跟随页面的大小
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; //x轴的分散速度
yv: number; //y轴的分散速度
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; //x轴的分散速度
yv: number; //y轴的分散速度
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.事件动画:
//装Ball对象的数组
let ballList: Array<Ball> = [];
// canvas 2 鼠标移动
canvas.addEventListener("mousemove", function(e) {
ballList.push(new Ball(e.clientX, e.clientY));
});
//1 触发事件
changeBall();
function changeBall(): void {
ctx.clearRect(0, 0, canvas.width, canvas.height);
// 最多共存100个小球
if (ballList.length > 100) {
ballList.splice(1);
}
//循环Ball实例上方法
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部分全部代码
/*
* @Descripttion:
* @version:
* @Author: ZhangJunQing
* @Date: 2022-03-08 14:54:03
* @LastEditors: ZhangJunQing
* @LastEditTime: 2022-04-08 15:33:16
*/
/**
* ts实现 小球单独淡出
*/
// 获取canvas标签
let canvas: HTMLCanvasElement = <HTMLCanvasElement>(
document.getElementById("canvas")
);
window.onresize = canvasOnresize;
//页面大小改变 canvans大小改变
function canvasOnresize(): void {
canvas.width = document.getElementsByTagName("body")[0].clientWidth;
canvas.height = document.getElementsByTagName("body")[0].clientHeight;
}
//初始化canvas的高度 宽度 跟随页面的大小
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; //x轴的分散速度
yv: number; //y轴的分散速度
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; //x轴的分散速度
yv: number; //y轴的分散速度
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;
};
}
//装Ball对象的数组
let ballList: Array<Ball> = [];
// canvas 2 鼠标移动
canvas.addEventListener("mousemove", function(e) {
ballList.push(new Ball(e.clientX, e.clientY));
});
//1 触发事件
changeBall();
function changeBall(): void {
ctx.clearRect(0, 0, canvas.width, canvas.height);
// 最多共存100个小球
if (ballList.length > 100) {
ballList.splice(1);
}
//循环Ball实例上方法
ballList.map(item => {
item.update();
item.move();
});
//按照电脑最优状态执行定动画效果
requestAnimationFrame(changeBall);
}
六卿
见贤思齐焉,见不贤内自省