hexo实现背景花瓣飞舞效果

2023-11-11

效果

步骤

在source目录下js文件中新增petal.js文件

var RENDERER = {
        INIT_CHERRY_BLOSSOM_COUNT : 30,
        MAX_ADDING_INTERVAL : 10,
  
        init : function(){
            this.setParameters();
            this.reconstructMethods();
            this.createCherries();
            this.render();
        },
        setParameters : function(){
            this.$container = $('#web_bg');
            this.width = this.$container.width();
            this.height = this.$container.height();
            this.context = $('<canvas />').attr({width : this.width, height : this.height}).appendTo(this.$container).get(0).getContext('2d');
            this.cherries = [];
            this.maxAddingInterval = Math.round(this.MAX_ADDING_INTERVAL * 1000 / this.width);
            this.addingInterval = this.maxAddingInterval;
        },
        reconstructMethods : function(){
            this.render = this.render.bind(this);
        },
        createCherries : function(){
            for(var i = 0, length = Math.round(this.INIT_CHERRY_BLOSSOM_COUNT * this.width / 1000); i < length; i++){
                this.cherries.push(new CHERRY_BLOSSOM(this, true));
            }
        },
        render : function(){
            requestAnimationFrame(this.render);
            this.context.clearRect(0, 0, this.width, this.height);
  
            this.cherries.sort(function(cherry1, cherry2){
                return cherry1.z - cherry2.z;
            });
            for(var i = this.cherries.length - 1; i >= 0; i--){
                if(!this.cherries[i].render(this.context)){
                    this.cherries.splice(i, 1);
                }
            }
            if(--this.addingInterval == 0){
                this.addingInterval = this.maxAddingInterval;
                this.cherries.push(new CHERRY_BLOSSOM(this, false));
            }
        }
    };
    var CHERRY_BLOSSOM = function(renderer, isRandom){
        this.renderer = renderer;
        this.init(isRandom);
    };
    CHERRY_BLOSSOM.prototype = {
        FOCUS_POSITION : 300,
        FAR_LIMIT : 600,
        MAX_RIPPLE_COUNT : 100,
        RIPPLE_RADIUS : 100,
        SURFACE_RATE : 0.5,
        SINK_OFFSET : 20,
  
        init : function(isRandom){
            this.x = this.getRandomValue(-this.renderer.width, this.renderer.width);
            this.y = isRandom ? this.getRandomValue(0, this.renderer.height) : this.renderer.height * 1.5;
            this.z = this.getRandomValue(0, this.FAR_LIMIT);
            this.vx = this.getRandomValue(-2, 2);
            this.vy = -2;
            this.theta = this.getRandomValue(0, Math.PI * 2);
            this.phi = this.getRandomValue(0, Math.PI * 2);
            this.psi = 0;
            this.dpsi = this.getRandomValue(Math.PI / 600, Math.PI / 300);
            this.opacity = 0;
            this.endTheta = false;
            this.endPhi = false;
            this.rippleCount = 0;
  
            var axis = this.getAxis(),
                theta = this.theta + Math.ceil(-(this.y + this.renderer.height * this.SURFACE_RATE) / this.vy) * Math.PI / 500;
            theta %= Math.PI * 2;
  
            this.offsetY = 40 * ((theta <= Math.PI / 2 || theta >= Math.PI * 3 / 2) ? -1 : 1);
            this.thresholdY = this.renderer.height / 2 + this.renderer.height * this.SURFACE_RATE * axis.rate;
            this.entityColor = this.renderer.context.createRadialGradient(0, 40, 0, 0, 40, 80);
            this.entityColor.addColorStop(0, 'hsl(330, 70%, ' + 50 * (0.3 + axis.rate) + '%)');
            this.entityColor.addColorStop(0.05, 'hsl(330, 40%,' + 55 * (0.3 + axis.rate) + '%)');
            this.entityColor.addColorStop(1, 'hsl(330, 20%, ' + 70 * (0.3 + axis.rate) + '%)');
            this.shadowColor = this.renderer.context.createRadialGradient(0, 40, 0, 0, 40, 80);
            this.shadowColor.addColorStop(0, 'hsl(330, 40%, ' + 30 * (0.3 + axis.rate) + '%)');
            this.shadowColor.addColorStop(0.05, 'hsl(330, 40%,' + 30 * (0.3 + axis.rate) + '%)');
            this.shadowColor.addColorStop(1, 'hsl(330, 20%, ' + 40 * (0.3 + axis.rate) + '%)');
        },
        getRandomValue : function(min, max){
            return min + (max - min) * Math.random();
        },
        getAxis : function(){
            var rate = this.FOCUS_POSITION / (this.z + this.FOCUS_POSITION),
                x = this.renderer.width / 2 + this.x * rate,
                y = this.renderer.height / 2 - this.y * rate;
            return {rate : rate, x : x, y : y};
        },
        renderCherry : function(context, axis){
            context.beginPath();
            context.moveTo(0, 40);
            context.bezierCurveTo(-60, 20, -10, -60, 0, -20);
            context.bezierCurveTo(10, -60, 60, 20, 0, 40);
            context.fill();
  
            for(var i = -4; i < 4; i++){
                context.beginPath();
                context.moveTo(0, 40);
                context.quadraticCurveTo(i * 12, 10, i * 4, -24 + Math.abs(i) * 2);
                context.stroke();
            }
        },
        render : function(context){
            var axis = this.getAxis();
  
            if(axis.y == this.thresholdY && this.rippleCount < this.MAX_RIPPLE_COUNT){
                context.save();
                context.lineWidth = 2;
                context.strokeStyle = 'hsla(0, 0%, 100%, ' + (this.MAX_RIPPLE_COUNT - this.rippleCount) / this.MAX_RIPPLE_COUNT + ')';
                context.translate(axis.x + this.offsetY * axis.rate * (this.theta <= Math.PI ? -1 : 1), axis.y);
                context.scale(1, 0.3);
                context.beginPath();
                context.arc(0, 0, this.rippleCount / this.MAX_RIPPLE_COUNT * this.RIPPLE_RADIUS * axis.rate, 0, Math.PI * 2, false);
                context.stroke();
                context.restore();
                this.rippleCount++;
            }
            if(axis.y < this.thresholdY || (!this.endTheta || !this.endPhi)){
                if(this.y <= 0){
                    this.opacity = Math.min(this.opacity + 0.01, 1);
                }
                context.save();
                context.globalAlpha = this.opacity;
                context.fillStyle = this.shadowColor;
                context.strokeStyle = 'hsl(330, 30%,' + 40 * (0.3 + axis.rate) + '%)';
                context.translate(axis.x, Math.max(axis.y, this.thresholdY + this.thresholdY - axis.y));
                context.rotate(Math.PI - this.theta);
                context.scale(axis.rate * -Math.sin(this.phi), axis.rate);
                context.translate(0, this.offsetY);
                this.renderCherry(context, axis);
                context.restore();
            }
            context.save();
            context.fillStyle = this.entityColor;
            context.strokeStyle = 'hsl(330, 40%,' + 70 * (0.3 + axis.rate) + '%)';
            context.translate(axis.x, axis.y + Math.abs(this.SINK_OFFSET * Math.sin(this.psi) * axis.rate));
            context.rotate(this.theta);
            context.scale(axis.rate * Math.sin(this.phi), axis.rate);
            context.translate(0, this.offsetY);
            this.renderCherry(context, axis);
            context.restore();
  
            if(this.y <= -this.renderer.height / 4){
                if(!this.endTheta){
                    for(var theta = Math.PI / 2, end = Math.PI * 3 / 2; theta <= end; theta += Math.PI){
                        if(this.theta < theta && this.theta + Math.PI / 200 > theta){
                            this.theta = theta;
                            this.endTheta = true;
                            break;
                        }
                    }
                }
                if(!this.endPhi){
                    for(var phi = Math.PI / 8, end = Math.PI * 7 / 8; phi <= end; phi += Math.PI * 3 / 4){
                        if(this.phi < phi && this.phi + Math.PI / 200 > phi){
                            this.phi = Math.PI / 8;
                            this.endPhi = true;
                            break;
                        }
                    }
                }
            }
            if(!this.endTheta){
                if(axis.y == this.thresholdY){
                    this.theta += Math.PI / 200 * ((this.theta < Math.PI / 2 || (this.theta >= Math.PI && this.theta < Math.PI * 3 / 2)) ? 1 : -1);
                }else{
                    this.theta += Math.PI / 500;
                }
                this.theta %= Math.PI * 2;
            }
            if(this.endPhi){
                if(this.rippleCount == this.MAX_RIPPLE_COUNT){
                    this.psi += this.dpsi;
                    this.psi %= Math.PI * 2;
                }
            }else{
                this.phi += Math.PI / ((axis.y == this.thresholdY) ? 200 : 500);
                this.phi %= Math.PI;
            }
            if(this.y <= -this.renderer.height * this.SURFACE_RATE){
                this.x += 2;
                this.y = -this.renderer.height * this.SURFACE_RATE;
            }else{
                this.x += this.vx;
                this.y += this.vy;
            }
            return this.z > -this.FOCUS_POSITION && this.z < this.FAR_LIMIT && this.x < this.renderer.width * 1.5;
        }
    };
    $(function(){
        RENDERER.init();
    });

在_config.butterfly.yml文件中找到inject,引入jquery和petal.js文件

# 插入代码到头部 </head> 之前 和 底部 </body> 之前
inject:
  head:
    # - <link rel="stylesheet" href="/bgcss/background.css">onload="this.media='all'">
  bottom:
    # - <script src="xxxx"></script>
     - <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
    
     - <script src="/js/petal.js"></script> # 背景落叶效果
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

hexo实现背景花瓣飞舞效果 的相关文章

随机推荐

  • for-loop 与 json.Unmarshal 性能分析概要

    原文地址 for loop 与 json Unmarshal 性能分析概要 前言 在项目中 常常会遇到循环交换赋值的数据处理场景 尤其是 RPC 数据交互格式要转为 Protobuf 赋值是无法避免的 一般会有如下几种做法 for for
  • Spring入门概述及基本知识点

    Spring是什么 我们常说的Spring 其实在官网中全称是SpringFrameWork Spring是一个轻量级 非入侵式的Java开发框架 主要用于业务层 和整合其他层 解决了业务层和表现层 持久层的耦合问题 将面向接口编程贯穿整个
  • boost介绍

    boost是一个准标准库 相当于STL的延续和扩充 它的设计理念和STL比较接近 都是利用泛型让复用达到最大化 不过对比STL boost更加实用 STL集中在算法部分 而boost包含了不少工具类 可以完成比较具体的工作 boost主要包
  • CVPR21 - BasicVSR:简单有效的视频超分辨率Baseline

    文章目录 原文信息 初识 相知 组件分析 BasicVSR IconVSR 部分实验 回顾 原文信息 原文链接 初识 相比于图像超分 视频超分 VSR Video Super Resolution 显然是一件更具挑战性的任务 视频超分比图像
  • Two slices reporting being the first in the same frame. 和 Could not find ref with POCXX问题

    hevc 000001716438fc00 Two slices reporting being the first in the same frame hevc 000001716439ec80 Could not find ref wi
  • 黑马并发编程(AQS源码分析、线程池)

    AQS源码分析 线程池 8 线程池 1 自定义线程池 阻塞队列 优化队列 线程池 执行和线程处理设计 线程池执行的整个思路 阻塞添加 拒绝策略 2 ThreadExecutor 线程池状态 线程池参数 拒绝策略 newFixedThread
  • 本地上传文件到Linux服务器

    问题描述 如何将本地文件上传至Linux服务器上 这里分别以Windows和Ubuntu系统为例 解决方法 scp filename username IP home directory 举个例子 scp data zip zhangsan
  • 打造利器Qt Creator:代码todo工具的使用

    打造利器Qt Creator 代码todo工具的使用 前言 俗话说 工欲善其事必先利其器 工作生活中 能有一款出色易用 高效简便的工具 对提高效率 达成价值有着莫大的影响 Qt是一套C 库 封装了许多好用的模块和功能 且带有先进的GUI设计
  • 【VUE】vue报错“‘vue-cli-service‘不是内部或外部命令,也不是...”的解决办法

    问题描述 项目执行npm run serve后报错 产生原因 最大概率原因 由于在该代码中含有node module依赖包 再拷贝到其他计算机时 项目路径发生变化 导致找不到vue cli service于是报错 其他出错情况 见下文扩展
  • 如何更好的利用区块链API

    区块链允许数据提供者和消费者直接在单个开放系统中交易信息 而不是订阅世界各地的数十个集中服务 并编写他们的软件来与每个API进行通信 阅读此区块链API教程 了解如何根据你的特定需求使用它 API 应用程序编程接口 是单个计算机程序可以用来
  • synchronized和ReentrantLock的比较

    六 synchronized和ReentrantLock的比较 1 区别 1 Lock是一个接口 而synchronized是Java中的关键字 synchronized是内置的语言实现 2 synchronized在发生异常时 会自动释放
  • IDEA 的 maven项目 Plugins以及Dependencies 爆红 红波浪线

    IntelliJ idea新建Maven项目 Plugins以及Dependencies下有红色波浪线 如图 一 配置maven的Local repository 点击File gt Settings gt Build Execution
  • 使用stream下载文件避坑-》堆内存溢出的原因

    场景 下载80MB的文zip文件正常 大文件就下载不下来 下载为0KB 原因 下载大文件耗时间 设置了超时时间 其实文件没有下载下来 conn setConnectTimeout 3 1000 并不是上面那个原因 这段代码表示通过 Http
  • 基于LSTM的交通工具轨迹预测

    网络上利用LSTM预测轨迹的文章不多 仅有的几篇比较粗略 本文对一些大佬开源的代码进行修改 增添了轨迹连续预测代码 不足之处欢迎批评 本文参考Muzi Water大佬的文章 LSTM模型 轨迹经纬度预测 https blog csdn ne
  • 2022 年十大 Python Web 开发框架

    1 Django Django 框架是任何 Web 开发公司的首选 开发人员使用此框架来开发高质量标准的复杂 Web 和移动应用程序 由于其开源特性 Django 具有成本效益 但在其他有助于开发人员创建 API 和业务类 Web 应用程序
  • 大题---砝码称重(贪心算法)

    5个砝码 用天平称重时 我们希望用尽可能少的砝码组合称出尽可能多的重量 如果只有5个砝码 重量分别是1 3 9 27 81 则它们可以组合称出1到121之间任意整数重量 砝码允许放在左右两个盘中 本题目要求编程实现 对用户给定的重量 给出砝
  • Redis多机数据库实现

    Redis多机数据库实现 为 Redis设计与实现 笔记 复制 客户端可以使用SLAVEOF命令将指定服务器设置为该服务器的主服务器 127 0 0 1 12345 gt SLAVEOF 127 0 0 1 6379 127 0 0 1 6
  • Date类(Date、SimpleDateFormat和Calendar)使用

    1 Date类与long数据类型的转型 2 SimpleDateFormat类的使用 3 Calendar类的使用 如果要操作日期一定要使用日期的处理类 1 Java util Date类 范例 package com lohas demo
  • Win10/Win11子系统(二)——深度学习环境搭建:WSL2+Ubuntu20.04+CUDA10.1+pytorch1.8.1+pycharm

    windows子系统wsl2深度学习环境配置 前言 一 准备工作 显卡驱动 二 CUDA10 1配置 1 下载安装 2 设置环境变量 三 cudnn配置 3 检验安装 四 安装Anaconda 五 安装pytorch 六 安装pycharm
  • hexo实现背景花瓣飞舞效果

    效果 步骤 在source目录下js文件中新增petal js文件 var RENDERER INIT CHERRY BLOSSOM COUNT 30 MAX ADDING INTERVAL 10 init function this se