1.首页主题魔改:顶部视频播放

1.首页主题魔改:顶部视频播放

功能介绍与重要提示

本指南将主题的静态首页顶部图,升级为一个支持视频背景、能够根据横竖屏自适应切换、并带有视差和滚动渐变等高级特效的动态媒体背景。

警告: 这是一项“魔改”级别的定制,涉及到覆盖主题的核心模板文件。在开始前,强烈建议您备份整个 themes/anzhiyu 文件夹,以防出现意外情况可以随时恢复。


第一步:替换核心布局文件

此修改需要替换掉主题中负责渲染页面头部的核心文件。

  1. 找到并打开文件
    themes/anzhiyu/layout/includes/header/index.pug

  2. 替换内容:将这个文件的全部内容,用下面提供的完整代码进行覆盖。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    // 优先级控制逻辑(独立作用域)
    if !theme.disable_top_img && page.top_img !== false
    if is_post()
    - var top_img = page.top_img || page.cover || page.randomcover
    else if is_page()
    - var top_img = page.top_img || theme.default_top_img
    else if is_home()
    // 首页专用媒体声明
    - var home_index_img = theme.index_img?.enable ? theme.index_img.path : false
    - var home_index_video = theme.index_video?.enable ? theme.index_video.path : false
    - var top_img = home_index_img || home_index_video || theme.default_top_img
    else
    - var top_img = page.top_img || theme.default_top_img

    if top_img !== false
    // 路径处理
    - var imgSource = top_img && top_img.indexOf('/') !== -1 ? url_for(top_img) : top_img
    // 首页专用路径
    - var homeImg = home_index_img ? url_for(home_index_img) : ''
    - var homeVideo = home_index_video ? url_for(home_index_video) : ''
    - var bg_img = is_home() ? (home_index_img || home_index_video) : imgSource

    - var site_title = page.title || page.tag || page.category || config.title
    - var isHomeClass = is_home() ? 'full_page' : 'not-home-page'
    - is_post() ? isHomeClass = 'post-bg' : isHomeClass
    else
    - var isHomeClass = 'not-top-img'
    else
    - var top_img = false
    - var isHomeClass = 'not-top-img'

    header#page-header(class=`${isHomeClass}`)
    !=partial('includes/header/nav', {}, {cache: true})
    if top_img !== false
    if is_post()
    if page.bilibili_bg
    !=partial('includes/bili-banner/index')
    else
    include ./post-info.pug
    if theme.dynamicEffect && theme.dynamicEffect.postTopWave
    section.main-hero-waves-area.waves-area
    svg.waves-svg(xmlns='http://www.w3.org/2000/svg', xlink='http://www.w3.org/1999/xlink', viewBox='0 24 150 28', preserveAspectRatio='none', shape-rendering='auto')
    defs
    path#gentle-wave(d='M -160 44 c 30 0 58 -18 88 -18 s 58 18 88 18 s 58 -18 88 -18 s 58 18 88 18 v 44 h -352 Z')
    g.parallax
    use(href='#gentle-wave', x='48', y='0')
    use(href='#gentle-wave', x='48', y='3')
    use(href='#gentle-wave', x='48', y='5')
    use(href='#gentle-wave', x='48', y='7')
    #post-top-cover
    img#post-top-bg(class='nolazyload' src=bg_img)
    else if is_home()
    // 媒体容器
    #home-media-container(
    data-landscape-img=home_index_img ? homeImg : ''
    data-portrait-img=home_index_img && theme.index_img.vpath ? url_for(theme.index_img.vpath) : ''
    data-landscape-video=home_index_video ? homeVideo : ''
    data-portrait-video=home_index_video && theme.index_video.vpath ? url_for(theme.index_video.vpath) : ''
    data-landscape-poster=home_index_video && theme.index_video.poster ? url_for(theme.index_video.poster) : ''
    data-portrait-poster=home_index_video && theme.index_video.vposter ? url_for(theme.index_video.vposter) : ''
    style="height:100%;background-attachment:fixed;z-index:0"
    )
    #site-info
    h1#site-title=site_title
    if theme.subtitle.enable
    - var loadSubJs = true
    #site-subtitle
    span#subtitle
    if(theme.social)
    #site_social_icons
    !=fragment_cache('social', function(){return partial('includes/header/social')})
    #scroll-down
    i.anzhiyufont.anzhiyu-icon-angle-down.scroll-down-effects
    else
    #page-site-info(style=`background-image: url(${imgSource})`)
    h1#site-title=site_title

第二步:添加自定义样式与脚本文件
  1. 创建CSS文件

    • themes/anzhiyu/source/css/ 目录下,新建一个文件,命名为 index_media.css
    • 将下面的CSS代码完整复制进去:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    /* index */

    #home-media-container {
    position: fixed; /* 改为固定定位 */
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    overflow: hidden;
    z-index: 0;

    /* 添加底部向上渐变遮罩 */
    -webkit-mask-image: linear-gradient(to top, transparent 0%, black 0%);
    mask-image: linear-gradient(to top, transparent 0%, black 0%);
    }

    .home-media {
    position: fixed; /* 同步改为固定定位 */
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;

    /* 添加透明度过渡 */
    transition: opacity 0.5s ease;
    opacity: 1;
    }

    /* 自定义加载动画容器 */
    .custom-loader {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    display: flex;
    justify-content: center;
    align-items: center;
    z-index: 10; /* 确保在视频上方 */
    pointer-events: none; /* 防止阻挡视频交互 */
    transition: opacity 0.5s ease; /* 淡出动画 */
    }

    /* 加载动画元素 - 修复尺寸问题 */
    .loader-animation {
    /* 修复:改为全屏覆盖模式 */
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    background-size: cover; /* 改为cover确保铺满屏幕 */
    background-position: center;
    background-repeat: no-repeat;
    animation: pulse 1.5s infinite ease-in-out;
    }

    /* 移动端优化 */
    @media screen and (max-width: 768px) {
    .loader-animation {
    background-size: cover; /* 移动端也保持cover模式 */
    }
    }

    /* 呼吸动画效果 */
    @keyframes pulse {
    0% { transform: scale(1); opacity: 0.8; }
    50% { transform: scale(1.02); opacity: 1; }
    100% { transform: scale(1); opacity: 0.8; }
    }
  2. 创建JS文件

    • themes/anzhiyu/source/js/ 目录下,新建一个文件,命名为 index_media.js
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    246
    247
    248
    249
    250
    251
    252
    253
    254
    255
    256
    257
    258
    259
    260
    261
    262
    263
    264
    265
    266
    267
    268
    269
    270
    271
    272
    273
    274
    275
    276
    277
    278
    279
    280
    281
    282
    283
    284
    285
    286
    287
    288
    289
    290
    291
    292
    293
    294
    295
    296
    297
    298
    299
    300
    301
    302
    303
    304
    305
    306
    307
    308
    309
    310
    311
    312
    313
    314
    315
    316
    317
    318
    319
    320
    321
    322
    323
    324
    325
    326
    327
    328
    329
    330
    331
    332
    333
    334
    335
    336
    337
    338
    339
    340
    341
    342
    343
    344
    345
    346
    347
    348
    349
    350
    351
    352
    353
    354
    355
    356
    357
    358
    359
    360
    361
    362
    363
    364
    365
    366
    367
    368
    369
    370
    371
    372
    373
    374
    375
    376
    377
    378
    379
    380
    381
    382
    383
    384
    385
    386
    387
    388
    389
    390
    391
    392
    393
    394
    395
    396
    397
    398
    399
    400
    401
    402
    403
    404
    405
    406
    407
    408
    409
    410
    411
    412
    413
    414
    415
    416
    417
    418
    419
    420
    421
    422
    423
    424
    425
    426
    427
    428
    429
    430
    431
    432
    433
    434
    435
    436
    437
    438
    439
    440
    441
    442
    443
    444
    445
    446
    447
    448
    449
    450
    451
    452
    453
    454
    455
    456
    457
    458
    459
    460
    461
    462
    463
    464
    465
    466
    467
    468
    469
    470
    471
    472
    473
    474
    475
    476
    477
    478
    479
    480
    481
    482
    483
    484
    485
    486
    487
    488
    489
    490
    491
    492
    493
    494
    495
    496
    497
    498
    499
    500
    501
    502
    503
    504
    505
    506
    507
    508
    509
    510
    511
    512
    513
    514
    515
    516
    517
    518
    519
    520
    521
    522
    523
    524
    525
    526
    527
    528
    529
    530
    531
    532
    533
    534
    535
    536
    537
    538
    539
    540
    541
    542
    543
    544
    545
    546
    547
    // ======================= 横竖屏自适应背景媒体加载器 =======================
    let lastOrientation = null; // 记录上一次的方向状态
    let isMediaInitializing = false; // 防止重复初始化的状态锁

    // ================= 新增滚动渐变效果函数 =================
    function initScrollFadeEffect() {
    const mediaContainer = document.getElementById('home-media-container');
    if (!mediaContainer) return;

    const mediaElement = mediaContainer.querySelector('.home-media');
    if (!mediaElement) return;

    // 节流函数优化性能
    function throttle(func, limit) {
    let lastFunc, lastRan;
    return function () {
    const context = this;
    const args = arguments;
    if (!lastRan) {
    func.apply(context, args);
    lastRan = Date.now();
    } else {
    clearTimeout(lastFunc);
    lastFunc = setTimeout(function () {
    if ((Date.now() - lastRan) >= limit) {
    func.apply(context, args);
    lastRan = Date.now();
    }
    }, limit - (Date.now() - lastRan));
    }
    }
    }

    // 处理滚动时的透明度变化
    function handleScrollFade() {
    const scrollY = window.scrollY;
    const windowHeight = window.innerHeight;

    // 计算透明度:从1(完全不透明)到0(完全透明)
    // 当滚动到一屏高度时,透明度变为0
    let opacity = 1 - (scrollY / windowHeight);
    opacity = Math.max(0, Math.min(1, opacity)); // 限制在0-1范围

    mediaElement.style.opacity = opacity;
    }

    // 节流处理滚动事件(每50ms检查一次)
    const throttledScrollHandler = throttle(handleScrollFade, 50);

    // 添加滚动监听
    window.addEventListener('scroll', throttledScrollHandler);

    // 初始化时执行一次
    handleScrollFade();

    // 存储当前滚动处理器以便后续移除
    return throttledScrollHandler;
    }


    // ================= 滚动渐变效果函数结束 =================

    // ================= 新增底部遮罩层控制函数 =================
    function initScrollMaskEffect() {
    const mediaContainer = document.getElementById('home-media-container');
    if (!mediaContainer) return;

    // 节流函数优化性能
    function throttle(func, limit) {
    let lastFunc, lastRan;
    return function () {
    const context = this;
    const args = arguments;
    if (!lastRan) {
    func.apply(context, args);
    lastRan = Date.now();
    } else {
    clearTimeout(lastFunc);
    lastFunc = setTimeout(function () {
    if ((Date.now() - lastRan) >= limit) {
    func.apply(context, args);
    lastRan = Date.now();
    }
    }, limit - (Date.now() - lastRan));
    }
    }
    }

    // 处理滚动时的遮罩变化
    function handleScrollMask() {
    const scrollY = window.scrollY;
    const windowHeight = window.innerHeight;

    // 计算遮罩高度(0-100%)
    let maskHeight = (scrollY / windowHeight) * 100;
    maskHeight = Math.min(100, Math.max(0, maskHeight));

    // 动态设置遮罩层高度
    mediaContainer.style.setProperty('--mask-height', `${maskHeight}%`);
    }

    // 节流处理滚动事件(每50ms检查一次)
    const throttledScrollHandler = throttle(handleScrollMask, 50);

    // 添加滚动监听
    window.addEventListener('scroll', throttledScrollHandler);

    // 初始化时执行一次
    handleScrollMask();

    // 返回处理器以便后续移除
    return throttledScrollHandler;
    }


    function initResponsiveBackground() {
    // 检查是否正在初始化
    if (isMediaInitializing) {
    return; // 如果正在初始化,则直接退出,防止冲突
    }
    isMediaInitializing = true; // 加锁

    const mediaContainer = document.getElementById('home-media-container');
    if (!mediaContainer) {
    isMediaInitializing = false; // 解锁
    return;
    }

    // 检测当前屏幕方向
    const currentIsPortrait = window.innerHeight > window.innerWidth;
    const currentOrientation = currentIsPortrait ? 'portrait' : 'landscape';

    // 如果方向未改变,则直接返回
    if (lastOrientation === currentOrientation) {
    return;
    }

    // 更新方向记录
    lastOrientation = currentOrientation;

    // 清除现有媒体元素和加载动画
    const existingMedia = mediaContainer.querySelector('.home-media');
    const existingLoader = mediaContainer.querySelector('.custom-loader');
    if (existingMedia) existingMedia.remove();
    if (existingLoader) existingLoader.remove();

    // 根据方向选择资源
    let mediaSrc, posterSrc, mediaType;
    if (currentIsPortrait) {
    mediaSrc = mediaContainer.dataset.portraitVideo || mediaContainer.dataset.portraitImg;
    posterSrc = mediaContainer.dataset.portraitPoster;
    mediaType = mediaContainer.dataset.portraitVideo ? 'video' : 'img';
    } else {
    mediaSrc = mediaContainer.dataset.landscapeVideo || mediaContainer.dataset.landscapeImg;
    posterSrc = mediaContainer.dataset.landscapePoster;
    mediaType = mediaContainer.dataset.landscapeVideo ? 'video' : 'img';
    }

    if (!mediaSrc) {
    console.error('[背景加载器] 未找到有效媒体资源');
    return;
    }

    console.log(`[背景加载器] 使用资源: ${mediaSrc} (类型: ${mediaType})`);

    // 创建媒体元素
    const mediaElement = document.createElement(mediaType);
    mediaElement.className = 'home-media';
    mediaElement.style.cssText = 'width:100%;height:100%;object-fit:cover';

    // ================= 设置初始透明度 =================
    mediaElement.style.opacity = '1';
    mediaElement.style.transition = 'opacity 0.5s ease';
    // ================================================

    // 在媒体容器添加媒体元素后调用效果函数
    mediaContainer.appendChild(mediaElement);
    addMediaEffects(mediaElement, mediaType); // 添加新功能

    console.log('[背景加载器] 媒体元素已创建');

    // 创建自定义加载动画容器
    const loaderContainer = document.createElement('div');
    loaderContainer.className = 'custom-loader';
    mediaContainer.prepend(loaderContainer);

    // 创建加载动画元素
    const loaderElement = document.createElement('div');
    loaderElement.className = 'loader-animation';

    // 设置加载动画样式(使用GIF)
    loaderElement.style.backgroundImage = `url(${posterSrc})`;
    loaderContainer.appendChild(loaderElement);

    // 视频特殊处理
    if (mediaType === 'video') {
    mediaElement.autoplay = true;
    mediaElement.muted = true;
    mediaElement.loop = true;
    mediaElement.playsInline = true;

    // 增强循环播放机制 - 备用处理
    mediaElement.addEventListener('ended', () => {
    console.log('[背景加载器] 视频播放结束,重新开始播放');
    mediaElement.currentTime = 0;
    mediaElement.play().catch(e => console.warn('重新播放失败:', e));
    });
    mediaElement.setAttribute('playsinline', '');
    mediaElement.setAttribute('webkit-playsinline', '');

    // 多源支持
    const source = document.createElement('source');
    source.src = mediaSrc;
    source.type = 'video/mp4';
    mediaElement.appendChild(source);

    // 处理自动播放限制
    const playPromise = mediaElement.play();
    if (playPromise !== undefined) {
    playPromise.catch(error => {
    console.warn('[背景加载器] 自动播放被阻止:', error);
    mediaElement.muted = true;
    mediaElement.play();
    });
    }

    // 视频加载完成后移除加载动画
    mediaElement.addEventListener('loadeddata', () => {
    loaderContainer.style.opacity = '0';
    setTimeout(() => {
    if (loaderContainer.parentNode) {
    loaderContainer.parentNode.removeChild(loaderContainer);
    }
    }, 500); // 淡出动画持续时间
    isMediaInitializing = false; // 解锁
    });
    } else {
    mediaElement.src = mediaSrc;
    mediaElement.loading = 'eager';

    // 图片加载完成后移除加载动画
    mediaElement.addEventListener('load', () => {
    loaderContainer.style.opacity = '0';
    setTimeout(() => {
    if (loaderContainer.parentNode) {
    loaderContainer.parentNode.removeChild(loaderContainer);
    }
    }, 500);
    isMediaInitializing = false; // 解锁
    });
    }

    // 错误处理
    mediaElement.onerror = function () {
    console.error(`[背景加载器] 资源加载失败: ${mediaSrc}`);
    this.style.display = 'none';
    isMediaInitializing = false; // 解锁

    // 尝试回退到备用类型
    console.warn('[背景加载器] 尝试回退到备用媒体');
    const fallbackType = mediaType === 'video' ? 'img' : 'video';
    const fallbackSrc = currentIsPortrait ?
    (mediaContainer.dataset.portraitImg || mediaContainer.dataset.portraitVideo) :
    (mediaContainer.dataset.landscapeImg || mediaContainer.dataset.landscapeVideo);

    if (fallbackSrc && fallbackSrc !== mediaSrc) {
    console.log(`[背景加载器] 使用备用资源: ${fallbackSrc}`);
    mediaElement.src = fallbackSrc;
    mediaElement.style.display = 'block';
    }
    };

    mediaContainer.appendChild(mediaElement);
    console.log('[背景加载器] 媒体元素已创建');

    // ================= 初始化滚动渐变效果 =================
    initScrollFadeEffect();
    }

    function addMediaEffects(mediaElement, mediaType) {
    if (mediaType === 'video') {
    // 获取当前方向
    const currentIsPortrait = window.innerHeight > window.innerWidth;

    // 竖屏模式下固定放大105%
    const baseScale = currentIsPortrait ? 1.05 : 1.2;
    mediaElement.style.transform = `scale(${baseScale})`;

    // 检测是否为iOS设备
    function isIOS() {
    return /iPad|iPhone|iPod/.test(navigator.userAgent) && !window.MSStream;
    }

    // 如果是iOS设备,直接禁用所有视差效果
    if (isIOS()) {
    console.log('[视差效果] 在iOS设备上,禁用所有视差效果');
    return; // 直接返回,不初始化任何视差效果
    }
    // 1. 添加缩放动画效果
    mediaElement.style.transform = 'scale(1.2)'; // 初始放大110%
    mediaElement.style.transition = 'transform 0.5s ease-out';

    // 在视频加载完成后触发缩放动画
    mediaElement.addEventListener('loadeddata', () => {
    // 竖屏模式保持105%缩放,不需要动画
    if (currentIsPortrait) {
    mediaElement.style.transform = 'scale(1.05)';
    }
    // 横屏模式执行缩放动画到正常大小
    else {
    setTimeout(() => {
    mediaElement.style.transform = 'scale(1)';
    }, 100);
    }
    });

    // 2. 添加视差效果(鼠标/陀螺仪)
    const mediaContainer = document.getElementById('page-header');
    mediaContainer.style.overflow = 'hidden';
    mediaElement.style.transformOrigin = 'center center';

    // 视差效果参数
    const parallaxIntensity = 0.05;
    const scaleIntensity = 0.05;
    let isGyroActive = false;

    // ================= 新增陀螺仪支持 =================
    // 检测陀螺仪支持
    function initGyroParallax() {
    if (typeof DeviceOrientationEvent !== 'undefined' && typeof DeviceOrientationEvent.requestPermission === 'function') {
    // iOS 13+ 需要权限
    DeviceOrientationEvent.requestPermission()
    .then(permissionState => {
    if (permissionState === 'granted') {
    setupGyroListeners();
    isGyroActive = true;
    }
    })
    .catch(console.error);
    } else if ('DeviceOrientationEvent' in window) {
    // Android和其他支持设备
    setupGyroListeners();
    isGyroActive = true;
    }

    return isGyroActive;
    }

    // 设置陀螺仪监听
    function setupGyroListeners() {
    window.addEventListener('deviceorientation', handleOrientation);
    }

    // 处理陀螺仪数据
    function handleOrientation(event) {
    // 竖屏模式使用105%基础缩放
    const baseScaleValue = currentIsPortrait ? 1.05 : 1;
    if (!isGyroActive) return;

    // 获取陀螺仪数据(beta: 前后倾斜, gamma: 左右倾斜)
    const beta = event.beta || 0; // 前后倾斜(-180到180)
    const gamma = event.gamma || 0; // 左右倾斜(-90到90)

    // 将角度转换为百分比偏移(归一化处理)
    const moveX = (gamma / 90) * parallaxIntensity * 100; // -100% 到 100%
    const moveY = (beta / 180) * parallaxIntensity * 100;

    // 应用视差效果
    mediaElement.style.transform = `
    translate(${moveX}%, ${moveY}%)
    scale(${baseScaleValue + scaleIntensity})
    `;
    }

    // ================= 鼠标视差效果 =================
    function initMouseParallax() {
    mediaContainer.addEventListener('mousemove', (e) => {
    const rect = mediaContainer.getBoundingClientRect();
    const x = (e.clientX - rect.left) / rect.width;
    const y = (e.clientY - rect.top) / rect.height;

    const moveX = (x - 0.5) * parallaxIntensity * 100;
    const moveY = (y - 0.5) * parallaxIntensity * 100;

    mediaElement.style.transform = `
    translate(${moveX}%, ${moveY}%)
    scale(${1 + scaleIntensity})
    `;
    });

    mediaContainer.addEventListener('mouseleave', () => {
    mediaElement.style.transform = 'scale(1)';
    });
    }

    // ================= 根据设备类型初始化 =================
    // 检测移动设备
    const isMobile = /Mobi|Android/i.test(navigator.userAgent);

    if (isMobile) {
    // 移动设备优先使用陀螺仪
    if (!initGyroParallax()) {
    // 不支持陀螺仪则回退到触摸事件
    initTouchParallax();
    }
    } else {
    // PC设备使用鼠标事件
    initMouseParallax();
    }

    // ================= 触摸事件回退方案 =================
    function initTouchParallax() {
    mediaContainer.addEventListener('touchmove', (e) => {
    e.preventDefault();
    const touch = e.touches[0];
    const rect = mediaContainer.getBoundingClientRect();
    const x = (touch.clientX - rect.left) / rect.width;
    const y = (touch.clientY - rect.top) / rect.height;

    const moveX = (x - 0.5) * parallaxIntensity * 50; // 移动强度减半
    const moveY = (y - 0.5) * parallaxIntensity * 50;

    mediaElement.style.transform = `
    translate(${moveX}%, ${moveY}%)
    scale(${1 + scaleIntensity * 0.5}) // 缩放强度减半
    `;
    });

    mediaContainer.addEventListener('touchend', () => {
    mediaElement.style.transform = 'scale(1)';
    });
    }

    // ================= 性能优化 =================
    // 页面不可见时暂停陀螺仪
    document.addEventListener('visibilitychange', () => {
    if (document.visibilityState === 'hidden') {
    isGyroActive = false;
    } else if (isMobile) {
    isGyroActive = initGyroParallax();
    }
    });
    }
    }

    // 在initMedia函数中调用新功能
    function initMedia() {
    if (document.readyState === 'loading') {
    document.addEventListener('DOMContentLoaded', function () {
    initResponsiveBackground();
    initScrollFadeEffect(); // 添加调用
    });
    } else {
    initResponsiveBackground();
    initScrollFadeEffect(); // 添加调用
    }
    }


    // ======================= 执行入口 =======================
    initMedia();

    // 防抖处理窗口变化
    let resizeTimer;
    window.addEventListener('resize', () => {
    clearTimeout(resizeTimer);
    resizeTimer = setTimeout(() => {
    // 计算当前方向状态
    const currentIsPortrait = window.innerHeight > window.innerWidth;
    const currentOrientation = currentIsPortrait ? 'portrait' : 'landscape';

    // 只有方向实际改变时才执行重载
    if (lastOrientation !== currentOrientation) {
    console.log('[背景加载器] 窗口大小变化,重新加载媒体');
    initResponsiveBackground();
    } else {
    console.log('[背景加载器] 窗口大小变化但方向未改变');
    // ================= 方向未变时重置透明度 =================
    initScrollFadeEffect();
    }
    }, 500);
    });

    // 页面可见性变化处理
    document.addEventListener('visibilitychange', () => {
    if (document.visibilityState === 'visible') {
    const video = document.querySelector('#home-media-container video');
    if (video && video.paused) {
    console.log('[背景加载器] 页面恢复可见,重新播放视频');
    video.play().catch(e => console.warn('视频恢复播放失败:', e));
    }
    // ================= 页面恢复可见时重置透明度 =================
    initScrollFadeEffect();
    }
    });

    // ========== 新增修复代码(直接加在现有代码后面) ========== //

    // 1. 缓存恢复检测(核心修复)
    window.addEventListener('pageshow', event => {
    if (event.persisted && location.pathname === '/') {
    console.log('[修复] 检测到缓存恢复主页,强制重置');
    lastOrientation = null;
    initResponsiveBackground();
    // ================= 缓存恢复时重置透明度 =================
    setTimeout(initScrollFadeEffect, 300);
    }
    });

    // 2. 路由变化监听(SPA兼容)
    window.addEventListener('popstate', () => {
    if (location.pathname === '/') {
    console.log('[修复] 检测到返回主页');
    setTimeout(() => {
    // 检查媒体元素是否存在
    const container = document.getElementById('home-media-container');
    if (!container?.querySelector('.home-media')) {
    lastOrientation = null;
    initResponsiveBackground();
    }
    // ================= 返回主页时重置透明度 =================
    initScrollFadeEffect();
    }, 300); // 延迟确保DOM更新
    }
    });

    // 3. 媒体状态自检(兜底方案)
    function checkMediaStatus() {
    if (location.pathname !== '/') return;

    const container = document.getElementById('home-media-container');
    if (!container) return;

    const hasMedia = container.querySelector('.home-media');
    if (!hasMedia) {
    console.log('[修复] 自检发现媒体丢失');
    lastOrientation = null;
    initResponsiveBackground();
    }
    // ================= 媒体自检时重置透明度 =================
    initScrollFadeEffect();
    }

    // 每0.5秒检查一次(轻量级检测)
    setInterval(checkMediaStatus, 500);



第三步:修改主题配置并注入新文件
  1. 打开主题配置文件 (themes/anzhiyu/_config.yml)。

  2. 修改首页顶部图配置

    • 找到 index_img 配置项,将其删除或注释掉。
    • 然后,添加下面这个新的 index_imgindex_video 结构。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    # 首页媒体配置
    # 注意:index_img 和 index_video 的 enable 只能有一个为 true
    index_img:
    enable: false # 如果想用图片背景,请将此项设为 true,并将下面的 index_video 的 enable 设为 false
    path: '[您的横屏图片链接]'
    vpath: '[您的竖屏图片链接]' # vpath 为竖屏设备显示的图片

    index_video:
    enable: true # ✅ 启用视频背景
    path: '[您的横屏视频链接]' # 例如 https://yun.ayakasuki.com/...
    poster: '[您的横屏视频加载动画GIF链接]' # 视频加载出来前的占位图
    vpath: '[您的竖屏视频链接]'
    vposter: '[您的竖屏视频加载动画GIF链接]'
  3. 注入新添加的CSS和JS文件

    • 在同一个主题配置文件中,找到 inject: 部分。
    • head: 列表的末尾添加一行,用于引入我们新建的CSS和JS文件。
    1
    2
    3
    4
    5
    6
    7
    inject:
    head:
    # - 其他 head 内容
    - <link rel="stylesheet" href="/css/index_media.css">
    bottom:
    # - 其他 bottom 内容
    - <script src="/js/index_media.js"></script>

    (注意:为便于主题管理,我们放在了 source/csssource/js 中,并在这里使用对应的路径引入)