fix: click effect

This commit is contained in:
shenyu 2020-06-02 20:41:10 +08:00
parent da27325950
commit 1609b61336
7 changed files with 330 additions and 337 deletions

View File

@ -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-close1-love2-boom3-particles
click_effect: 0
# articleWidth and sidebarWidth
layout:

View File

@ -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:

View File

@ -60,16 +60,16 @@
<%- js('/js/busuanzi-2.3.pure.min') %>
<% } %>
<!-- ClickLove -->
<% if (theme.clickLove){ %>
<% if (theme.click_effect===1){ %>
<%- js('/js/clickLove') %>
<% } %>
<!-- ClickBoom -->
<% if (theme.clickBoom){ %>
<%- js('/js/clickBoom') %>
<!-- ClickBoom1 -->
<% if (theme.click_effect===2){ %>
<script src="https://cdn.jsdelivr.net/npm/animejs@latest/anime.min.js"></script>
<%- js('/js/clickBoom1') %>
<% } %>
<!-- ClickBoom2 -->
<% if (theme.clickBoom2){ %>
<script src="https://cdn.jsdelivr.net/npm/animejs@latest/anime.min.js"></script>
<% if (theme.click_effect===3){ %>
<%- js('/js/clickBoom2') %>
<% } %>
<!-- CodeCopy -->

View File

@ -1,22 +1,6 @@
<%- partial('_partial/head') %>
<body>
<% if (theme.clickBoom){ %>
<canvas width="1777" height="841"
style="position: fixed; left: 0px; top: 0px; z-index: 999; pointer-events: none;"></canvas>
<% } %>
<% if (theme.clickBoom2){ %>
<canvas class="fireworks"></canvas>
<style>
.fireworks {
position: fixed;
left: 0;
top: 0;
z-index: 99999;
pointer-events: none;
}
</style>
<% } %>
<div id="app">
<main class="content on">
<%- body %>
@ -40,6 +24,23 @@
<% if (theme.music&&theme.music.enable){ %>
<%- partial('_partial/music') %>
<% } %>
<% if (theme.click_effect===2){ %>
<canvas class="fireworks"></canvas>
<style>
.fireworks {
position: fixed;
left: 0;
top: 0;
z-index: 99999;
pointer-events: none;
}
</style>
<% } %>
<% if (theme.click_effect===3){ %>
<canvas width="1777" height="841"
style="position: fixed; left: 0px; top: 0px; z-index: 99999; pointer-events: none;"></canvas>
<% } %>
</div>
</body>

View File

@ -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()

152
source/js/clickBoom1.js Normal file
View File

@ -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);

View File

@ -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()