mirror of
https://github.com/pengzhanbo/vuepress-theme-plume.git
synced 2026-04-23 10:58:13 +08:00
perf(theme): 优化首页 Hero 背景效果
This commit is contained in:
parent
cc4837c45d
commit
c6a2b8cab2
@ -1,9 +1,10 @@
|
||||
<script setup lang="ts">
|
||||
import { usePageFrontmatter, withBase } from 'vuepress/client'
|
||||
import { isLinkHttp } from 'vuepress/shared'
|
||||
import { computed } from 'vue'
|
||||
import { computed, ref } from 'vue'
|
||||
import VButton from '../VButton.vue'
|
||||
import { useDarkMode } from '../../composables/index.js'
|
||||
import { useHomeHeroFilterBackground } from '../../composables/home.js'
|
||||
import type { PlumeThemeHomeFrontmatter, PlumeThemeHomeHero } from '../../../shared/index.js'
|
||||
|
||||
const props = defineProps<PlumeThemeHomeHero>()
|
||||
@ -34,6 +35,9 @@ const heroBackground = computed(() => {
|
||||
|
||||
const hero = computed(() => props.hero ?? matter.value.hero ?? {})
|
||||
const actions = computed(() => hero.value.actions ?? [])
|
||||
|
||||
const canvas = ref<HTMLCanvasElement>()
|
||||
useHomeHeroFilterBackground(canvas, computed(() => props.background === 'filter-blur'))
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@ -41,9 +45,7 @@ const actions = computed(() => hero.value.actions ?? [])
|
||||
<div v-if="heroBackground" class="home-hero-bg" :style="heroBackground" />
|
||||
|
||||
<div v-if="background === 'filter-blur'" class="bg-filter">
|
||||
<div class="g g-1" />
|
||||
<div class="g g-2" />
|
||||
<div class="g g-3" />
|
||||
<canvas ref="canvas" width="32" height="32" />
|
||||
</div>
|
||||
|
||||
<div class="container">
|
||||
@ -181,52 +183,19 @@ const actions = computed(() => hero.value.actions ?? [])
|
||||
height: calc(100% + var(--vp-footer-height, 0px));
|
||||
}
|
||||
|
||||
.bg-filter::before {
|
||||
.bg-filter::after {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
z-index: 1;
|
||||
width: 100%;
|
||||
height: 20%;
|
||||
content: "";
|
||||
backdrop-filter: blur(150px);
|
||||
transform: translate3d(0, 0, 0);
|
||||
background: linear-gradient(var(--vp-c-bg) 0, transparent 100%);
|
||||
}
|
||||
|
||||
.g {
|
||||
position: absolute;
|
||||
opacity: 0.5;
|
||||
transform: translate3d(0, 0, 0);
|
||||
}
|
||||
|
||||
.g-1 {
|
||||
bottom: 100px;
|
||||
left: 50%;
|
||||
width: 714px;
|
||||
height: 390px;
|
||||
clip-path: polygon(0 10%, 30% 0, 100% 40%, 70% 100%, 20% 90%);
|
||||
background: var(--vp-c-yellow-3);
|
||||
transform: translate(-50%, 0);
|
||||
}
|
||||
|
||||
.g-2 {
|
||||
bottom: 0;
|
||||
left: 30%;
|
||||
width: 1000px;
|
||||
height: 450px;
|
||||
clip-path: polygon(10% 0, 100% 70%, 100% 100%, 20% 90%);
|
||||
background: var(--vp-c-red-3);
|
||||
transform: translate(-50%, 0);
|
||||
}
|
||||
|
||||
.g-3 {
|
||||
bottom: 0;
|
||||
left: 70%;
|
||||
width: 1000px;
|
||||
height: 450px;
|
||||
clip-path: polygon(80% 0, 100% 70%, 100% 100%, 20% 90%);
|
||||
background: var(--vp-c-purple-3);
|
||||
transform: translate(-50%, 0);
|
||||
.bg-filter canvas {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
/* =========== background filter end ======= */
|
||||
|
||||
56
theme/src/client/composables/home.ts
Normal file
56
theme/src/client/composables/home.ts
Normal file
@ -0,0 +1,56 @@
|
||||
import type { Ref } from 'vue'
|
||||
import { computed, onMounted, onUnmounted } from 'vue'
|
||||
import { useDarkMode } from './darkMode.js'
|
||||
|
||||
export function useHomeHeroFilterBackground(
|
||||
canvas: Ref<HTMLCanvasElement | undefined>,
|
||||
enable: Ref<boolean>,
|
||||
) {
|
||||
const isDark = useDarkMode()
|
||||
|
||||
let ctx: CanvasRenderingContext2D | null = null
|
||||
let t = 0
|
||||
let timer: number
|
||||
|
||||
const F = computed(() => isDark.value ? 32 : 220)
|
||||
|
||||
onMounted(() => {
|
||||
if (canvas.value && enable.value) {
|
||||
ctx = canvas.value.getContext('2d')!
|
||||
timer && window.cancelAnimationFrame(timer)
|
||||
run()
|
||||
}
|
||||
})
|
||||
|
||||
onUnmounted(() => {
|
||||
timer && window.cancelAnimationFrame(timer)
|
||||
})
|
||||
|
||||
function run() {
|
||||
for (let x = 0; x <= 35; x++) {
|
||||
for (let y = 0; y <= 35; y++)
|
||||
col(x, y, R(x, y, t), G(x, y, t), B(x, y, t))
|
||||
}
|
||||
t = t + 0.020
|
||||
timer = window.requestAnimationFrame(run)
|
||||
}
|
||||
|
||||
function col(x: number, y: number, r: number, g: number, b: number) {
|
||||
if (!ctx)
|
||||
return
|
||||
ctx.fillStyle = `rgb(${r},${g},${b})`
|
||||
ctx.fillRect(x, y, 1, 1)
|
||||
}
|
||||
|
||||
function R(x: number, y: number, t: number) {
|
||||
return (Math.floor(F.value + 36 * Math.cos((x * x - y * y) / 300 + t)))
|
||||
}
|
||||
|
||||
function G(x: number, y: number, t: number) {
|
||||
return (Math.floor(F.value + 36 * Math.sin((x * x * Math.cos(t / 4) + y * y * Math.sin(t / 3)) / 300)))
|
||||
}
|
||||
|
||||
function B(x: number, y: number, t: number) {
|
||||
return (Math.floor(F.value + 36 * Math.sin(5 * Math.sin(t / 9) + ((x - 100) * (x - 100) + (y - 100) * (y - 100)) / 1100)))
|
||||
}
|
||||
}
|
||||
@ -5,7 +5,7 @@ export * from './useNavLink.js'
|
||||
export * from './sidebar.js'
|
||||
export * from './aside.js'
|
||||
export * from './page.js'
|
||||
// export * from './readingTime.js'
|
||||
export * from './blog.js'
|
||||
export * from './locale.js'
|
||||
export * from './useRouteQuery.js'
|
||||
export * from './waterMark.js'
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user