From 9317a2d5d4c711db83440aed431b24a34cc6d6f0 Mon Sep 17 00:00:00 2001 From: shenyu <448766534@qq.com> Date: Sat, 23 May 2020 06:45:12 +0800 Subject: [PATCH] :rocket: feat: clickBoom --- _config.yml | 6 +- layout/_partial/after-footer.ejs | 4 + layout/layout.ejs | 3 + source/js/clickBoom.js | 154 +++++++++++++++++++++++++++++++ 4 files changed, 165 insertions(+), 2 deletions(-) create mode 100644 source/js/clickBoom.js diff --git a/_config.yml b/_config.yml index 6699612..f5c82a3 100644 --- a/_config.yml +++ b/_config.yml @@ -98,6 +98,8 @@ darkmode: true # 页面点击小红心(开启请设置为true) clickLove: false +# 页面点击烟花效果(开启请设置为true) +clickBoom: false # 页面宽度自定义(不建议修改,可能造成布局混乱),article_width文章宽度,sidebar_width侧边栏宽度 layout: @@ -110,8 +112,8 @@ layout: # 启用Valine必须先创建leancloud应用, 获取 id|key 填入即可 leancloud: enable: true - app_id: # Your leancloud application appid - app_key: # Your leancloud application appkey + app_id: # + app_key: # # Valine配置 valine: enable: true # 是否启用 diff --git a/layout/_partial/after-footer.ejs b/layout/_partial/after-footer.ejs index ac40d69..7a8d47b 100644 --- a/layout/_partial/after-footer.ejs +++ b/layout/_partial/after-footer.ejs @@ -63,6 +63,10 @@ <% if (theme.clickLove){ %> <%- js('/js/clickLove') %> <% } %> + +<% if (theme.clickBoom){ %> +<%- js('/js/clickBoom') %> +<% } %> <% if (theme.copy_btn == true) { %> <%- css('/css/clipboard') %> diff --git a/layout/layout.ejs b/layout/layout.ejs index 0af2813..2ba1906 100644 --- a/layout/layout.ejs +++ b/layout/layout.ejs @@ -1,6 +1,9 @@ <%- partial('_partial/head') %> + <% if (theme.clickBoom){ %> + + <% } %>
<%- body %> diff --git a/source/js/clickBoom.js b/source/js/clickBoom.js new file mode 100644 index 0000000..7926f94 --- /dev/null +++ b/source/js/clickBoom.js @@ -0,0 +1,154 @@ +class Circle { + constructor({ origin, speed, color, angle, context }) { + this.origin = origin + this.position = { ...this.origin } + this.color = color + this.speed = speed + this.angle = angle + this.context = context + this.renderCount = 0 + } + + draw() { + this.context.fillStyle = this.color + this.context.beginPath() + this.context.arc(this.position.x, this.position.y, 2, 0, Math.PI * 2) + this.context.fill() + } + + move() { + this.position.x = (Math.sin(this.angle) * this.speed) + this.position.x + this.position.y = (Math.cos(this.angle) * this.speed) + this.position.y + (this.renderCount * 0.3) + this.renderCount++ + } + } + + class Boom { + constructor ({ origin, context, circleCount = 10, area }) { + this.origin = origin + this.context = context + this.circleCount = circleCount + this.area = area + this.stop = false + this.circles = [] + } + + randomArray(range) { + const length = range.length + const randomIndex = Math.floor(length * Math.random()) + return range[randomIndex] + } + + randomColor() { + const range = ['8', '9', 'A', 'B', 'C', 'D', 'E', 'F'] + return '#' + this.randomArray(range) + this.randomArray(range) + this.randomArray(range) + this.randomArray(range) + this.randomArray(range) + this.randomArray(range) + } + + randomRange(start, end) { + return (end - start) * Math.random() + start + } + + init() { + for(let i = 0; i < this.circleCount; i++) { + const circle = new Circle({ + context: this.context, + origin: this.origin, + color: this.randomColor(), + angle: this.randomRange(Math.PI - 1, Math.PI + 1), + speed: this.randomRange(1, 6) + }) + this.circles.push(circle) + } + } + + move() { + this.circles.forEach((circle, index) => { + if (circle.position.x > this.area.width || circle.position.y > this.area.height) { + return this.circles.splice(index, 1) + } + circle.move() + }) + if (this.circles.length == 0) { + this.stop = true + } + } + + draw() { + this.circles.forEach(circle => circle.draw()) + } + } + + class CursorSpecialEffects { + constructor() { + this.computerCanvas = document.createElement('canvas') + this.renderCanvas = document.createElement('canvas') + + this.computerContext = this.computerCanvas.getContext('2d') + this.renderContext = this.renderCanvas.getContext('2d') + + this.globalWidth = window.innerWidth + this.globalHeight = window.innerHeight + + this.booms = [] + this.running = false + } + + handleMouseDown(e) { + const boom = new Boom({ + origin: { x: e.clientX, y: e.clientY }, + context: this.computerContext, + area: { + width: this.globalWidth, + height: this.globalHeight + } + }) + boom.init() + this.booms.push(boom) + this.running || this.run() + } + + handlePageHide() { + this.booms = [] + this.running = false + } + + init() { + const style = this.renderCanvas.style + style.position = 'fixed' + style.top = style.left = 0 + style.zIndex = '999999999999999999999999999999999999999999' + style.pointerEvents = 'none' + + style.width = this.renderCanvas.width = this.computerCanvas.width = this.globalWidth + style.height = this.renderCanvas.height = this.computerCanvas.height = this.globalHeight + + document.body.append(this.renderCanvas) + + window.addEventListener('mousedown', this.handleMouseDown.bind(this)) + window.addEventListener('pagehide', this.handlePageHide.bind(this)) + } + + run() { + this.running = true + if (this.booms.length == 0) { + return this.running = false + } + + requestAnimationFrame(this.run.bind(this)) + + this.computerContext.clearRect(0, 0, this.globalWidth, this.globalHeight) + this.renderContext.clearRect(0, 0, this.globalWidth, this.globalHeight) + + this.booms.forEach((boom, index) => { + if (boom.stop) { + return this.booms.splice(index, 1) + } + boom.move() + boom.draw() + }) + this.renderContext.drawImage(this.computerCanvas, 0, 0, this.globalWidth, this.globalHeight) + } + } + + const cursorSpecialEffects = new CursorSpecialEffects() + cursorSpecialEffects.init() \ No newline at end of file