完善周边网站美化效果

作者:

[collapse title=”新增页脚Dev样式 页脚开发历时” color=”indigo”]

<!-- 页脚运行时间 -->
<div class="github-badge-big">
    <span class="badge-subject"><i class="fa fa-clock-o"></i> 项目历时:</span>
    <span class="badge-value bg-apricots">
        <span id="footer_running_days" class="odometer"></span> 天
        <span id="footer_running_hours"></span> 小时
        <span id="footer_running_mins"></span> 分钟
        <span id="footer_running_secs"></span> 秒
    </span>
    <i class="footer-love-icon2">♥</i>
</div>

<!-- 备案号 放在项目历时下方 -->
<div class="github-badge-big">
    <span class="badge-subject"><i class="fa fa-id-card"></i> 备案号 </span>
    <a href="https://beian.miit.gov.cn/" target="_blank" one-link-mark="yes">苏ICP备1234567890号</a>
</div>

<script no-pjax="">
// 页脚项目历时(完全同步公告写法)
(function() {
  const dEl = document.getElementById("footer_running_days");
  const hEl = document.getElementById("footer_running_hours");
  const mEl = document.getElementById("footer_running_mins");
  const sEl = document.getElementById("footer_running_secs");
  if (!dEl) return;
  
  // 这里和你公告的 PROJECT_START_TIME 保持一致
  const start = new Date(2026, 3, 20);

  function update() {
    const diff = Date.now() - start;
    const d = Math.floor(diff / 86400000);
    const h = Math.floor((diff % 86400000) / 3600000);
    const m = Math.floor((diff % 3600000) / 60000);
    const s = Math.floor((diff % 60000) / 1000);

    dEl.textContent = d;
    hEl.textContent = h < 10 ? '0' + h : h;
    mEl.textContent = m < 10 ? '0' + m : m;
    sEl.textContent = s < 10 ? '0' + s : s;
  }

  update();
  if (!window.footerRunTimeInterval) window.footerRunTimeInterval = setInterval(update, 1000);
})();

// 页脚爱心动画 + 点击飘字
function initFooterLove() {
    const loveIcon = document.querySelector(".footer-love-icon2");
    const footer = document.getElementById("footer");
    if (!loveIcon || !footer) return;

    loveIcon.replaceWith(loveIcon.cloneNode(true));
    const newLove = document.querySelector(".footer-love-icon2");

    Object.assign(newLove.style, {
        display: "inline-block",
        color: "#ffffff",
        fontSize: "18px",
        transition: "color 0.3s ease",
        cursor: "pointer",
        marginLeft: "6px"
    });

    if (!document.querySelector('#heartBeatStyle')) {
        const style = document.createElement("style");
        style.id = "heartBeatStyle";
        style.textContent = `
            @keyframes heartBeatReal2 {
                0% { transform: scale(1); }
                15% { transform: scale(1.2); }
                30% { transform: scale(1); }
                45% { transform: scale(1.2); }
                60% { transform: scale(1); }
                100% { transform: scale(1); }
            }
        `;
        document.head.appendChild(style);
    }

    footer.addEventListener("mouseenter", () => {
        newLove.style.color = "#e62445";
        newLove.style.animation = "heartBeatReal2 1.2s ease infinite";
    });
    footer.addEventListener("mouseleave", () => {
        newLove.style.color = "#ffffff";
        newLove.style.animation = "none";
    });

    const random = (min, max) => Math.random() * (max - min) + min;
    newLove.addEventListener("click", e => {
        e.preventDefault();
        window.getSelection?.removeAllRanges?.();
        let cur = parseInt(localStorage.getItem("loveClickCount") || 0);
        cur++;
        localStorage.setItem("loveClickCount", cur);
        if (window.updateLoveCount) window.updateLoveCount();

        const rect = newLove.getBoundingClientRect();
        const pop = document.createElement("span");
        pop.innerText = "+1";
        Object.assign(pop.style, {
            position: "fixed",
            left: `${rect.left + rect.width / 2 - 8}px`,
            top: `${rect.top - 6}px`,
            zIndex: "99999999",
            color: "#e62445",
            fontWeight: "bold",
            fontSize: "16px",
            pointerEvents: "none",
            opacity: "1"
        });
        document.body.appendChild(pop);

        const moveX = random(-6, 6);
        const rotate = random(-25, 25);
        const duration = 1200;
        const start = performance.now();
        function animate() {
            const t = performance.now() - start;
            const p = Math.min(t / duration, 1);
            const k = 1 - Math.pow(1 - p, 3);
            pop.style.transform = `translate(${moveX * k}px, ${-35 * k}px) rotate(${rotate * k}deg)`;
            pop.style.opacity = 1 - k;
            p < 1 ? requestAnimationFrame(animate) : pop.remove();
        }
        requestAnimationFrame(animate);
    });
    newLove.addEventListener("mousedown", e => e.preventDefault());
    newLove.ondragstart = () => false;
}
document.addEventListener('DOMContentLoaded', initFooterLove);
window.addEventListener('load', initFooterLove);
document.addEventListener('pjax:success', initFooterLove);
document.addEventListener('pjax:end', initFooterLove);
</script>
[/collapse]

[collapse title=”新增公告进度条 公告爱心点赞特效” color=”indigo”]

<!-- ======================================
     🔥 【顶部可配置区域 - 改这里就够了】
     🧊 进度条颜色:
        bg-orange 橙色 | bg-blue 蓝色 | bg-red 红色 | bg-green 绿色
     🧊 爱心清零:控制台输入 resetlove()
====================================== -->
<script no-pjax="">
// DDL 死线
const TEXT_TITLE1 = "斩杀线 6月22日";
const PROGRESS_START = [2026, 3, 20];
const PROGRESS_END   = [2026, 5, 22];
// DDL进度条颜色
const PROGRESS_BAR_COLOR = "bg-orange";

// 开发进度
const TEXT_TITLE2 = "Demo开发进度";
const DEV_PROGRESS = 30;
const DEV_HOVER_TEXT = "急急急,你别急"; 
// 开发进度条颜色 直白命名
const DEV_BAR_COLOR = "bg-blue";

// 项目历时
const PROJECT_START_TIME = [2026, 3, 20];

// 全局爱心更新函数(两边共用)
window.updateLoveCount = function() {
  const count = localStorage.getItem('loveClickCount') || 0;
  window.loveCountState = parseInt(count);
  
  const el = document.getElementById('loveCount');
  if (el) el.textContent = count;
};

// 爱心清零
window.resetlove = function() {
  if (confirm('确定清零爱心计数?')) {
    localStorage.removeItem('loveClickCount');
    window.updateLoveCount();
    alert('✅ 已清零');
  }
};
</script>

<!-- 进度条 + 项目历时 -->
<div class="progress-wrapper" style="padding:0">
  <div class="progress-info" style="display:flex;justify-content:space-between;align-items:center">
    <div class="progress-label" style="white-space:nowrap;"><script>document.write(TEXT_TITLE1)</script></div>
    <div id="yearprogress_text_container">
      <span id="yearprogress_progresstext"></span>
      <span id="yearprogress_progresstext_full"></span>
    </div>
  </div>
  <div class="progress">
    <div id="yearprogress_progressbar" class="progress-bar">
      <div class="bubble-container">
        <div class="bubble"></div><div class="bubble"></div><div class="bubble"></div>
        <div class="bubble"></div><div class="bubble"></div><div class="bubble"></div>
        <div class="bubble"></div><div class="bubble"></div><div class="bubble"></div>
        <div class="bubble"></div>
      </div>
    </div>
  </div>
</div>

<div class="progress-wrapper" style="padding:0;margin-top:8px;">
  <div class="progress-info" style="display:flex;justify-content:space-between;align-items:center">
    <div class="progress-label" style="white-space:nowrap;"><script>document.write(TEXT_TITLE2)</script></div>
    <!-- 开发进度 悬浮容器 -->
    <div id="devprogress_text_container">
      <span id="devprogress_progresstext"></span>
      <span id="devprogress_progresstext_full"></span>
    </div>
  </div>
  <div class="progress">
    <div id="devprogress_progressbar" class="progress-bar">
      <div class="bubble-container">
        <div class="bubble"></div><div class="bubble"></div><div class="bubble"></div>
        <div class="bubble"></div><div class="bubble"></div><div class="bubble"></div>
        <div class="bubble"></div><div class="bubble"></div><div class="bubble"></div>
        <div class="bubble"></div>
      </div>
    </div>
  </div>
</div>

<!-- 项目历时 + 爱心(两行全部居中) -->
<div class="github-badge-big" style="margin-top:12px;position:relative;text-align:center;">
  <span class="badge-subject">项目历时:</span>
  <i class="footer-love-icon">♥</i>
  <span id="loveCount" class="love-count">0</span>

  <!-- 时间单独一行并居中 -->
  <span class="badge-value bg-apricots" style="display:block;text-align:center;margin-top:4px;">
    <span id="blog_running_days" class="odometer"></span> 天
    <span id="blog_running_hours"></span> 小时
    <span id="blog_running_mins"></span> 分钟
    <span id="blog_running_secs"></span> 秒
  </span>
</div>

<script no-pjax="">
// 提交进度(DDL)
(function() {
  function refresh() {
    const start = new Date(...PROGRESS_START);
    const end = new Date(...PROGRESS_END);
    const now = new Date();
    const total = end - start;
    const past = now - start;
    let progress = 0;
    if (past > 0 && past < total) progress = (past / total * 100).toFixed(5);
    else if (past >= total) progress = 100;
    const short = parseFloat(progress).toFixed(2);
    $("#yearprogress_progresstext").text(short + "%");
    $("#yearprogress_progresstext_full").text(progress + "%");
    $("#yearprogress_progressbar").css("width", progress + "%");
    // 应用直白颜色类名
    $("#yearprogress_progressbar").addClass(PROGRESS_BAR_COLOR);
  }
  refresh();
  if (!window.yearProgressInterval) {
    window.yearProgressInterval = setInterval(refresh, 500);
  }
})();

// 开发进度
(function() {
  $("#devprogress_progresstext").text(DEV_PROGRESS + ".00%");
  $("#devprogress_progresstext_full").text(DEV_HOVER_TEXT);
  $("#devprogress_progressbar").css("width", DEV_PROGRESS + "%");
  // 应用直白颜色类名
  $("#devprogress_progressbar").addClass(DEV_BAR_COLOR);
})();

// 爱心点击
(function() {
  const icon = document.querySelector(".footer-love-icon");
  const count = document.getElementById("loveCount");
  const box = document.querySelector(".github-badge-big");
  if (!icon || !count) return;

  // 初始化
  window.updateLoveCount();

  function rand(a, b) { return Math.random() * (b - a) + a }
  function pop() {
    const el = document.createElement("span");
    el.textContent = "+1";
    el.style.cssText = "position:absolute;color:#e62445;font-weight:bold;font-size:16px;pointer-events:none;left:" + (icon.offsetLeft - 5) + "px;top:" + (icon.offsetTop - 5) + "px;opacity:1";
    box.appendChild(el);
    const x = rand(-8, 8);
    const r = rand(-30, 30);
    const start = performance.now();
    function run() {
      const t = performance.now() - start;
      const p = Math.min(t / 1200, 1);
      const k = 1 - Math.pow(1 - p, 3);
      el.style.transform = `translate(${x*k}px,${-35*k}px)rotate(${r*k}deg)`;
      el.style.opacity = 1 - k;
      if (p < 1) requestAnimationFrame(run);
      else el.remove();
    }
    requestAnimationFrame(run);
  }

  icon.addEventListener("click", e => {
    e.preventDefault();
    window.getSelection?.removeAllRanges?.();
    
    // 统一计数逻辑
    let cur = parseInt(localStorage.getItem("loveClickCount") || 0);
    cur++;
    localStorage.setItem("loveClickCount", cur);
    
    // 全局更新
    window.updateLoveCount();
    pop();
  });
  icon.addEventListener("mousedown", e => e.preventDefault());
  icon.ondragstart = () => false;
})();

// 爱心心跳
(function() {
  const card = document.getElementById("leftbar_announcement");
  const icon = document.querySelector(".footer-love-icon");
  if (!card || !icon) return;
  Object.assign(icon.style, {
    display: "inline-block", color: "#fff", fontSize: "18px",
    transition: "color 0.3s", cursor: "pointer", marginRight: "4px"
  });
  const style = document.createElement("style");
  style.textContent = "@keyframes heartBeatReal{0%{transform:scale(1)}15%{transform:scale(1.2)}30%{transform:scale(1)}45%{transform:scale(1.2)}60%{transform:scale(1)}100%{transform:scale(1)}}";
  document.head.appendChild(style);
  card.addEventListener("mouseenter", () => { icon.style.color = "#e62445"; icon.style.animation = "heartBeatReal 1.2s infinite" });
  card.addEventListener("mouseleave", () => { icon.style.color = "#fff"; icon.style.animation = "none" });
})();

// 项目历时
(function() {
  const dEl = document.getElementById("blog_running_days");
  const hEl = document.getElementById("blog_running_hours");
  const mEl = document.getElementById("blog_running_mins");
  const sEl = document.getElementById("blog_running_secs");
  if (!dEl) return;
  const start = new Date(...PROJECT_START_TIME);

  function update() {
    const diff = Date.now() - start;
    const d = Math.floor(diff / 86400000);
    const h = Math.floor((diff % 86400000) / 3600000);
    const m = Math.floor((diff % 3600000) / 60000);
    const s = Math.floor((diff % 60000) / 1000);

    dEl.textContent = d;
    hEl.textContent = h < 10 ? '0' + h : h;
    mEl.textContent = m < 10 ? '0' + m : m;
    sEl.textContent = s < 10 ? '0' + s : s;
  }

  update();
  if (!window.runTimeInterval) window.runTimeInterval = setInterval(update, 1000);
})();
</script>

<style>
/* 自定义直白颜色类 - bg-xxx 一看就懂 */
.bg-orange { background-color: #fd7e14 !important; }
.bg-blue   { background-color: #0d6efd !important; }
.bg-red    { background-color: #dc3545 !important; }
.bg-green  { background-color: #198754 !important; }
.bg-yellow { background-color: #ffc107 !important; }

/* 两个进度条共用悬浮效果 */
#yearprogress_text_container,
#devprogress_text_container{
  font-size:14px;color:#333;line-height:22px;text-align:right;width:110px;
  height:22px;overflow:hidden;user-select:none
}
#yearprogress_text_container>span,
#devprogress_text_container>span{
  transition:transform .3s ease;display:block
}
#yearprogress_text_container:hover>span,
#devprogress_text_container:hover>span{
  transform:translateY(-22px)
}
.love-count{font-size:14px;color:#e62445;font-weight:500;margin-right:6px}
.progress{height:12px;border-radius:6px;background:#e9ecef;overflow:hidden}
.progress-bar{position:relative;height:100%;border-radius:6px}
.bubble-container{position:absolute;inset:0;pointer-events:none}
.bubble{position:absolute;bottom:-20px;background:rgba(255,255,255,.35);opacity:.8;animation:bubbleUp linear infinite}
.bubble:nth-child(1){width:3px;height:3px;left:5%;animation-duration:2.2s}
.bubble:nth-child(2){width:5px;height:5px;left:15%;animation-duration:3.8s}
.bubble:nth-child(3){width:4px;height:4px;left:25%;animation-duration:2.6s}
.bubble:nth-child(4){width:6px;height:6px;left:38%;animation-duration:4.2s}
.bubble:nth-child(5){width:3px;height:3px;left:48%;animation-duration:2.9s}
.bubble:nth-child(6){width:5px;height:5px;left:60%;animation-duration:3.5s}
.bubble:nth-child(7){width:4px;height:4px;left:70%;animation-duration:2.4s}
.bubble:nth-child(8){width:6px;height:6px;left:80%;animation-duration:4.5s}
.bubble:nth-child(9){width:3px;height:3px;left:88%;animation-duration:3.1s}
.bubble:nth-child(10){width:4px;height:4px;left:95%;animation-duration:2.7s}
@keyframes bubbleUp{0%{transform:translateY(0)scale(1);opacity:.7}50%{opacity:.9}100%{transform:translateY(-120px)scale(1.1);opacity:0}}
</style>

[/collapse]

[collapse title=”新增主页卡片3D效果” color=”indigo”]


<!--鼠标悬停3D效果start-->
<style>
/* 开启3D空间 */
article.post:not(.post-full),
.shuoshuo-preview-container {
  transform-style: preserve-3d !important;
  transition: all 0.3s ease;
}

/* 常态:文字不做任何3D偏移 */
article.post:not(.post-full) header.post-header,
article.post:not(.post-full) a.post-title,
article.post:not(.post-full) div.post-meta,
.shuoshuo-preview-container .shuoshuo-title,
.shuoshuo-preview-container .shuoshuo-content {
  position: relative !important;
  transition: all 0.3s cubic-bezier(.03,.98,.52,.99);
  will-change: transform, text-shadow;
  /* 初始无3D、无阴影 */
  transform: translateZ(0px);
  text-shadow: none;
}

/* 🔥 鼠标悬浮卡片时:文字才开启3D上浮 + 立体阴影 */
article.post:not(.post-full):hover header.post-header,
article.post:not(.post-full):hover a.post-title,
article.post:not(.post-full):hover div.post-meta,
.shuoshuo-preview-container:hover .shuoshuo-title,
.shuoshuo-preview-container:hover .shuoshuo-content {
  transform: translateZ(30px) !important;
  /* 3D立体文字阴影,柔和有层次 */
  text-shadow: 0 8px 16px rgba(0,0,0,0.15), 
               0 4px 8px rgba(0,0,0,0.1);
}
</style>

<script src="https://cdn.jsdelivr.net/gh/huangwb8/bloghelper@latest/js/mobile-detect.js"></script>
<script type="text/javascript" src="https://cdn.jsdelivr.net/gh/huangwb8/bloghelper@latest/vanilla3D/vanilla-tilt.js"></script>

<script type="text/javascript">
var md = new MobileDetect(window.navigator.userAgent);

if(!md.phone() && !md.tablet()){
    window.pjaxLoaded = function(){
        // 销毁旧实例防冲突
        document.querySelectorAll("article.post:not(.post-full), .shuoshuo-preview-container").forEach(el => {
            if (el.vanillaTilt) el.vanillaTilt.destroy();
        });

        // 文章卡片3D倾斜
        VanillaTilt.init(document.querySelectorAll("article.post:not(.post-full)"),{
            reverse:false,
            max:4,
            startX:0,
            startY:0,
            perspective:1000,
            scale:1.02,
            speed:300,
            transition:true,
            axis:null,
            reset:true,
            easing:"cubic-bezier(.03,.98,.52,.99)",
            glare:true,
            "max-glare":0.7,
            "glare-prerender":false,
            gyroscope:false
        });

        // 说说卡片3D倾斜
        VanillaTilt.init(document.querySelectorAll(".shuoshuo-preview-container"),{
            reverse:false,  // 是否反转倾斜方向
            max:4,     // 最大的倾斜角度(度)
            startX:0,      // X轴上的起始倾斜,单位为度。
            startY:0,      // Y轴上的起始倾斜,单位为度。
            perspective:1000,   // 转换角度,越低倾斜越极端
            scale:1.02,      // 缩放比例,2 = 200%, 1.5 = 150%, 等等..
            speed:300,    // 进入/退出 过渡的速度
            transition:true,   // 是否在进入/退出的时候设置过渡效果
            xis:null,   // 设置禁用哪个轴的反转,值为"x"或者"y"或者null
            reset:true,   // 设置在退出时清除倾斜效果
            easing:"cubic-bezier(.03,.98,.52,.99)",    // 设置进入退出时过渡的贝塞尔曲线
            glare:true,// 设置是否拥有炫光效果,即透明度渐变效果
            "max-glare":0.7,      // 设置最大的透明效果,1=100%,0.5=50%
            "glare-prerender":false,  // false, VanillaTilt为你创建透明炫光元素,否则你需要自己在.jstilt-glare>.js-tilt-glare-inner中自己添加render函数
            "mouse-event-element":null,   // css选择器或者链接到HTML的元素,他将监听该元素上的鼠标事件
            "full-page-listening":false,  // 是否监听整个页面的鼠标移动事件,若为true,他将监听这个页面,而非选中元素
            gyroscope:false,   // 是否开启陀螺仪的方向检测
            gyroscopeMinAngleX: 0,  //陀螺仪最小角度X
            gyroscopeMaxAngleX: 0,  //陀螺仪最大角度X
            gyroscopeMinAngleY: 0,  //陀螺仪最小角度
            gyroscopeMaxAngleY: 0,  //陀螺仪最大角度
            gyroscopeSamples: 10  //陀螺仪样品
        });
    }

    $(window.pjaxLoaded);
    $(document)?.on('pjax:end', window.pjaxLoaded);
}
</script>
<!--鼠标悬停3D效果end-->

[/collapse]

[collapse title=”新增鼠标特效” color=”indigo”]

<!--鼠标样式:两个同心圆,大圆追小圆-->
<style type="text/css">
#cursor{position:fixed;width:16px;height:16px;background:#009688;border-radius:8px;opacity:0.25;z-index:10086;pointer-events:none;transition:0.2s ease-in-out;transition-property:background,opacity,transform}
#cursor.hidden{opacity:0}
#cursor.hover{opacity:0.1;transform:scale(2.5)}
#cursor.active{opacity:0.5;transform:scale(0.5)}
#clickME{cursor:pointer;display:inline-block;border:1px solid #009688}
</style>
<script src="https://cdn.jsdelivr.net/gh/huangwb8/bloghelper@latest/js/cursor_01.js"></script>
<!--鼠标样式结束-->

[/collapse]

评论

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注