思路
- 跟
渡一袁老师
学的 canvas
中文字是使用filltext(text,x,y)
进行绘制的,我们需要搞定这些参数就可以绘制出来。- 先设定一个
fontSize
为文字大小,列宽columnWidth =fontSize
,可以用来计算绘制多少列
以及x坐标
,计算列数可以用画布宽度/列宽
,假设fontSize=20
例如:
列数 = 画布宽度 / 列宽
columnCount = Math.floor(width/columnWidth)
索引 0 1 2 3 4 5 列数 第一列 第二列 第三列 第四列 第五列 第六列 x坐标 0 20 40 60 80 100
可以看出每一列的
x=i*fontSize
- 如何计算
y坐标
,可以用一个数组来记录列下一个文字
,例如:
[0,0,0]
是指当前所有列绘制了0
个文字。
[3,4,7]
是指第1列绘制了3个文字
,第2列绘制了4个文字
,第3列绘制了7个文字
怎么算呢?看下面这个表
记录的第n个文字 | 列 | y坐标 |
---|---|---|
0 | l | 20 |
1 | ; | 40 |
2 | k | 60 |
3 | k | 80 |
4 | f | 100 |
5 | s | 120 |
6 | m | 140 |
7 | n | 160 |
现在可以看出
y坐标=(下一个文字+1)*fontSize
因为canvas
的y
不是看原点是看基线
,可以理解为y
在字母的下面。
- 每次绘制之前要加上一个蒙层,以实现慢慢变淡的效果
效果
代码
<template>
<canvas id="bg"></canvas>
</template>
<script setup lang="ts">
import { onMounted, onUnmounted, ref } from 'vue'
const timer = ref<number | undefined>(undefined)
function init() {
// 获取canvas元素
const cvs: HTMLCanvasElement = document.getElementById('bg') as HTMLCanvasElement
// 获取窗口尺寸
const width = window.innerWidth * devicePixelRatio,
height = window.innerHeight * devicePixelRatio
// 设置canvas尺寸
cvs.width = width
cvs.height = height
// 获取绘制上下文
const ctx = cvs.getContext('2d')
// 字体大小
const fontSize = 20 * devicePixelRatio
// 列宽
const columnWidth = fontSize
// 列数
const columnCount = Math.floor(width / columnWidth)
// 每一列下一个文字是第几个文字
const nextChar = new Array(columnCount).fill(0)
function draw() {
// 蒙层
ctx!.fillStyle = 'rgba(240,240,240,0.1)'
ctx!.fillRect(0, 0, width, height)
for (let i = 0; i < columnCount; i++) {
// 画一个字符
// 颜色,字体,字符,位置
ctx!.fillStyle = getRandomColor()
const char = getRandomChar()
ctx!.font = `${fontSize}px "Roboto Mono"`
const x = i * fontSize
const s = nextChar[i]
const y = (s + 1) * fontSize
ctx!.fillText(char, x, y)
if (y > height && Math.random() > 0.99) {
nextChar[i] = 0
} else {
nextChar[i]++
}
}
}
draw()
timer.value = setInterval(draw, 100)
}
// 随机颜色
function getRandomColor() {
return '#' + Math.random().toString(16).slice(2, 8)
}
// 随机文字
function getRandomChar() {
const str = 'dfdfadfgfadgafdg15561561'
return str[Math.floor(Math.random() * str.length)]
}
onMounted(init)
onUnmounted(() => {
clearInterval(timer.value)
})
</script>