diff --git a/components/CursorDot.js b/components/CursorDot.js new file mode 100644 index 00000000..72fef5ca --- /dev/null +++ b/components/CursorDot.js @@ -0,0 +1,97 @@ +import { useEffect } from 'react'; + +const CursorDot = () => { + useEffect(() => { + // 创建小白点元素 + const dot = document.createElement('div'); + dot.classList.add('cursor-dot'); + document.body.appendChild(dot); + + // 鼠标坐标和缓动目标坐标 + let mouse = { x: -100, y: -100 }; // 初始位置在屏幕外 + let dotPos = { x: mouse.x, y: mouse.y }; + + // 监听鼠标移动 + const handleMouseMove = (e) => { + mouse.x = e.clientX; + mouse.y = e.clientY; + }; + document.addEventListener('mousemove', handleMouseMove); + + // 监听鼠标悬停在可点击对象上的事件 + const handleMouseEnter = () => { + dot.classList.add('cursor-dot-hover'); // 添加放大样式 + }; + const handleMouseLeave = () => { + dot.classList.remove('cursor-dot-hover'); // 移除放大样式 + }; + + + // 为所有可点击元素和包含 hover 或 group-hover 类名的元素添加事件监听 + const clickableElements = document.querySelectorAll( + 'a, button, [role="button"], [onclick], [cursor="pointer"], [class*="hover"], [class*="group-hover"]' + ); + clickableElements.forEach((el) => { + el.addEventListener('mouseenter', handleMouseEnter); + el.addEventListener('mouseleave', handleMouseLeave); + }); + + // 动画循环:延迟更新小白点位置 + const updateDotPosition = () => { + const damping = 0.2; // 阻尼系数,值越小延迟越明显 + dotPos.x += (mouse.x - dotPos.x) * damping; + dotPos.y += (mouse.y - dotPos.y) * damping; + + // 更新DOM + dot.style.left = `${dotPos.x}px`; + dot.style.top = `${dotPos.y}px`; + + requestAnimationFrame(updateDotPosition); + }; + + // 启动动画 + updateDotPosition(); + + // 清理函数 + return () => { + document.removeEventListener('mousemove', handleMouseMove); + clickableElements.forEach((el) => { + el.removeEventListener('mouseenter', handleMouseEnter); + el.removeEventListener('mouseleave', handleMouseLeave); + }); + document.body.removeChild(dot); + }; + }, []); + + return ( + + ); +}; + +export default CursorDot; \ No newline at end of file diff --git a/components/Lenis.js b/components/Lenis.js index b0ed5ed8..43b1c062 100644 --- a/components/Lenis.js +++ b/components/Lenis.js @@ -1,52 +1,53 @@ -/** - * 鼠标滚动阻尼感 - */ -import { useEffect } from 'react' +import { useEffect, useRef } from 'react' import { loadExternalResource } from '@/lib/utils' /** - * 鼠标点击烟花特效 + * 滚动阻尼特效 + * 目前只用在proxio主题 * @returns */ const Lenis = () => { + const lenisRef = useRef(null) // 用于存储 Lenis 实例 useEffect(() => { // 异步加载 async function loadLenis() { - loadExternalResource( - '/js/lenis.js', - 'js' - ).then(() => { - console.log('Lenis',window.Lenis) - if(!window.Lenis) { + loadExternalResource('/js/lenis.js', 'js').then(() => { + // console.log('Lenis', window.Lenis) + if (!window.Lenis) { console.error('Lenis not loaded') return } const Lenis = window.Lenis - // 创建 Lenis 实例 - const lenis = new Lenis({ - duration: 1.2, - easing: (t) => Math.min(1, 1.001 - Math.pow(2, -10 * t)), // https://www.desmos.com/calculator/brs54l4xou - direction: 'vertical', // vertical, horizontal - gestureDirection: 'vertical', // vertical, horizontal, both - smooth: true, - mouseMultiplier: 1, - smoothTouch: false, - touchMultiplier: 2, - infinite: false, - }) - - //get scroll value - lenis.on('scroll', ({ scroll, limit, velocity, direction, progress }) => { console.log({ scroll, limit, velocity, direction, progress }) - }) - - function raf(time) { - lenis.raf(time) - requestAnimationFrame(raf) - } - - requestAnimationFrame(raf) + // 创建 Lenis 实例 + const lenis = new Lenis({ + duration: 1.2, + easing: (t) => Math.min(1, 1.001 - Math.pow(2, -10 * t)), // https://www.desmos.com/calculator/brs54l4xou + direction: 'vertical', // vertical, horizontal + gestureDirection: 'vertical', // vertical, horizontal, both + smooth: true, + mouseMultiplier: 1, + smoothTouch: false, + touchMultiplier: 2, + infinite: false, + }) + + // 存储实例到 ref + lenisRef.current = lenis + + // 监听滚动事件 + // lenis.on('scroll', ({ scroll, limit, velocity, direction, progress }) => { + // // console.log({ scroll, limit, velocity, direction, progress }) + // }) + + // 动画帧循环 + function raf(time) { + lenis.raf(time) + requestAnimationFrame(raf) + } + + requestAnimationFrame(raf) }) } @@ -54,6 +55,11 @@ const Lenis = () => { return () => { // 在组件卸载时清理资源 + if (lenisRef.current) { + lenisRef.current.destroy() // 销毁 Lenis 实例 + lenisRef.current = null + // console.log('Lenis instance destroyed') + } } }, []) diff --git a/public/images/themes-preview/proxio.png b/public/images/themes-preview/proxio.png new file mode 100644 index 00000000..8aa0a3e1 Binary files /dev/null and b/public/images/themes-preview/proxio.png differ diff --git a/themes/proxio/components/Announcement.js b/themes/proxio/components/Announcement.js index 2a72cea0..24de87eb 100644 --- a/themes/proxio/components/Announcement.js +++ b/themes/proxio/components/Announcement.js @@ -13,7 +13,7 @@ const Announcement = ({ post, className }) => {
+
{siteConfig('PROXIO_CTA_DESCRIPTION')}
{siteConfig('PROXIO_CTA_BUTTON') && ( <> + className='inline-flex items-center justify-center rounded-2xl bg-white px-7 py-[14px] text-center text-base font-medium text-dark shadow-1 transition duration-300 ease-in-out hover:bg-gray-2'> {siteConfig('PROXIO_CTA_BUTTON_TEXT')} > diff --git a/themes/proxio/components/Footer.js b/themes/proxio/components/Footer.js index 427f913c..0f68f4ab 100644 --- a/themes/proxio/components/Footer.js +++ b/themes/proxio/components/Footer.js @@ -1,168 +1,96 @@ +import AnalyticsBusuanzi from '@/components/AnalyticsBusuanzi' +import { BeiAnGongAn } from '@/components/BeiAnGongAn' +import BeiAnSite from '@/components/BeiAnSite' +import CopyRightDate from '@/components/CopyRightDate' +import DarkModeButton from '@/components/DarkModeButton' +import LazyImage from '@/components/LazyImage' +import PoweredBy from '@/components/PoweredBy' import { siteConfig } from '@/lib/config' -import SocialButton from '@/themes/fukasawa/components/SocialButton' -import { Logo } from './Logo' -import { SVGFooterCircleBG } from './svg/SVGFooterCircleBG' +import { useGlobal } from '@/lib/global' import Link from 'next/link' +import CONFIG from '../config' +import SocialButton from './SocialButton' + +/** + * 网页底脚 + */ +export const Footer = ({ title }) => { + const { siteInfo } = useGlobal() + const PROXIO_FOOTER_LINKS = siteConfig('PROXIO_FOOTER_LINKS', [], CONFIG) -/* eslint-disable @next/next/no-img-element */ -export const Footer = props => { - const footerPostCount = siteConfig('PROXIO_FOOTER_POST_COUNT', 2) - const latestPosts = props?.latestPosts - ? props?.latestPosts.slice(0, footerPostCount) - : [] - const PROXIO_FOOTER_LINK_GROUP = siteConfig('PROXIO_FOOTER_LINK_GROUP', []) return ( - <> - {/* */} -