首页 > 其他分享 >日常总结:Vue实现一个炫酷的代码瀑布流背景

日常总结:Vue实现一个炫酷的代码瀑布流背景

时间:2022-12-19 14:03:38浏览次数:42  
标签:Vue newCtx ctx HEIGHT WIDTH 瀑布 codes let 炫酷


先看一下效果:

日常总结:Vue实现一个炫酷的代码瀑布流背景_ci

代码奉上:

<template>
<canvas id="canvas" />
</template>

<script>
export default {
name: "BackCanvas",
props: {
height: {
type: Number,
default: 500
}
},
data() {
return {
settings: {
COL_WIDTH: 15,
COL_HEIGHT: 15,
// 速度参数 最小值:4 - 最大值:8
VELOCITY_PARAMS: {
min: 3,
max: 8
},
// 代码长度参数 最小值 20 - 最大值 40
CODE_LENGTH_PARAMS: {
min: 20,
max: 40
}
},
animation: null,
c: null,
ctx: null,
lineC: null,
ctx2: null,
WIDTH: window.innerWidth,
HEIGHT: window.innerHeight,
COLUMNS: null,
canvii: [],
// font from here https://www.dafont.com/matrix-code-nfi.font
font: '24px matrix-code',
letters: ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'this', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '$', '+', '-', '*', '/', '=', '%', '"', '\'', '#', '&', '_', '(', ')', ',', '.', ';', ':', '?', '!', '\\', '|', '{', '}', '<', '>', '[', ']', '^', '~'],
codes: [],
createCodeLoop: null,
codesCounter: 0
}
},
mounted() {
this.init();
},
methods: {
init () {
this.c = document.getElementById( 'canvas' );
this.ctx = this.c.getContext( '2d' );
this.c.width = this.WIDTH;
this.c.height = this.HEIGHT;

this.ctx.shadowBlur = 0;
this.ctx.fillStyle = '#000';
this.ctx.fillRect(0, 0, this.WIDTH, this.HEIGHT);
this.ctx.font = this.font;

this.COLUMNS = Math.ceil(this.WIDTH / this.settings.COL_WIDTH);

for (let i = 0; i < this.COLUMNS; i++) {
this.codes[i] = [];
this.codes[i][0] = {
'open': true,
'position': {'x': 0, 'y': 0},
'strength': 0
};
}

this.loop();

this.createLines();

this.createCode();

window.onresize = function () {
window.cancelAnimationFrame(this.animation);
this.animation = null;
this.ctx.clearRect(0, 0, this.WIDTH, this.HEIGHT);
this.codesCounter = 0;

this.ctx2.clearRect(0, 0, this.WIDTH, this.HEIGHT);

this.WIDTH = window.innerWidth;
this.HEIGHT = window.innerHeight;
this.init();
};
},
loop () {
this.animation = requestAnimationFrame( () => { this.loop(); } );
this.draw();
},
draw () {
let velocity, height, x, y, c, ctx;
// slow fade BG colour
this.ctx.shadowColor = 'rgba(0, 0, 0, 0.5)';
this.ctx.fillStyle = 'rgba(0, 0, 0, 0.5)';
this.ctx.fillRect(0, 0, this.WIDTH, this.HEIGHT);
this.ctx.globalCompositeOperation = 'source-over';
for (let i = 0; i < this.COLUMNS; i++) {
if (this.codes[i][0].canvas) {
velocity = this.codes[i][0].velocity;
height = this.codes[i][0].canvas.height;
x = this.codes[i][0].position.x;
y = this.codes[i][0].position.y - height;
c = this.codes[i][0].canvas;
ctx = c.getContext('2d');

this.ctx.drawImage(c, x, y, this.settings.COL_WIDTH, height);

if ((this.codes[i][0].position.y - height) < this.HEIGHT){
this.codes[i][0].position.y += velocity;
} else {
this.codes[i][0].position.y = 0;
}
}
}
},
createCode () {
if (this.codesCounter > this.COLUMNS) {
clearTimeout(this.createCodeLoop);
return;
}
let randomInterval = this.randomFromInterval(0, 100);
let column = this.assignColumn();
if (column) {
let codeLength = this.randomFromInterval(this.settings.CODE_LENGTH_PARAMS.min, this.settings.CODE_LENGTH_PARAMS.max);
let codeVelocity = (Math.random() * (this.settings.VELOCITY_PARAMS.max - this.settings.VELOCITY_PARAMS.min)) + this.settings.VELOCITY_PARAMS.min;
let lettersLength = this.letters.length;

this.codes[column][0].position = {'x': (column * this.settings.COL_WIDTH), 'y': 0};
this.codes[column][0].velocity = codeVelocity;
this.codes[column][0].strength = this.codes[column][0].velocity / this.settings.VELOCITY_PARAMS.max;

for (let i = 1; i <= codeLength; i++) {
let newLetter = this.randomFromInterval(0, (lettersLength - 1));
this.codes[column][i] = this.letters[newLetter];
}

this.createCanvii(column);

this.codesCounter++;
}
this.createCodeLoop = setTimeout(this.createCode, randomInterval);

},
createCanvii (i) {
let codeLen = this.codes[i].length - 1;
let canvHeight = codeLen * this.settings.COL_HEIGHT;
let velocity = this.codes[i][0].velocity;
let strength = this.codes[i][0].strength;
let text, fadeStrength;

let newCanv = document.createElement('canvas');
let newCtx = newCanv.getContext('2d');

newCanv.width = this.settings.COL_WIDTH;
newCanv.height = canvHeight;

for (let j = 1; j < codeLen; j++) {
text = this.codes[i][j];
newCtx.globalCompositeOperation = 'source-over';
newCtx.font = '24px matrix-code';

if (j < 5) {
newCtx.shadowColor = 'hsl(104, 79%, 74%)';
newCtx.shadowOffsetX = 0;
newCtx.shadowOffsetY = 0;
// 设置模糊程度
newCtx.shadowBlur = 6;
newCtx.fillStyle = 'hsla(104, 79%, ' + (100 - (j * 5)) + '%, ' + strength + ')';
} else if (j > (codeLen - 4)) {
fadeStrength = j / codeLen;
fadeStrength = 1 - fadeStrength;

newCtx.shadowOffsetX = 0;
newCtx.shadowOffsetY = 0;
newCtx.shadowBlur = 0;
newCtx.fillStyle = 'hsla(104, 79%, 74%, ' + (fadeStrength + 0.3) + ')';
} else {
newCtx.shadowOffsetX = 0;
newCtx.shadowOffsetY = 0;
newCtx.shadowBlur = 0;
newCtx.fillStyle = 'hsla(104, 79%, 74%, ' + strength + ')';
}

newCtx.fillText(text, 0, (canvHeight - (j * this.settings.COL_HEIGHT)));
}

this.codes[i][0].canvas = newCanv;

},
createLines () {
this.linesC = document.createElement('canvas');
this.linesC.width = this.WIDTH;
this.linesC.height = this.HEIGHT;
this.linesC.style.position = 'fixed';
this.linesC.style.top = 0;
this.linesC.style.left = 0;
this.linesC.style.zIndex = 10;
document.body.appendChild(this.linesC);

let linesYBlack = 0;
let linesYWhite = 0;
this.ctx2 = this.linesC.getContext('2d');

this.ctx2.beginPath();

this.ctx2.lineWidth = 1;
this.ctx2.strokeStyle = 'rgba(0, 0, 0, 0.7)';

while (linesYBlack < this.HEIGHT) {

this.ctx2.moveTo(0, linesYBlack);
this.ctx2.lineTo(this.WIDTH, linesYBlack);

linesYBlack += 5;
}

this.ctx2.lineWidth = 0.15;
this.ctx2.strokeStyle = 'rgba(255, 255, 255, 0)';

while (linesYWhite < this.HEIGHT) {

this.ctx2.moveTo(0, linesYWhite+1);
this.ctx2.lineTo(this.WIDTH, linesYWhite+1);

linesYWhite += 5;
}

this.ctx2.stroke();
},
assignColumn () {
let randomColumn = this.randomFromInterval(0, (this.COLUMNS - 1));

if (this.codes[randomColumn][0].open) {
this.codes[randomColumn][0].open = false;
} else {
return false;
}

return randomColumn;
},
randomFromInterval (from, to) {
return Math.floor(Math.random() * (to - from+ 1 ) + from);
}

}
}
</script>

<style scoped>
/** 让这个背景固定在页面不随着滚动而滚动 */
#canvas {
position: fixed;
top: 0;
left: 0;
}
</style>

有帮助的点个赞!感谢


标签:Vue,newCtx,ctx,HEIGHT,WIDTH,瀑布,codes,let,炫酷
From: https://blog.51cto.com/luckyqilin/5952254

相关文章

  • vue基础 B站课程
     反转字符串:<template><div><!--先照抄,之后再自己写。多写。把vue的课程全学出来。。。。。职业:1学好本专业学技术2跨专业考研考公3.公务员教师......
  • vuejs实现文件下载的三种方式
    第一种方式是前端创建超链接,通过a标签的链接向后端服务发get请求,接收后端的文件流,非常简单:<a:href='"/路径"'>下载模板</a>另一种情况是创建div标签,动态创建a标签:<div......
  • Vue.$nextTick的原理是什么-vue面试进阶
    原理性的东西就会文字较多,请耐下心来,细细品味Vue中DOM更新机制当你气势汹汹地使用Vue大展宏图的时候,突然发现,咦,我明明对这个数据进行更改了,但是当我获取它的时候怎么是上......
  • 面试官:vue2和vue3的区别有哪些?
    一、Vue3与Vue2区别详述1.生命周期对于生命周期来说,整体上变化不大,只是大部分生命周期钩子名称上+“on”,功能上是类似的。不过有一点需要注意,Vue3在组合式API(Comp......
  • 必会vue面试题(附答案)
    vue初始化页面闪动问题使用vue开发时,在vue初始化之前,由于div是不归vue管的,所以我们写的代码在还没有解析的情况下会容易出现花屏现象,看到类似于{{message}}的字样,虽然一般......
  • 前端一面必会vue面试题(边面边更)
    为什么要使用异步组件节省打包出的结果,异步组件分开打包,采用jsonp的方式进行加载,有效解决文件过大的问题。核心就是包组件定义变成一个函数,依赖import()语法,可以实现文......
  • 说说你对Vue的keep-alive的理解
    什么是keep-alive在平常开发中,有部分组件没有必要多次初始化,这时,我们需要将组件进行持久化,使组件的状态维持不变,在下一次展示时,也不会进行重新初始化组件。也就是说,keep......
  • 说说Vue响应式系统中的Watcher和Dep的关系-面试进阶
    引言在这里我先提出两个问题(文章末尾会进行解答):在Vue的数据响应系统中,Dep和Watcher各自分担什么任务?Vue的数据响应系统的核心是Object.defineproperty一定是最好的吗?有......
  • 京东前端高频vue面试题(边面边更)
    Redux和Vuex有什么区别,它们的共同思想(1)Redux和Vuex区别Vuex改进了Redux中的Action和Reducer函数,以mutations变化函数取代Reducer,无需switch,只需在对应的mutation函......
  • 前端vue面试题集锦1
    Vue.extend作用和原理官方解释:Vue.extend使用基础Vue构造器,创建一个“子类”。参数是一个包含组件选项的对象。其实就是一个子类构造器是Vue组件的核心api实现......