模仿CSDN黑暗帝国动态背景的vue项目(附源码)

Posted 紫米粥

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了模仿CSDN黑暗帝国动态背景的vue项目(附源码)相关的知识,希望对你有一定的参考价值。

开发工具:Webstorm
技术栈:vue、html、canvas
实现效果(其实这里面的是动态变换的,只是没有截成GIF动图):
实现步骤:
(1)在这里的项目我是用VueCli3脚手架进行搭建的。
(2)关于动态背景的源码则是在github找的源码。
(3)总体是在App.vue中进行背景的添加
(4)因为在这里是在App.vue中添加的,所以在这里给出了不想以这种动态背景为背景的解决方案。
(5)在最后我会附上源码
(6)因为这个是我用来练手的,所以只有前台页面,而且很多不完善,但是大家可以借鉴一下这个代码,然后在这个基础上大家可以自由发挥。如果大家想下载源码文件的话。
需要注意,因为我在登陆的时候与后端进行了交互,大家可以改一下Login.vue的登录的代码即可,修改成直接跳转就可以,因为时间关系,在这里我就不一一阐述了。

1、黑客帝国实现源码:

(1)大家可以创建一个vue文件,将其复制进去即可,给大家贴一个结构目录。

<template>
    <div class="main">
    <canvas  id="vue-matrix-raindrop"></canvas>
    </div>
</template>

<script>
	export default 
		name: 'vue-matrix-raindrop',
    props:
        canvasWidth:
        	type:Number,
            default:1900
        ,
        canvasHeight:
            type:Number,
            default:1200
        ,
        fontSize:
        	type:Number,
            default:20
        ,
        fontFamily:
        	type:String,
            default:'arial'
        ,
        textContent:
        	type:String,
            default:'abcdefghijklmnopqrstuvwxyz'
        ,
        textColor:
        	type:String,
            default:'#0F0',
            validator:function(value)
          	  var colorReg = /^#([0-9a-fA-F]6)|([0-9a-fA-F]3)$/g
              return colorReg.test(value)
            
        ,
        backgroundColor:
        	type:String,
            default:'rgba(0,0,0,0.1)',
            validator:function(value)
              var reg = /^[rR][gG][Bb][Aa][\\(]((2[0-4][0-9]|25[0-5]|[01]?[0-9][0-9]?),)2(2[0-4][0-9]|25[0-5]|[01]?[0-9][0-9]?),?(0\\.\\d1,2|1|0)?[\\)]1$/;
              return reg.test(value);
            
        ,
        speed:
        	type:Number,
            default:2,
            validator:function(value)
              return value%1 === 0;
            
        
    ,
    mounted:function()
          this.initRAF();
          this.initCanvas();
          this.initRainDrop();
          this.animationUpdate();
    ,
    methods:
    	 initRAF()
         window.requestAnimationFrame = (function()
           return window.requestAnimationFrame       ||
                  window.webkitRequestAnimationFrame ||
                  window.mozRequestAnimationFrame    ||
                  window.oRequestAnimationFrame      ||
                  function( callback )
                    window.setTimeout(callback, 1000 / 60);
                  ;
         )();
         window.cancelAnimationFrame = (function () 
           return window.cancelAnimationFrame ||
                  window.webkitCancelAnimationFrame ||
                  window.mozCancelAnimationFrame ||
                  window.oCancelAnimationFrame ||
                  function (id) 
                    window.clearTimeout(id);
                  ;
           )();

       ,
    	 initCanvas()
         this.canvas = document.getElementById('vue-matrix-raindrop');
         //需要判断获取到的canvas是否是真的canvas
         if(this.canvas.tagName.toLowerCase() !== 'canvas')
            console.error("Error! Invalid canvas! Please check the canvas's id!")
         

         this.canvas.width = window.innerWidth;
         this.canvas.height = window.innerHeight;
         console.log(this.canvas.height )
         this.canvasCtx = this.canvas.getContext('2d');
         this.canvasCtx.font = this.fontSize+'px '+this.fontFamily;
         this.columns = this.canvas.width / this.fontSize;
       ,
       initRainDrop()
    	 	for(var i=0;i<this.columns;i++)
    	 		this.rainDropPositionArray.push(0);
        
       ,

       animationUpdate()
       	 this.speedCnt++;
       	 //speed为1最快,越大越慢
       	 if(this.speedCnt===this.speed)
       	 	 this.speedCnt = 0;
           //绘制背景
           this.canvasCtx.fillStyle=this.backgroundColor;
           this.canvasCtx.fillRect(0,0,this.canvas.width,this.canvas.height);
           //绘制文字
           this.canvasCtx.fillStyle=this.textColor;
           for(var i=0,len=this.rainDropPositionArray.length;i<len;i++)
             this.rainDropPositionArray[i]++;
             var randomTextIndex = Math.floor(Math.random()*this.textContent.length);
             var randomText = this.textContent[randomTextIndex];
             var textYPostion = this.rainDropPositionArray[i]*this.fontSize;
             this.canvasCtx.fillText(randomText,i*this.fontSize,textYPostion);
             if(textYPostion>this.canvasHeight)
               if(Math.random()>0.9)
                 this.rainDropPositionArray[i]=0;
               
             
           

         
         window.requestAnimationFrame(this.animationUpdate)
       
    ,
		data () 
			return 
				canvasCtx:null,
                canvas:null,
                columns:0,
                rainDropPositionArray:[],
                speedCnt:0
			
		
	
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
    canvas 
        position: absolute;
    
    .component
        position: absolute;
        width: 100%;
        height: 100%;
        z-index: 1;
    
    .userName 
        position: absolute;
        top: 40%;
        left: 20%;
    
</style>

2、对于App.vue文件中的修改:

(1)注意上一个特效文件的路径的修改。

<template>
  <div id="app" style="width: 100%;height:100%">
      <VueMatrixRaindrop></VueMatrixRaindrop>
    <keep-alive>
      <router-view></router-view>
    </keep-alive>
  </div>
</template>

<script>
//这里根据自己的前面的特效vue项目的具体目录合理选择
import VueMatrixRaindrop from './views/vue-matrix-digit-rain'
export default 
  name: 'app',
  components: 
      VueMatrixRaindrop,
  ,
    methods:
      
    


</script>

3、但是如果是后台文件不想以这种动态背景为背景,那怎么办呢?

在这里主要借助z-index属性进行解决。在这里我主要以后台的管理页面为例子,来简单说明一下。

效果实现(可以自定义背景):


copyMenu.vue 代码实现:

<template>

    <el-container class="home-container">
        <!-- 头部区域 -->
        <el-header>
            <div>
                <div class="home">
                    <img src="../assets/logo.png" alt="" />
                </div>
                <span>电商后台管理系统</span>
            </div>
            <el-button type="info" @click="logout">退出</el-button>
        </el-header>
        <!-- 页面主体区域 -->
        <el-container>
            <!-- 侧边栏 -->
            <el-aside :width="isCollapse ? '64px' : '200px'">
                <div class="toggle-button" @click="toggleCollapse">|||</div>
                <!-- 侧边栏菜单区域 -->
                <el-menu background-color="#333744" text-color="#fff" active-text-color="#409EFF" unique-opened :collapse="isCollapse" :collapse-transition="false" router :default-active="activePath">
                    <!-- 一级菜单 -->
                    <el-submenu :index="item.id + ''" v-for="item in menulist" :key="item.id">
                        <!-- 一级菜单的模板区域 -->
                        <template slot="title">
                            <!-- 图标 -->
                            <i :class="iconsObj[item.id]"></i>
                            <!-- 文本 -->
                            <span> item.authName </span>
                        </template>

                        <!-- 二级菜单 -->
                        <el-menu-item :index="'/' + subItem.path" v-for="subItem in item.children" :key="subItem.id" @click="saveNavState('/' + subItem.path)">
                            <template slot="title">
                                <!-- 图标 -->
                                <i class="el-icon-menu"></i>
                                <!-- 文本 -->
                                <span> subItem.authName </span>
                            </template>
                        </el-menu-item>
                    </el-submenu>
                </el-menu>
            </el-aside>
            <!-- 右侧内容主体 -->
            <el-main>
                <!-- 路由占位符 -->
                <router-view></router-view>
            </el-main>
        </el-container>
    </el-container>


</template>

<script>
    export default 
        name: "copy-menu",
        data() 
            return 
                // 左侧菜单数据
                menulist: [],
                iconsObj: 
                    '125': 'iconfont icon-user',
                    '103': 'iconfont icon-tijikongjian',
                    '101': 'iconfont icon-shangpin',
                    '102': 'iconfont icon-danju',
                    '145': 'iconfont icon-baobiao'
                ,
                // 是否折叠
                isCollapse: false,
                // 被激活的链接地址
                activePath: ''
            
        ,
        created() 
            this.getMenuList()
            this.activePath = window.sessionStorage.getItem('activePath')
        ,
        methods: 
            logout() 
                window.sessionStorage.clear()
                this.$router.push('/login')
            ,
            // 获取所有的菜单
           getMenuList() 
                console.log("测试")
                //const router = useRouter()
                var bmenus =
                    [
                        
                            "id": 125,
                            "authName": "用户管理",
                            "path": "users",
                            "children": [
                                
                                    "id": 110,
                                    "authName": "用户列表",
                                    "path": "user",
                                    "children": [],
                                    "order": null
                                ,
                                
                                    "id": 210,
                                    "authName": "异步状态",
                                    "path": "netTick",
                                    "children": [],
                                    "order": null
                                ,
                                
                                    "id": 211,
                                    "authName": "表格测试",
                                    "path": "table",
                                    "children": [],
                                    "order": null
                                
                            ],
                            "order": 1
                        ,
                        
                            "id": 103,
                            "authName": "权限管理",
                            "path": "rights",
                            "children": [
                                
                                    "id": 111,
                                    "authName": "角色列表",
                                    "path": "roles",
                                    "children": [],
                                    "order": null
                             

以上是关于模仿CSDN黑暗帝国动态背景的vue项目(附源码)的主要内容,如果未能解决你的问题,请参考以下文章

个人博客系统(附源码)

经典毕设项目-企业云盘(springboot+mybaits+vue+华为云obs存储)附全部源码

vue3项目练习大全(附github源码)

快速入门vue.js的3个小实例(附源码)

vue项目实现记住密码到cookie功能(附源码)

Redrain 通用菜单控件使用方法和说明(增加动态添加功能附源码和demo)