diff --git a/README.md b/README.md index 7129a7b..c2a3e1c 100644 --- a/README.md +++ b/README.md @@ -171,12 +171,8 @@ mouse: enable: false path: /images/mouse.cur -# ClickLove -clickLove: false -# ClickBoom style 1 -clickBoom: false -# ClickBoom style 2 -clickBoom2: false +# Click effect: 0-close,1-love,2-boom,3-particles +click_effect: 0 # articleWidth and sidebarWidth layout: diff --git a/_config.yml b/_config.yml index cef5d20..ff5da35 100644 --- a/_config.yml +++ b/_config.yml @@ -97,19 +97,15 @@ rss: /atom.xml darkmode: true # 动态背景效果: 0-关闭,1-动态线条(跟随鼠标) -canvas_bg: 0 +canvas_bg: 1 # 自定义鼠标样式,直接替换/images/mouse.cur文件 mouse: enable: false path: /images/mouse.cur -# 页面点击小红心(开启请设置为true) -clickLove: false -# 页面点击-粒子烟花效果(开启请设置为true) -clickBoom: false -# 页面点击-爆炸烟花效果(开启请设置为true) -clickBoom2: false +# 鼠标点击效果:0-关闭,1-爱心,2-爆炸烟花,3-粒子烟花 +click_effect: 0 # 页面宽度自定义(不建议修改,可能造成布局混乱),article_width文章宽度,sidebar_width侧边栏宽度 layout: diff --git a/layout/_partial/after-footer.ejs b/layout/_partial/after-footer.ejs index 2a280f7..aeb2c80 100644 --- a/layout/_partial/after-footer.ejs +++ b/layout/_partial/after-footer.ejs @@ -60,16 +60,16 @@ <%- js('/js/busuanzi-2.3.pure.min') %> <% } %> -<% if (theme.clickLove){ %> +<% if (theme.click_effect===1){ %> <%- js('/js/clickLove') %> <% } %> - -<% if (theme.clickBoom){ %> -<%- js('/js/clickBoom') %> + +<% if (theme.click_effect===2){ %> + +<%- js('/js/clickBoom1') %> <% } %> -<% if (theme.clickBoom2){ %> - +<% if (theme.click_effect===3){ %> <%- js('/js/clickBoom2') %> <% } %> diff --git a/layout/layout.ejs b/layout/layout.ejs index 98e395c..1616e91 100644 --- a/layout/layout.ejs +++ b/layout/layout.ejs @@ -1,22 +1,6 @@ <%- partial('_partial/head') %> - <% if (theme.clickBoom){ %> - - <% } %> - <% if (theme.clickBoom2){ %> - - - <% } %>
<%- body %> @@ -40,6 +24,23 @@ <% if (theme.music&&theme.music.enable){ %> <%- partial('_partial/music') %> <% } %> + + <% if (theme.click_effect===2){ %> + + + <% } %> + <% if (theme.click_effect===3){ %> + + <% } %>
diff --git a/source/js/clickBoom.js b/source/js/clickBoom.js deleted file mode 100644 index 7926f94..0000000 --- a/source/js/clickBoom.js +++ /dev/null @@ -1,154 +0,0 @@ -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 diff --git a/source/js/clickBoom1.js b/source/js/clickBoom1.js new file mode 100644 index 0000000..69b899b --- /dev/null +++ b/source/js/clickBoom1.js @@ -0,0 +1,152 @@ +const numberOfParticules = 20; + +const minOrbitRadius = 50; +const maxOrbitRadius = 100; + +const minCircleRadius = 10; +const maxCircleRadius = 20; + +const minAnimeDuration = 900; +const maxAnimeDuration = 1500; + +const minDiffuseRadius = 50; +const maxDiffuseRadius = 100; + +let canvasEl = document.querySelector(".fireworks"); +let ctx = canvasEl.getContext("2d"); +let pointerX = 0; +let pointerY = 0; + +let tap = + "ontouchstart" in window || navigator.msMaxTouchPoints + ? "touchstart" + : "mousedown"; + +// sea blue +let colors = ["127, 180, 226", "157, 209, 243", "204, 229, 255"]; + +function setCanvasSize() { + canvasEl.width = window.innerWidth; + canvasEl.height = window.innerHeight; + canvasEl.style.width = window.innerWidth + "px"; + canvasEl.style.height = window.innerHeight + "px"; +} + +function updateCoords(e) { + pointerX = e.clientX || e.touches[0].clientX; + pointerY = e.clientY || e.touches[0].clientY; +} + +function setParticuleDirection(p) { + let angle = (anime.random(0, 360) * Math.PI) / 180; + let value = anime.random(minDiffuseRadius, maxDiffuseRadius); + let radius = [-1, 1][anime.random(0, 1)] * value; + return { + x: p.x + radius * Math.cos(angle), + y: p.y + radius * Math.sin(angle) + }; +} + +function createParticule(x, y) { + let p = {}; + p.x = x; + p.y = y; + p.color = + "rgba(" + + colors[anime.random(0, colors.length - 1)] + + "," + + anime.random(0.2, 0.8) + + ")"; + p.radius = anime.random(minCircleRadius, maxCircleRadius); + p.endPos = setParticuleDirection(p); + p.draw = function () { + ctx.beginPath(); + ctx.arc(p.x, p.y, p.radius, 0, 2 * Math.PI, true); + ctx.fillStyle = p.color; + ctx.fill(); + }; + return p; +} + +function createCircle(x, y) { + let p = {}; + p.x = x; + p.y = y; + p.color = "#000"; + p.radius = 0.1; + p.alpha = 0.5; + p.lineWidth = 6; + p.draw = function () { + ctx.globalAlpha = p.alpha; + ctx.beginPath(); + ctx.arc(p.x, p.y, p.radius, 0, 2 * Math.PI, true); + ctx.lineWidth = p.lineWidth; + ctx.strokeStyle = p.color; + ctx.stroke(); + ctx.globalAlpha = 1; + }; + return p; +} + +function renderParticule(anim) { + for (let i = 0; i < anim.animatables.length; i++) { + anim.animatables[i].target.draw(); + } +} + +function animateParticules(x, y) { + let circle = createCircle(x, y); + let particules = []; + for (let i = 0; i < numberOfParticules; i++) { + particules.push(createParticule(x, y)); + } + anime + .timeline() + .add({ + targets: particules, + x: function (p) { + return p.endPos.x; + }, + y: function (p) { + return p.endPos.y; + }, + radius: 0.1, + duration: anime.random(minAnimeDuration, maxAnimeDuration), + easing: "easeOutExpo", + update: renderParticule + }) + .add({ + targets: circle, + radius: anime.random(minOrbitRadius, maxOrbitRadius), + lineWidth: 0, + alpha: { + value: 0, + easing: "linear", + duration: anime.random(600, 800) + }, + duration: anime.random(1200, 1800), + easing: "easeOutExpo", + update: renderParticule, + offset: 0 + }); +} + +let render = anime({ + duration: Infinity, + update: function () { + ctx.clearRect(0, 0, canvasEl.width, canvasEl.height); + } +}); + +document.addEventListener( + tap, + function (e) { + render.play(); + updateCoords(e); + animateParticules(pointerX, pointerY); + }, + false +); + +setCanvasSize(); +window.addEventListener("resize", setCanvasSize, false); diff --git a/source/js/clickBoom2.js b/source/js/clickBoom2.js index 69b899b..d3f9d79 100644 --- a/source/js/clickBoom2.js +++ b/source/js/clickBoom2.js @@ -1,152 +1,154 @@ -const numberOfParticules = 20; - -const minOrbitRadius = 50; -const maxOrbitRadius = 100; - -const minCircleRadius = 10; -const maxCircleRadius = 20; - -const minAnimeDuration = 900; -const maxAnimeDuration = 1500; - -const minDiffuseRadius = 50; -const maxDiffuseRadius = 100; - -let canvasEl = document.querySelector(".fireworks"); -let ctx = canvasEl.getContext("2d"); -let pointerX = 0; -let pointerY = 0; - -let tap = - "ontouchstart" in window || navigator.msMaxTouchPoints - ? "touchstart" - : "mousedown"; - -// sea blue -let colors = ["127, 180, 226", "157, 209, 243", "204, 229, 255"]; - -function setCanvasSize() { - canvasEl.width = window.innerWidth; - canvasEl.height = window.innerHeight; - canvasEl.style.width = window.innerWidth + "px"; - canvasEl.style.height = window.innerHeight + "px"; -} - -function updateCoords(e) { - pointerX = e.clientX || e.touches[0].clientX; - pointerY = e.clientY || e.touches[0].clientY; -} - -function setParticuleDirection(p) { - let angle = (anime.random(0, 360) * Math.PI) / 180; - let value = anime.random(minDiffuseRadius, maxDiffuseRadius); - let radius = [-1, 1][anime.random(0, 1)] * value; - return { - x: p.x + radius * Math.cos(angle), - y: p.y + radius * Math.sin(angle) - }; -} - -function createParticule(x, y) { - let p = {}; - p.x = x; - p.y = y; - p.color = - "rgba(" + - colors[anime.random(0, colors.length - 1)] + - "," + - anime.random(0.2, 0.8) + - ")"; - p.radius = anime.random(minCircleRadius, maxCircleRadius); - p.endPos = setParticuleDirection(p); - p.draw = function () { - ctx.beginPath(); - ctx.arc(p.x, p.y, p.radius, 0, 2 * Math.PI, true); - ctx.fillStyle = p.color; - ctx.fill(); - }; - return p; -} - -function createCircle(x, y) { - let p = {}; - p.x = x; - p.y = y; - p.color = "#000"; - p.radius = 0.1; - p.alpha = 0.5; - p.lineWidth = 6; - p.draw = function () { - ctx.globalAlpha = p.alpha; - ctx.beginPath(); - ctx.arc(p.x, p.y, p.radius, 0, 2 * Math.PI, true); - ctx.lineWidth = p.lineWidth; - ctx.strokeStyle = p.color; - ctx.stroke(); - ctx.globalAlpha = 1; - }; - return p; -} - -function renderParticule(anim) { - for (let i = 0; i < anim.animatables.length; i++) { - anim.animatables[i].target.draw(); +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 } -} - -function animateParticules(x, y) { - let circle = createCircle(x, y); - let particules = []; - for (let i = 0; i < numberOfParticules; i++) { - particules.push(createParticule(x, y)); + + 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() } - anime - .timeline() - .add({ - targets: particules, - x: function (p) { - return p.endPos.x; - }, - y: function (p) { - return p.endPos.y; - }, - radius: 0.1, - duration: anime.random(minAnimeDuration, maxAnimeDuration), - easing: "easeOutExpo", - update: renderParticule + + 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) }) - .add({ - targets: circle, - radius: anime.random(minOrbitRadius, maxOrbitRadius), - lineWidth: 0, - alpha: { - value: 0, - easing: "linear", - duration: anime.random(600, 800) - }, - duration: anime.random(1200, 1800), - easing: "easeOutExpo", - update: renderParticule, - offset: 0 - }); -} - -let render = anime({ - duration: Infinity, - update: function () { - ctx.clearRect(0, 0, canvasEl.width, canvasEl.height); + this.circles.push(circle) + } } -}); - -document.addEventListener( - tap, - function (e) { - render.play(); - updateCoords(e); - animateParticules(pointerX, pointerY); - }, - false -); - -setCanvasSize(); -window.addEventListener("resize", setCanvasSize, false); + + 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 = '99999' + 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