Merge branch 'main' into bug-fix-code-copy-repeat

This commit is contained in:
tangly1024
2022-05-06 17:32:01 +08:00
71 changed files with 1131 additions and 689 deletions

209
components/Fireworks.js Normal file
View File

@@ -0,0 +1,209 @@
/**
* https://codepen.io/juliangarnier/pen/gmOwJX
* custom by hexo-theme-yun @YunYouJun
*/
import React from 'react'
import anime from 'animejs'
export const Fireworks = () => {
React.useEffect(() => {
createFireworks({})
}, [])
return <canvas id='fireworks' className='fireworks'></canvas>
}
/**
* 创建烟花
* @param config
*/
function createFireworks(config) {
const defaultColors = ['102, 167, 221', '62, 131, 225', '33, 78, 194']
const defaultConfig = {
colors: defaultColors,
numberOfParticules: 20,
orbitRadius: {
min: 50,
max: 100
},
circleRadius: {
min: 10,
max: 20
},
diffuseRadius: {
min: 50,
max: 100
},
animeDuration: {
min: 900,
max: 1500
}
}
config = Object.assign(defaultConfig, config)
let pointerX = 0
let pointerY = 0
// sky blue
const colors = config.colors || defaultColors
const canvasEl = document.querySelector('.fireworks')
const ctx = canvasEl.getContext('2d')
/**
* 设置画布尺寸
*/
function setCanvasSize(canvasEl) {
canvasEl.width = window.innerWidth
canvasEl.height = window.innerHeight
canvasEl.style.width = `${window.innerWidth}px`
canvasEl.style.height = `${window.innerHeight}px`
}
/**
* update pointer
* @param {TouchEvent} e
*/
function updateCoords(e) {
pointerX =
e.clientX ||
(e.touches[0] ? e.touches[0].clientX : e.changedTouches[0].clientX)
pointerY =
e.clientY ||
(e.touches[0] ? e.touches[0].clientY : e.changedTouches[0].clientY)
}
function setParticuleDirection(p) {
const angle = (anime.random(0, 360) * Math.PI) / 180
const value = anime.random(
config.diffuseRadius.min,
config.diffuseRadius.max
)
const radius = [-1, 1][anime.random(0, 1)] * value
return {
x: p.x + radius * Math.cos(angle),
y: p.y + radius * Math.sin(angle)
}
}
/**
* 在指定位置创建粒子
* @param {number} x
* @param {number} y
* @returns
*/
function createParticule(x, y) {
const p = {
x,
y,
color: `rgba(${
colors[anime.random(0, colors.length - 1)]
},${
anime.random(0.2, 0.8)
})`,
radius: anime.random(config.circleRadius.min, config.circleRadius.max),
endPos: null,
draw() {}
}
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) {
const p = {
x,
y,
color: '#000',
radius: 0.1,
alpha: 0.5,
lineWidth: 6,
draw() {}
}
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) {
const circle = createCircle(x, y)
const particules = []
for (let i = 0; i < config.numberOfParticules; i++) { particules.push(createParticule(x, y)) }
anime
.timeline()
.add({
targets: particules,
x(p) {
return p.endPos.x
},
y(p) {
return p.endPos.y
},
radius: 0.1,
duration: anime.random(
config.animeDuration.min,
config.animeDuration.max
),
easing: 'easeOutExpo',
update: renderParticule
})
.add(
{
targets: circle,
radius: anime.random(config.orbitRadius.min, config.orbitRadius.max),
lineWidth: 0,
alpha: {
value: 0,
easing: 'linear',
duration: anime.random(600, 800)
},
duration: anime.random(1200, 1800),
easing: 'easeOutExpo',
update: renderParticule
},
0
)
}
const render = anime({
duration: Infinity,
update: () => {
ctx.clearRect(0, 0, canvasEl.width, canvasEl.height)
}
})
document.addEventListener(
'mousedown',
(e) => {
render.play()
updateCoords(e)
animateParticules(pointerX, pointerY)
},
false
)
setCanvasSize(canvasEl)
window.addEventListener(
'resize',
() => {
setCanvasSize(canvasEl)
},
false
)
}

View File

@@ -23,15 +23,20 @@ export default function Live2D() {
return <canvas id="live2d" className='cursor-pointer' width="280" height="250" onClick={handleClick} alt='切换主题' title='切换主题' />
}
/**
* 加载宠物
*/
function initLive2D() {
// 加载 waifu.css live2d.min.js waifu-tips.js
if (screen.width >= 768) {
Promise.all([
// loadExternalResource('https://cdn.zhangxinxu.com/sp/demo/live2d/live2d/js/live2d.js', 'js')
loadExternalResource('https://cdn.jsdelivr.net/gh/stevenjoezhang/live2d-widget@latest/live2d.min.js', 'js')
]).then((e) => {
// https://github.com/xiazeyu/live2d-widget-models
loadlive2d('live2d', BLOG.WIDGET_PET_LINK)
})
}
setTimeout(() => {
// 加载 waifu.css live2d.min.js waifu-tips.js
if (screen.width >= 768) {
Promise.all([
// loadExternalResource('https://cdn.zhangxinxu.com/sp/demo/live2d/live2d/js/live2d.js', 'js')
loadExternalResource('https://cdn.jsdelivr.net/gh/stevenjoezhang/live2d-widget@latest/live2d.min.js', 'js')
]).then((e) => {
// https://github.com/xiazeyu/live2d-widget-models
loadlive2d('live2d', BLOG.WIDGET_PET_LINK)
})
}
}, 1000)
}

View File

@@ -1,5 +1,6 @@
import { NotionRenderer } from 'react-notion-x'
import dynamic from 'next/dynamic'
import mediumZoom from 'medium-zoom'
import React from 'react'
const Code = dynamic(() =>
@@ -26,11 +27,32 @@ const NotionPage = ({ post }) => {
return <>{post?.summary || ''}</>
}
React.useEffect(() => {
addWatch4Dom()
const zoom = typeof window !== 'undefined' && mediumZoom({
container: '.notion-viewport',
background: 'rgba(0, 0, 0, 0.2)',
margin: getMediumZoomMargin()
})
return <div id='container'>
const zoomRef = React.useRef(zoom ? zoom.clone() : null)
React.useEffect(() => {
addWatch4Dom()
// 将相册gallery下的图片加入放大功能
// const container = document?.getElementById('container')
const imgList = document?.querySelectorAll('.notion-collection-card-cover img')
if (imgList && zoomRef.current) {
for (let i = 0; i < imgList.length; i++) {
(zoomRef.current).attach(imgList[i])
}
}
const cards = document.getElementsByClassName('notion-collection-card')
for (const e of cards) {
e.removeAttribute('href')
}
})
return <div id='container' className='max-w-4xl mx-auto'>
<NotionRenderer
recordMap={post.blockMap}
mapPageUrl={mapPageUrl}
@@ -44,8 +66,6 @@ const NotionPage = ({ post }) => {
</div>
}
export default NotionPage
/**
* 监听DOM变化
* @param {*} element
@@ -116,3 +136,23 @@ const mapPageUrl = id => {
// return 'https://www.notion.so/' + id.replace(/-/g, '')
return '/article/' + id.replace(/-/g, '')
}
function getMediumZoomMargin() {
const width = window.innerWidth
if (width < 500) {
return 8
} else if (width < 800) {
return 20
} else if (width < 1280) {
return 30
} else if (width < 1600) {
return 40
} else if (width < 1920) {
return 48
} else {
return 72
}
}
export default NotionPage