All checks were successful
Gitea Actions Official-website / deploy-dev (push) Successful in 2s
1420 lines
51 KiB
HTML
1420 lines
51 KiB
HTML
{extend name="public/base" /}
|
||
{block name="style"}
|
||
<link rel="stylesheet" href="__CSS__/topic_laptop/header.css">
|
||
<link rel="stylesheet" href="__CSS__/before-after.min.css">
|
||
<link rel="stylesheet" href="__CSS__/topic_laptop/swiper.css">
|
||
<link rel="stylesheet" href="__CSS__/topic_laptop/footer.css">
|
||
<link rel="stylesheet" href="__CSS__/topic_laptop/index.css">
|
||
<link rel="stylesheet" href="__CSS__/topic_laptop/swiper.css">
|
||
<link rel="stylesheet" href="__CSS__/topic_laptop/amd.css">
|
||
<link rel="stylesheet" href="__CSS__/topic_laptop/yq.css">
|
||
<link rel="stylesheet" href="__CSS__/topic_laptop/progress.css">
|
||
<link rel="stylesheet" href="__CSS__/topic_laptop/readon.css">
|
||
<link rel="stylesheet" href="__CSS__/topic_laptop/wift.css">
|
||
<link rel="stylesheet" href="__CSS__/topic_laptop/m2.css">
|
||
<link rel="stylesheet" href="__CSS__/topic_laptop/45w.css">
|
||
<link rel="stylesheet" href="__CSS__/topic_laptop/fs.css">
|
||
<link rel="stylesheet" href="__CSS__/topic_laptop/xn.css">
|
||
<link rel="stylesheet" href="__CSS__/topic_laptop/ips.css">
|
||
<link rel="stylesheet" href="__CSS__/topic_laptop/rgb.css">
|
||
<link rel="stylesheet" href="__CSS__/topic_laptop/bly.css">
|
||
<link rel="stylesheet" href="__CSS__/topic_laptop/bly.css">
|
||
<link rel="stylesheet" href="__CSS__/topic_laptop/qb.css">
|
||
<link rel="stylesheet" href="__CSS__/topic_laptop/xh.css">
|
||
<link rel="stylesheet" href="__CSS__/topic_laptop/jk.css">
|
||
<link rel="stylesheet" href="__CSS__/topic_laptop/th.css">
|
||
<link rel="stylesheet" href="__CSS__/topic_laptop/lb.css">
|
||
<link rel="stylesheet" href="__CSS__/topic_laptop/windows.css">
|
||
<link rel="stylesheet" href="__CSS__/topic_laptop/bottom.css">
|
||
<link rel="stylesheet" href="__CSS__/topic_laptop/wift6.css">
|
||
<script type="text/javascript">
|
||
(function (doc, win)
|
||
{
|
||
var docEl = doc.documentElement;
|
||
var resizeEvt = 'orientationchange' in window ? 'orientationchange' : 'resize';
|
||
// 设计稿基准宽度改为2560px
|
||
var designWidth = 2560;
|
||
// 设计稿下1rem对应的px值(2560px下1rem=100px)
|
||
var designRemPx = 100;
|
||
|
||
function setRootFontSize ()
|
||
{
|
||
var clientWidth = docEl.clientWidth;
|
||
if (!clientWidth) return;
|
||
// 计算font-size:屏幕宽度/分割值(25.6)
|
||
var fontSize = (clientWidth / designWidth) * designRemPx;
|
||
// 关键:限制最小值(避免小屏幕下rem过小,内容不可读)
|
||
// 例如:最小1rem=20px(对应屏幕宽度512px,可调整)
|
||
fontSize = Math.max(fontSize, 20);
|
||
// 可选:限制最大值(若2560px以上屏幕不想继续放大)
|
||
fontSize = Math.min(fontSize, designRemPx);
|
||
docEl.style.fontSize = fontSize + 'px';
|
||
}
|
||
|
||
setRootFontSize();
|
||
win.addEventListener(resizeEvt, setRootFontSize);
|
||
doc.addEventListener('DOMContentLoaded', setRootFontSize);
|
||
})(document, window);
|
||
</script>
|
||
{/block}
|
||
{block name="main"}
|
||
{notempty name="data.top_focus_images"}
|
||
<!-- 轮播核心容器 -->
|
||
<div class="swiper-container auto-swiper-container" style="margin-top:60px;">
|
||
<div class="swiper-wrapper">
|
||
{volist name="data.top_focus_images" id="tfi"}
|
||
<a class="swiper-slide auto-swiper-slide" href="{$tfi.link}">
|
||
<img src="{$tfi.image}" alt="{$tfi.title}" />
|
||
</a>
|
||
{/volist}
|
||
</div>
|
||
</div>
|
||
{/notempty}
|
||
{notempty name="data.perf"}
|
||
<!-- 性能 -->
|
||
<div class="amd-box">
|
||
<div class="amd-img-box">
|
||
<div class="amd-img-1 opacity0" data-order="1" data-name="">
|
||
{notempty name="data.perf.0"}<img src="{$data.perf.0.image}" alt="{$data.perf.0.title}" class="amd-img-1-1">{/notempty}
|
||
</div>
|
||
<div class="amd-img-2 opacity0" data-order="2" data-name="">
|
||
<div class="amd-img-2-1">{notempty name="data.perf.1"}<img src="{$data.perf.1.image}" alt="{$data.perf.1.title}">{/notempty}</div>
|
||
<div class="amd-img-2-2">{notempty name="data.perf.2"}<img src="{$data.perf.2.image}" alt="{$data.perf.2.title}">{/notempty}</div>
|
||
</div>
|
||
<div class="amd-img-3 opacity0" data-order="3" data-name="">
|
||
<div class="amd-img-3-left">
|
||
{notempty name="data.perf.3"}<img src="{$data.perf.3.image}" alt="{$data.perf.3.title}" class="amd-img-3-1-left">{/notempty}
|
||
</div>
|
||
<div class="amd-img-3-right">
|
||
<div class="amd-img-3-1-right">
|
||
{notempty name="data.perf.4"}<img src="{$data.perf.4.image}" alt="{$data.perf.4.title}">{/notempty}
|
||
</div>
|
||
<div class="amd-img-3-2-right">
|
||
{notempty name="data.perf.5"}<img src="{$data.perf.5.image}" alt="{$data.perf.5.title}">{/notempty}
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="amd-img-4 opacity0" data-order="4" data-name="">
|
||
{notempty name="data.perf.6"}<img src="{$data.perf.6.image}" alt="{$data.perf.6.title}">{/notempty}
|
||
</div>
|
||
<div class="amd-img-5 opacity0" data-order="5" data-name="">
|
||
{notempty name="data.perf.7"}<img src="{$data.perf.7.image}" alt="{$data.perf.7.title}">{/notempty}
|
||
{notempty name="data.perf.8"}<img src="{$data.perf.8.image}" alt="{$data.perf.8.title}">{/notempty}
|
||
</div>
|
||
<div class="amd-img-6 opacity0" data-order="6" data-name="">
|
||
{notempty name="data.perf.9"}<img src="{$data.perf.9.image}" alt="{$data.perf.9.title}">{/notempty}
|
||
</div>
|
||
</div>
|
||
</div>
|
||
{/notempty}
|
||
{notempty name="data.cpu"}
|
||
<!-- 引擎 -->
|
||
{assign name="cpu_first_section" value=":array_shift($data.cpu)" /}
|
||
<div class="fullscreen-img-container" style="background: url('{$cpu_first_section.image|default=\'\'}');background-size:100% auto">
|
||
<div class="overlay-text opacity0" data-order="7">
|
||
<h2>{$cpu_first_section.title|default=''}</h2>
|
||
<p>{$cpu_first_section.short_title|default=''}</p>
|
||
</div>
|
||
<div class="float-cards opacity0" data-order="8" >
|
||
{volist name="data.cpu" id="co"}
|
||
<img class="float-card" src="{$co.image}" alt="{$co.title}">
|
||
{/volist}
|
||
</div>
|
||
</div>
|
||
<!-- 引擎描述 -->
|
||
<div class="bottom-desc">
|
||
{$cpu_first_section.desc|default=''|raw}
|
||
</div>
|
||
{/notempty}
|
||
<!-- 引擎进度条 写死在前端(后台配置太繁琐)-->
|
||
<div class="container">
|
||
<h1 class="progress-title">{:lang_i18n('CineBench R23 多核跑分')}</h1>
|
||
<div class="progress-section">
|
||
<div class="progress-item">
|
||
<div class="progress-bar-container">
|
||
<div class="progress-bar">
|
||
<div class="progress-fill m4-max" data-value="100"></div>
|
||
</div>
|
||
</div>
|
||
<div class="label">
|
||
<span class="device-name colorLinearGradient">Ryzen7 7735HS:</span>
|
||
<span class="value m4-max colorLinearGradient">13766</span>
|
||
</div>
|
||
</div>
|
||
<div class="progress-item">
|
||
<div class="progress-bar-container w1368">
|
||
<div class="progress-bar">
|
||
<div class="progress-fill m2-max" data-value="100"></div>
|
||
</div>
|
||
</div>
|
||
<div class="label w1368">
|
||
<span class="device-name font32 colorCBCFD8">Ryzen5 7640HS:</span>
|
||
<span class="value gray font32 color8A8787">12950</span>
|
||
</div>
|
||
</div>
|
||
<div class="progress-item">
|
||
<div class="progress-bar-container w1243">
|
||
<div class="progress-bar">
|
||
<div class="progress-fill m1-max" data-value="100"></div>
|
||
</div>
|
||
</div>
|
||
<div class="label w1243">
|
||
<span class="device-name font32 colorCBCFD8">{:lang_i18n('锐龙9 6900HX')}:</span>
|
||
<span class="value gray font32 color8A8787">13183</span>
|
||
</div>
|
||
</div>
|
||
<div class="progress-item">
|
||
<div class="progress-bar-container w964">
|
||
<div class="progress-bar w964">
|
||
<div class="progress-fill baseline" data-value="100"></div>
|
||
</div>
|
||
</div>
|
||
<div class="label w964">
|
||
<span class="device-name baseline font32 colorCBCFD8">{:lang_i18n('酷睿i5-12450H')}:</span>
|
||
<span class="value gray font32 color8A8787">10200</span>
|
||
</div>
|
||
</div>
|
||
<div class="progress-item">
|
||
<div class="progress-bar-container w681">
|
||
<div class="progress-bar">
|
||
<div class="progress-fill baseline" data-value="100"></div>
|
||
</div>
|
||
</div>
|
||
<div class="label w681 ">
|
||
<span class="device-name baseline font32 colorCBCFD8">Ryzen5 6600H:</span>
|
||
<span class="value gray font32 color8A8787">10297</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="progress-p">{:lang_i18n('*此跑分为ORICO实验室测定所得,请以实际使用为准')}</div>
|
||
</div>
|
||
{notempty name="data.gpu"}
|
||
<!-- 显卡-->
|
||
{assign name="gpu_first_section" value=":array_shift($data.gpu)"/}
|
||
<div class="readon-box" style="background: url('{$gpu_first_section.image|default=\'\'}');background-size:100% auto">
|
||
<div class="readon-text opacity0" data-order="9">
|
||
<div class="readon-t">{$gpu_first_section.title|default=''|raw}</div>
|
||
<div class="readon-js">{$gpu_first_section.short_title|default=''|raw}</div>
|
||
<div class="readon-img opacity0" data-order="10">
|
||
<img src="{$gpu_first_section.extra_image|default=''}" alt="">
|
||
</div>
|
||
</div>
|
||
<div class="readon-img-box opacity0" data-order="11">
|
||
{volist name="data.gpu" id="go"}
|
||
<img src="{$go.image}" alt="">
|
||
{/volist}
|
||
</div>
|
||
</div>
|
||
{/notempty}
|
||
<!-- 显卡进度条 -->
|
||
<div class="container">
|
||
<h1 class="progress-title">{:lang_i18n('3DMARK Time Spy显卡得分')}</h1>
|
||
<div class="progress-section">
|
||
<div class="progress-item">
|
||
<div class="progress-bar-container">
|
||
<div class="progress-bar">
|
||
<div class="progress-fill m4-max" data-value="100"></div>
|
||
</div>
|
||
</div>
|
||
<div class="label">
|
||
<span class="device-name colorLinearGradient">Ryzen7 7735HS:</span>
|
||
<span class="value m4-max colorLinearGradient">13766</span>
|
||
</div>
|
||
</div>
|
||
<div class="progress-item w1274">
|
||
<div class="progress-bar-container ">
|
||
<div class="progress-bar">
|
||
<div class="progress-fill m2-max" data-value="100"></div>
|
||
</div>
|
||
</div>
|
||
<div class="label">
|
||
<span class="device-name font32 colorCBCFD8">Ryzen7 7735HS:</span>
|
||
<span class="value gray font32 color8A8787">1000</span>
|
||
</div>
|
||
</div>
|
||
<div class="progress-item w1274">
|
||
<div class="progress-bar-container ">
|
||
<div class="progress-bar">
|
||
<div class="progress-fill m1-max" data-value="100"></div>
|
||
</div>
|
||
</div>
|
||
<div class="label ">
|
||
<span class="device-name font32 colorCBCFD8">NVIDIA GTX 750:</span>
|
||
<span class="value gray font32 color8A8787">1000</span>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="progress-item w1000">
|
||
<div class="progress-bar-container ">
|
||
<div class="progress-bar">
|
||
<div class="progress-fill baseline" data-value="100"></div>
|
||
</div>
|
||
</div>
|
||
<div class="label">
|
||
<span class="device-name baseline font32 colorCBCFD8">Ryzen5 6600H:</span>
|
||
<span class="value gray font32 color8A8787">950</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="progress-p">{:lang_i18n('*此跑分为ORICO实验室测定所得,请以实际使用为准')}</div>
|
||
</div>
|
||
{notempty name="data.ram"}
|
||
<!-- 运行内存 -->
|
||
<div class="wift" >
|
||
<div class="wift-t opacity0" data-order="12">{$data.ram.title|raw}</div>
|
||
<div class="wift-bg" style="background: url('{$data.ram.image}');background-size:100% auto;">
|
||
<div class="opacity0" data-order="13">
|
||
<div class="wift-bg-p">{$data.ram.short_title|raw}</div>
|
||
</div>
|
||
<div class="wift-bg-img opacity0" data-order="14">
|
||
{$data.ram.desc|raw}
|
||
</div>
|
||
</div>
|
||
</div>
|
||
{/notempty}
|
||
{notempty name="data.hard_drive"}
|
||
<!-- 硬盘 -->
|
||
<div class="m2">
|
||
{assign name="hard_drive_first" value=":array_shift($data.hard_drive)"/}
|
||
<div class="m2-bg" style="background: url('{$hard_drive_first.image|default=\'\'}');background-size:100% auto">
|
||
<div class="m2-bg-t opacity0" data-order="15">{$hard_drive_first.title|default=''|raw}</div>
|
||
<div class="m2-img-box opacity0" data-order="16">
|
||
{volist name="data.hard_drive" id="ho"}
|
||
<img src="{$ho.image}" alt="">
|
||
{/volist}
|
||
</div>
|
||
</div>
|
||
</div>
|
||
{/notempty}
|
||
{notempty name="data.cooling_system"}
|
||
{notempty name="$data.cooling_system.0"}
|
||
<!-- 45w -->
|
||
<div class="dl opacity0" data-order="17">
|
||
<div class="dl-t">{$data.cooling_system.0.title|raw}</div>
|
||
<p class="dl-p">{$data.cooling_system.0.short_title|raw}</p>
|
||
</div>
|
||
{/notempty}
|
||
<!-- 风扇 -->
|
||
<div class="fs">
|
||
<div class="fs-box">
|
||
{notempty name="data.cooling_system.0"}
|
||
<img src="{$data.cooling_system.0.image|default=''}" alt="" class="fs-img">
|
||
<video
|
||
src="{$data.cooling_system.0.video|default=''}"
|
||
class="fs-video" muted loop playsinline controls
|
||
style="display: none;width: 1440px;margin:0 auto;max-width: 1440px;">
|
||
您的浏览器不支持HTML5视频播放,请升级浏览器
|
||
</video>
|
||
<div class="fs-ts">{$data.cooling_system.0.desc|raw}</div>
|
||
{/notempty}
|
||
<div class="fs-box-img opacity0" data-order="18">
|
||
{notempty name="data.cooling_system.1"}<img src="{$data.cooling_system.1.image}" alt="">{/notempty}
|
||
{notempty name="data.cooling_system.2"}<img src="{$data.cooling_system.2.image}" alt="">{/notempty}
|
||
</div>
|
||
</div>
|
||
<div class="fs-b-img">
|
||
{notempty name="data.cooling_system.3"}<img src="{$data.cooling_system.3.image}" alt="">{/notempty}
|
||
</div>
|
||
</div>
|
||
{/notempty}
|
||
{notempty name="data.apps"}
|
||
<!-- 性能 -->
|
||
<div class="xn">
|
||
<div class="xn-t opacity0" data-order="19">{$data.apps.title|default=''}</div>
|
||
<div class="xn-container">
|
||
<!-- 图片区域(滚动到此处自动放大) -->
|
||
<div class="xn-image-section">
|
||
<!-- 示例图:MacBook Air 天蓝色款(替换为官网高清图) -->
|
||
<img src="{$data.apps.image|default=''}" alt="" class="zoom-image first-image" loading="lazy"> <!-- 懒加载优化 -->
|
||
</div>
|
||
</div>
|
||
<div class="xn-p">{$data.apps.desc|default=''|raw}</div>
|
||
</div>
|
||
{/notempty}
|
||
{notempty name="data.screen_soft_light"}
|
||
<!-- IPS -->
|
||
{assign name="soft_light_first" value=":array_shift($data.screen_soft_light)"/}
|
||
<div class="ips" style="background: url('{$soft_light_first.image|default=\'\'}');background-size:100% auto">
|
||
<div class="ips-text opacity0" data-order="20">
|
||
{notempty name="soft_light_first"}
|
||
<div class="ips-t">{$soft_light_first.title|raw}</div>
|
||
<div class="ips-p">{$soft_light_first.short_title|raw}</div>
|
||
{/notempty}
|
||
<div class="ips-img opacity0" data-order="21">
|
||
{volist name="data.screen_soft_light" id="so"}
|
||
<img src="{$so.image}" alt="">
|
||
{/volist}
|
||
</div>
|
||
</div>
|
||
</div>
|
||
{/notempty}
|
||
{notempty name="data.screen_color_gamut"}
|
||
<!-- RGB -->
|
||
{assign name="color_gamut_first" value=":array_shift($data.screen_color_gamut)"/}
|
||
<div class="rgb" style="background: url('{$color_gamut_first.image|default=\'\'}');background-size:100% auto">
|
||
{notempty name="color_gamut_first"}
|
||
<div class="rgb-text opacity0" data-order="22">
|
||
<div class="rgb-t">{$color_gamut_first.title|raw}</div>
|
||
<div class="rgb-p">{$color_gamut_first.short_title|raw}</div>
|
||
</div>
|
||
{/notempty}
|
||
<div class="rgb-img opacity0" data-order="23">
|
||
{volist name="data.screen_color_gamut" id="so"}
|
||
<img src="{$so.image}" alt="">
|
||
{/volist}
|
||
</div>
|
||
</div>
|
||
{/notempty}
|
||
{notempty name="data.screen_anti_glare"}
|
||
<!-- 舒适不累眼 -->
|
||
<div class="bly">
|
||
{assign name="anti_glare_first" value=":array_shift($data.screen_anti_glare)"/}
|
||
{notempty name="anti_glare_first"}
|
||
<div class="bly-text opacity0" data-order="24">
|
||
<div class="bly-t">{$anti_glare_first.title|raw}</div>
|
||
<div class="bly-p">{$anti_glare_first.short_title|raw}</div>
|
||
</div>
|
||
{/notempty}
|
||
<div class="beforeafter ba-slider">
|
||
<!-- 对比前的图片 -->
|
||
{assign name="anti_glare_left" value=":array_shift($data.screen_anti_glare)"/}
|
||
<img src="{$anti_glare_left.image|default=''}">
|
||
<div class="resize">
|
||
<!-- 对比后的图片 -->
|
||
{assign name="anti_glare_right" value=":array_shift($data.screen_anti_glare)"/}
|
||
<img src="{$anti_glare_right.image|default=''}">
|
||
</div>
|
||
<!-- 可拖动的分隔条 -->
|
||
<span class="handle"></span>
|
||
</div>
|
||
</div>
|
||
{/notempty}
|
||
{notempty name="data.exterior_texture"}
|
||
<!-- 轻薄有型 -->
|
||
<div class="qb">
|
||
<div class="qb-text opacity0" data-order="24">
|
||
{assign name="exterior_texture_first" value=":array_shift($data.exterior_texture)"/}
|
||
<div class="qb-t">{$exterior_texture_first.title|default=''|raw}</div>
|
||
<div class="qb-p">{$exterior_texture_first.short_title|default=''|raw}</div>
|
||
<div class="swiper-container auto-swiper-container">
|
||
<div class="swiper-wrapper">
|
||
{volist name="data.exterior_texture" id="eo"}
|
||
<a class="swiper-slide auto-swiper-slide">
|
||
<img src="{$eo.image}" alt="{$eo.title}" href="{$eo.link}">
|
||
</a>
|
||
{/volist}
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
{/notempty}
|
||
{notempty name="data.network_card"}
|
||
<!-- wifi6 -->
|
||
{assign name="netword_card_first" value=":array_shift($data.network_card)"/}
|
||
<div class="wift6" style="background: url('{$netword_card_first.image|default=\'\'}');background-size:100% auto">
|
||
<div class="wift6-text opacity0" data-order="25">
|
||
<div class="wift6-t">{$netword_card_first.title|default=''|raw}</div>
|
||
<div class="wift6-p">{$netword_card_first.short_title|default=''|raw}</div>
|
||
</div>
|
||
<div class="wift6-img opacity0" data-order="26">
|
||
{volist name="data.network_card" id="no"}
|
||
<img src="{$no.image}" alt="">
|
||
{/volist}
|
||
</div>
|
||
</div>
|
||
{/notempty}
|
||
{notempty name="data.battery_life"}
|
||
<!-- 11.4h长久续航 -->
|
||
{assign name="battery_life_first" value=":array_shift($data.battery_life)"/}
|
||
<div class="xh" style="background: url('{$battery_life_first.image|default=\'\'}');background-size:100% auto">
|
||
<div class="xh-text opacity0" data-order="27">
|
||
<div class="xh-t">{$battery_life_first.title|default=''|raw}</div>
|
||
<div class="xh-p">{$battery_life_first.short_title|default=''|raw}</div>
|
||
</div>
|
||
<div class="xh-img opacity0" data-order="28">
|
||
{volist name="data.battery_life" id="bo"}
|
||
<img src="{$bo.image}" alt="">
|
||
{/volist}
|
||
</div>
|
||
<div class="xh-b-p">{$battery_life_first.desc|default=''|raw}</div>
|
||
</div>
|
||
{/notempty}
|
||
<!-- 接口 -->
|
||
<div class="zoom-container" id="zoomContainer">
|
||
<!-- <img src="__IMAGES__/topic_laptop/jk.png" alt="接口图" class="bg-img" id="bgImg"> -->
|
||
<div class="img-wrapper">
|
||
<img src="__IMAGES__/topic_laptop/jk.png" alt="接口图" class="bg-img" id="bgImg">
|
||
</div>
|
||
<!-- 标注:top/left用百分比,位置相对图片不变 -->
|
||
<div class="annotation anno-delay-1" style="top: 53.5%; left: 42%;"><span style="text-align: center;">{:lang_i18n('肯幸通锁孔')}</span></div>
|
||
<div class="annotation anno-delay-1" style="top: 57%; left: 37%;"><span style="text-align: center;">{:lang_i18n('千兆网口')}</span></div>
|
||
<div class="annotation anno-delay-1" style="top: 60.3%; left: 31%;"><span style="text-align: center;">{:lang_i18n('USB-A<br/>(5Gbps)')}</span></div>
|
||
<div class="annotation anno-delay-1" style="top:63.4%; left:25%;"><span style="text-align: center;">{:lang_i18n('USB-A<br/>(480Mbps)')}</span></div>
|
||
<div class="annotation anno-delay-1" style="top: 66%; left: 20.5%;"><span style="text-align: center;">{:lang_i18n('3.5mm<br/>耳麦合一')}</span></div>
|
||
<div class="annotation anno-delay-1" style="top: 68%; left: 16%;"><span style="text-align: center;">{:lang_i18n('TF口3.0')}</span></div>
|
||
|
||
<div class="annotation anno-delay-1" style="top: 63.5%; left: 70.5%;"><span style="text-align: center;">{:lang_i18n('USB-A<br/>(5Gbps)')}</span></div>
|
||
<div class="annotation anno-delay-1" style="top: 66.5%; left: 76%;"><span style="text-align: center;">{:lang_i18n('USB-C<br/>(5Gbps)')}</span></div>
|
||
<div class="annotation anno-delay-1" style="top: 59.5%; left: 64%;"><span style="text-align: center;">{:lang_i18n('HDMI')}</span></div>
|
||
<div class="annotation anno-delay-1" style="top: 57%; left: 59%;"><span style="text-align: center;">{:lang_i18n('全功能<br/>USB-C')}</span></div>
|
||
</div>
|
||
{notempty name="data.scene_focus_images"}
|
||
<!-- 轮播图2 -->
|
||
<div class="lb">
|
||
<div class="carousel-wrapper">
|
||
<!-- 左箭头 -->
|
||
<div class="carousel-arrow arrow-left">
|
||
<img src="__IMAGES__/topic_laptop/l1.png" alt="左箭头">
|
||
</div>
|
||
<!-- 轮播图容器 -->
|
||
<div class="carousel-container">
|
||
<div class="carousel-imgs">
|
||
{volist name="data.scene_focus_images" id="so"}
|
||
<img src="{$so.image}" alt="{$so.title}" class="carousel-img">
|
||
{/volist}
|
||
</div>
|
||
</div>
|
||
<!-- 右箭头 -->
|
||
<div class="carousel-arrow arrow-right">
|
||
<img src="__IMAGES__/topic_laptop/r1.png" alt="右箭头">
|
||
</div>
|
||
</div>
|
||
<!-- 轮播对应文字 -->
|
||
<div class="carousel-texts">
|
||
{volist name="data.scene_focus_images" id="so"}
|
||
<div class="carousel-text active" data-index="{$key}">
|
||
<div class="carousel-text-t">{$so.title}</div>
|
||
<div class="carousel-text-p">{$so.short_title}</div>
|
||
</div>
|
||
{/volist}
|
||
</div>
|
||
</div>
|
||
{/notempty}
|
||
{notempty name="data.camare_microphone_security"}
|
||
<!-- 模块标题 -->
|
||
{assign name="cms_section_title" value=":array_shift($data.camare_microphone_security)"/}
|
||
<!-- 摄像头/麦克风 -->
|
||
{assign name="camare_microphone" value=":array_shift($data.camare_microphone_security)"/}
|
||
<!-- 安全介绍 -->
|
||
{assign name="security" value=":array_shift($data.camare_microphone_security)"/}
|
||
<div class="tabs-container">
|
||
<div class="tab-t opacity0" data-order="29">{$cms_section_title.title|default=''}</div>
|
||
<div class="tab-content">
|
||
<!-- 清晰通话 - 图片内容 -->
|
||
{notempty name="camare_microphone"}
|
||
<div class="tab-panel active">
|
||
<img src="{$camare_microphone.image}" alt="{$camare_microphone.title}" class="content-image">
|
||
</div>
|
||
{/notempty}
|
||
<!-- 安护密守 - 视频内容 -->
|
||
{notempty name="security"}
|
||
<div class="tab-panel">
|
||
<video
|
||
src="{$security.video}"
|
||
id="securityVideo" class="content-video" muted loop playsinline controls
|
||
style="width: 1440px;margin:0 auto;max-width: 1440px;min-width: 1280px">
|
||
您的浏览器不支持HTML5视频播放,请升级浏览器
|
||
</video>
|
||
</div>
|
||
{/notempty}
|
||
</div>
|
||
<div class="tabs-header-box">
|
||
<div class="tabs-header">
|
||
{notempty name="camare_microphone"}<div class="tab-item active" data-index="0">{$camare_microphone.title}</div>{/notempty}
|
||
{notempty name="security"}<div class="tab-item" data-index="1">{$security.title}</div>{/notempty}
|
||
<div class="tab-indicator"></div>
|
||
</div>
|
||
</div>
|
||
{notempty name="camare_microphone"}
|
||
<div class="tabs-p active" data-index="0">{$camare_microphone.short_title}</div>
|
||
{/notempty}
|
||
{notempty name="security"}
|
||
<div class="tabs-p" data-index="1">{$security.short_title}</div>
|
||
{/notempty}
|
||
</div>
|
||
{/notempty}
|
||
{notempty name="data.unified_preinstall"}
|
||
<!-- windows -->
|
||
<div class="windows" style="background: url('{$data.unified_preinstall.image|default=\'\'}');background-size:100% auto"></div>
|
||
{/notempty}
|
||
{notempty name="data.product_testing"}
|
||
<!-- 底部图片 -->
|
||
<div class="bottom-img-box">
|
||
<div class="bottom-img opacity0" data-order="30">
|
||
{volist name="data.product_testing" id="po"}
|
||
<img src="{$po.image}" alt="{$po.title}">
|
||
{/volist}
|
||
</div>
|
||
</div>
|
||
{/notempty}
|
||
{notempty name="data.webpage_footnotes"}
|
||
<!-- 底部文字 -->
|
||
<div class="bottom-text">
|
||
<div class="bottom-p">{$data.webpage_footnotes.desc|raw}</div>
|
||
</div>
|
||
{/notempty}
|
||
{/block}
|
||
{block name="script"}
|
||
<script src="__JS__/before-after.min.js" type="text/javascript"></script>
|
||
<script type="text/javascript">
|
||
|
||
// 轮播初始化
|
||
let swiper;
|
||
window.onload = function ()
|
||
{
|
||
if (typeof Swiper === 'undefined') {
|
||
console.error('Swiper加载失败,请刷新页面重试');
|
||
return;
|
||
}
|
||
swiper = new Swiper('.auto-swiper-container', {
|
||
autoplay: {
|
||
delay: 3000, // 3秒切换
|
||
disableOnInteraction: false,
|
||
},
|
||
loop: false,
|
||
slidesPerView: 1,
|
||
spaceBetween: 0,
|
||
pagination: false,
|
||
navigation: false,
|
||
scrollbar: false,
|
||
on: {
|
||
resize: function ()
|
||
{
|
||
this.update();
|
||
},
|
||
},
|
||
});
|
||
// 初始化时触发滚动事件,确保状态正确
|
||
window.dispatchEvent(new Event('scroll'));
|
||
};
|
||
|
||
// 滚动淡入动效(修复刷新/缩放隐藏问题)
|
||
(function ()
|
||
{
|
||
const TRIGGER_RATIO = 0.1; // 10%可见触发
|
||
let lastScrollY = window.scrollY;
|
||
let isResizing = false;
|
||
let resizeTimer = null;
|
||
|
||
const els = Array.from(document.querySelectorAll('[data-order]')).sort((a, b) => a.dataset.order - b.dataset.order);
|
||
const elState = new Map();
|
||
els.forEach(el =>
|
||
{
|
||
elState.set(el, {
|
||
isInView: false,
|
||
isFadedIn: false
|
||
});
|
||
});
|
||
|
||
// 可视区判断工具函数
|
||
const isElementInView = (el) =>
|
||
{
|
||
const rect = el.getBoundingClientRect();
|
||
const viewportHeight = window.innerHeight;
|
||
const viewportWidth = window.innerWidth;
|
||
|
||
const intersects = (
|
||
rect.bottom > 0 &&
|
||
rect.top < viewportHeight &&
|
||
rect.right > 0 &&
|
||
rect.left < viewportWidth
|
||
);
|
||
|
||
if (!intersects) return false;
|
||
|
||
const visibleHeight = Math.min(rect.bottom, viewportHeight) - Math.max(rect.top, 0);
|
||
const visibleWidth = Math.min(rect.right, viewportWidth) - Math.max(rect.left, 0);
|
||
const visibleRatio = (visibleHeight * visibleWidth) / (rect.height * rect.width);
|
||
|
||
return visibleRatio >= TRIGGER_RATIO;
|
||
};
|
||
|
||
// 判断元素是否在当前滚动位置上方
|
||
const isElementAboveViewport = (el) =>
|
||
{
|
||
const rect = el.getBoundingClientRect();
|
||
return rect.bottom <= 0 || isElementInView(el);
|
||
};
|
||
|
||
// 淡入元素
|
||
const fadeInElement = (el) =>
|
||
{
|
||
if (elState.get(el).isFadedIn) return;
|
||
el.classList.add('fade-in');
|
||
elState.get(el).isFadedIn = true;
|
||
};
|
||
|
||
// 隐藏元素(缩放时跳过)
|
||
const hideElement = (el) =>
|
||
{
|
||
if (isResizing) return;
|
||
if (!elState.get(el).isFadedIn) return;
|
||
el.classList.remove('fade-in');
|
||
elState.get(el).isFadedIn = false;
|
||
};
|
||
|
||
// 防抖函数
|
||
const debounce = (fn, delay = 16) =>
|
||
{
|
||
let timer = null;
|
||
return (isResize = false) =>
|
||
{
|
||
clearTimeout(timer);
|
||
isResizing = isResize;
|
||
timer = setTimeout(() =>
|
||
{
|
||
fn();
|
||
if (isResize) {
|
||
isResizing = false;
|
||
refreshAllElementsState();
|
||
}
|
||
}, delay);
|
||
};
|
||
};
|
||
|
||
// 缩放后刷新所有元素状态(保留已显示)
|
||
const refreshAllElementsState = () =>
|
||
{
|
||
els.forEach(el =>
|
||
{
|
||
const isFaded = elState.get(el).isFadedIn;
|
||
const isAbove = isElementAboveViewport(el);
|
||
if (isFaded) {
|
||
el.classList.add('fade-in');
|
||
}
|
||
if (!isFaded && isAbove) {
|
||
fadeInElement(el);
|
||
}
|
||
});
|
||
};
|
||
|
||
// 核心滚动逻辑
|
||
const handleScroll = debounce((isResize) =>
|
||
{
|
||
if (isResize) return;
|
||
|
||
const currentScrollY = window.scrollY;
|
||
const isScrollUp = currentScrollY < lastScrollY;
|
||
const isScrollDown = currentScrollY > lastScrollY;
|
||
|
||
els.forEach(el =>
|
||
{
|
||
const prevInView = elState.get(el).isInView;
|
||
const currentInView = isElementInView(el);
|
||
elState.set(el, { ...elState.get(el), isInView: currentInView });
|
||
|
||
// 向下滚动淡入
|
||
if (isScrollDown) {
|
||
if (currentInView && !prevInView) {
|
||
fadeInElement(el);
|
||
}
|
||
}
|
||
|
||
// 向上滚动隐藏
|
||
if (isScrollUp) {
|
||
if (!currentInView && prevInView) {
|
||
hideElement(el);
|
||
}
|
||
}
|
||
});
|
||
|
||
lastScrollY = currentScrollY;
|
||
});
|
||
|
||
// 缩放处理
|
||
const handleResize = () =>
|
||
{
|
||
clearTimeout(resizeTimer);
|
||
isResizing = true;
|
||
resizeTimer = setTimeout(() =>
|
||
{
|
||
isResizing = false;
|
||
refreshAllElementsState();
|
||
}, 200);
|
||
};
|
||
|
||
// 初始化上方元素
|
||
const initAllAboveElements = () =>
|
||
{
|
||
setTimeout(() =>
|
||
{
|
||
els.forEach(el =>
|
||
{
|
||
if (isElementAboveViewport(el)) {
|
||
fadeInElement(el);
|
||
}
|
||
});
|
||
}, 100);
|
||
};
|
||
|
||
// 事件绑定
|
||
window.addEventListener('scroll', () => handleScroll(false), { passive: true });
|
||
window.addEventListener('resize', handleResize);
|
||
window.addEventListener('load', initAllAboveElements);
|
||
document.addEventListener('DOMContentLoaded', initAllAboveElements);
|
||
})();
|
||
|
||
// 接口模块动画(同步修复)
|
||
(function ()
|
||
{
|
||
const TRIGGER_RATIO = 0.1;
|
||
let lastScrollY = window.scrollY;
|
||
let isResizing = false;
|
||
let resizeTimer = null;
|
||
|
||
const zoomContainer = document.getElementById('zoomContainer');
|
||
const annotations = document.querySelectorAll('.annotation');
|
||
const bgImg = document.getElementById('bgImg');
|
||
|
||
const elState = new Map();
|
||
if (zoomContainer) {
|
||
elState.set(zoomContainer, {
|
||
isInView: false,
|
||
isFadedIn: false
|
||
});
|
||
}
|
||
|
||
// 可视区判断
|
||
const isElementInView = (el) =>
|
||
{
|
||
const rect = el.getBoundingClientRect();
|
||
const viewportHeight = window.innerHeight;
|
||
const viewportWidth = window.innerWidth;
|
||
|
||
const intersects = (
|
||
rect.bottom > 0 &&
|
||
rect.top < viewportHeight &&
|
||
rect.right > 0 &&
|
||
rect.left < viewportWidth
|
||
);
|
||
|
||
if (!intersects) return false;
|
||
|
||
const visibleHeight = Math.min(rect.bottom, viewportHeight) - Math.max(rect.top, 0);
|
||
const visibleWidth = Math.min(rect.right, viewportWidth) - Math.max(rect.left, 0);
|
||
const visibleRatio = (visibleHeight * visibleWidth) / (rect.height * rect.width);
|
||
|
||
return visibleRatio >= TRIGGER_RATIO;
|
||
};
|
||
|
||
// 判断是否在上方
|
||
const isElementAboveViewport = (el) =>
|
||
{
|
||
const rect = el.getBoundingClientRect();
|
||
return rect.bottom <= 0 || isElementInView(el);
|
||
};
|
||
|
||
// 淡入接口模块
|
||
const fadeInInterface = (el) =>
|
||
{
|
||
if (!el || elState.get(el).isFadedIn) return;
|
||
annotations.forEach(anno => anno.classList.add('anno-show'));
|
||
bgImg.classList.add('zoom-out');
|
||
elState.get(el).isFadedIn = true;
|
||
};
|
||
|
||
// 隐藏接口模块(缩放时跳过)
|
||
const hideInterface = (el) =>
|
||
{
|
||
if (isResizing) return;
|
||
if (!el || !elState.get(el).isFadedIn) return;
|
||
annotations.forEach(anno => anno.classList.remove('anno-show'));
|
||
bgImg.classList.remove('zoom-out');
|
||
elState.get(el).isFadedIn = false;
|
||
};
|
||
|
||
// 防抖
|
||
const debounce = (fn, delay = 16) =>
|
||
{
|
||
let timer = null;
|
||
return (isResize = false) =>
|
||
{
|
||
clearTimeout(timer);
|
||
isResizing = isResize;
|
||
timer = setTimeout(() =>
|
||
{
|
||
fn();
|
||
isResizing = false;
|
||
}, delay);
|
||
};
|
||
};
|
||
|
||
// 滚动逻辑
|
||
const handleScroll = debounce((isResize) =>
|
||
{
|
||
if (isResize) return;
|
||
|
||
const currentScrollY = window.scrollY;
|
||
const isScrollUp = currentScrollY < lastScrollY;
|
||
const isScrollDown = currentScrollY > lastScrollY;
|
||
|
||
if (!zoomContainer) return;
|
||
|
||
const prevInView = elState.get(zoomContainer).isInView;
|
||
const currentInView = isElementInView(zoomContainer);
|
||
elState.set(zoomContainer, { ...elState.get(zoomContainer), isInView: currentInView });
|
||
|
||
if (isScrollDown) {
|
||
if (currentInView && !prevInView) {
|
||
fadeInInterface(zoomContainer);
|
||
}
|
||
}
|
||
|
||
if (isScrollUp) {
|
||
if (!currentInView && prevInView) {
|
||
hideInterface(zoomContainer);
|
||
}
|
||
}
|
||
|
||
lastScrollY = currentScrollY;
|
||
});
|
||
|
||
// 缩放处理
|
||
const handleResize = () =>
|
||
{
|
||
clearTimeout(resizeTimer);
|
||
isResizing = true;
|
||
resizeTimer = setTimeout(() =>
|
||
{
|
||
isResizing = false;
|
||
// 保留已显示状态
|
||
if (zoomContainer && elState.get(zoomContainer).isFadedIn) {
|
||
annotations.forEach(anno => anno.classList.add('anno-show'));
|
||
bgImg.classList.add('zoom-out');
|
||
}
|
||
}, 200);
|
||
};
|
||
|
||
// 初始化
|
||
const initInterfaceElement = () =>
|
||
{
|
||
setTimeout(() =>
|
||
{
|
||
if (zoomContainer && isElementAboveViewport(zoomContainer)) {
|
||
fadeInInterface(zoomContainer);
|
||
}
|
||
}, 100);
|
||
};
|
||
|
||
// 事件绑定
|
||
window.addEventListener('scroll', () => handleScroll(false), { passive: true });
|
||
window.addEventListener('resize', handleResize);
|
||
window.addEventListener('load', initInterfaceElement);
|
||
document.addEventListener('DOMContentLoaded', initInterfaceElement);
|
||
})();
|
||
|
||
// 进度条动画(修复重复触发)
|
||
function animateProgressBars (container)
|
||
{
|
||
// 防重复执行锁
|
||
if (container._isAnimating) return;
|
||
container._isAnimating = true;
|
||
|
||
const progressFills = container.querySelectorAll('.progress-fill');
|
||
progressFills.forEach(fill =>
|
||
{
|
||
clearTimeout(fill._animateTimer); // 清空旧定时器
|
||
fill.style.width = '0';
|
||
fill._animateTimer = setTimeout(() =>
|
||
{
|
||
const targetValue = fill.getAttribute('data-value');
|
||
fill.style.width = targetValue + '%';
|
||
// 动画结束解锁
|
||
setTimeout(() =>
|
||
{
|
||
container._isAnimating = false;
|
||
}, 500);
|
||
}, 100);
|
||
});
|
||
}
|
||
|
||
function isElementInView (el)
|
||
{
|
||
const rect = el.getBoundingClientRect();
|
||
const viewportHeight = window.innerHeight;
|
||
const viewportWidth = window.innerWidth;
|
||
|
||
const intersects = (
|
||
rect.bottom > 0 &&
|
||
rect.top < viewportHeight &&
|
||
rect.right > 0 &&
|
||
rect.left < viewportWidth
|
||
);
|
||
|
||
if (!intersects) return false;
|
||
|
||
const visibleHeight = Math.min(rect.bottom, viewportHeight) - Math.max(rect.top, 0);
|
||
const visibleWidth = Math.min(rect.right, viewportWidth) - Math.max(rect.left, 0);
|
||
const visibleRatio = (visibleHeight * visibleWidth) / (rect.height * rect.width);
|
||
|
||
return visibleRatio >= 0.1;
|
||
}
|
||
|
||
// 判断进度条容器是否在上方
|
||
function isProgressContainerAbove (container)
|
||
{
|
||
const rect = container.getBoundingClientRect();
|
||
return rect.bottom <= 0 || isElementInView(container);
|
||
}
|
||
|
||
const debounce = (fn, delay = 16) =>
|
||
{
|
||
let timer = null;
|
||
return (isResize = false) =>
|
||
{
|
||
clearTimeout(timer);
|
||
timer = setTimeout(() => fn(isResize), delay);
|
||
};
|
||
};
|
||
|
||
const progressContainers = document.querySelectorAll('.container');
|
||
const progressAnimatedMap = new Map();
|
||
const progressPermanentMap = new Map(); // 永久触发标记
|
||
|
||
// 初始化标记
|
||
progressContainers.forEach(container =>
|
||
{
|
||
progressAnimatedMap.set(container, false);
|
||
progressPermanentMap.set(container, false);
|
||
});
|
||
|
||
// 滚动处理
|
||
const handleProgressScroll = debounce((isResize) =>
|
||
{
|
||
if (isResize) return;
|
||
|
||
progressContainers.forEach(container =>
|
||
{
|
||
if (progressPermanentMap.get(container)) return; // 已触发则跳过
|
||
|
||
const isAnimated = progressAnimatedMap.get(container);
|
||
if (isElementInView(container) && !isAnimated) {
|
||
animateProgressBars(container);
|
||
progressAnimatedMap.set(container, true);
|
||
progressPermanentMap.set(container, true); // 标记永久触发
|
||
}
|
||
});
|
||
});
|
||
|
||
// 缩放处理(仅刷新样式,不重复动画)
|
||
let progressResizeTimer = null;
|
||
const handleProgressResize = () =>
|
||
{
|
||
clearTimeout(progressResizeTimer);
|
||
progressResizeTimer = setTimeout(() =>
|
||
{
|
||
progressContainers.forEach(container =>
|
||
{
|
||
const isPermanent = progressPermanentMap.get(container);
|
||
if (isPermanent) {
|
||
const progressFills = container.querySelectorAll('.progress-fill');
|
||
progressFills.forEach(fill =>
|
||
{
|
||
clearTimeout(fill._animateTimer);
|
||
const targetValue = fill.getAttribute('data-value');
|
||
fill.style.width = targetValue + '%'; // 直接设置最终宽度
|
||
});
|
||
}
|
||
});
|
||
}, 200);
|
||
};
|
||
|
||
// 初始化进度条
|
||
const initAllProgressContainers = () =>
|
||
{
|
||
setTimeout(() =>
|
||
{
|
||
progressContainers.forEach(container =>
|
||
{
|
||
if (!progressPermanentMap.get(container) && isProgressContainerAbove(container)) {
|
||
animateProgressBars(container);
|
||
progressAnimatedMap.set(container, true);
|
||
progressPermanentMap.set(container, true);
|
||
}
|
||
});
|
||
}, 100);
|
||
};
|
||
|
||
// 事件绑定
|
||
window.addEventListener('scroll', () => handleProgressScroll(false), { passive: true });
|
||
window.addEventListener('resize', handleProgressResize);
|
||
document.addEventListener('DOMContentLoaded', initAllProgressContainers);
|
||
|
||
// 视频/图片切换(修复缩放隐藏)
|
||
const allVideos = document.querySelectorAll('.fs-video');
|
||
function stopAllVideos ()
|
||
{
|
||
allVideos.forEach((video) =>
|
||
{
|
||
video.pause();
|
||
video.style.display = 'none';
|
||
const img = video.parentElement.querySelector('.fs-img');
|
||
if (img) img.style.display = 'block';
|
||
});
|
||
}
|
||
|
||
let isVideoResizing = false;
|
||
let videoResizeTimer = null;
|
||
|
||
// 滚动处理
|
||
const handleVideoScroll = () =>
|
||
{
|
||
if (isVideoResizing) return;
|
||
|
||
const productRights = document.querySelectorAll('.fs-box');
|
||
let activeVideo = null;
|
||
productRights.forEach((rightContainer) =>
|
||
{
|
||
const img = rightContainer.querySelector('.fs-img');
|
||
const video = rightContainer.querySelector('.fs-video');
|
||
const videoSrc = video.src.trim()
|
||
if (!img || !video) return;
|
||
if (!videoSrc) return;
|
||
const rect = rightContainer.getBoundingClientRect();
|
||
const isInView =
|
||
rect.top < window.innerHeight * 0.7 &&
|
||
rect.bottom > window.innerHeight * 0.3;
|
||
|
||
if (isInView) {
|
||
activeVideo = video;
|
||
}
|
||
});
|
||
|
||
if (activeVideo) {
|
||
stopAllVideos();
|
||
const img = activeVideo.parentElement.querySelector('.fs-img');
|
||
img.style.display = 'none';
|
||
activeVideo.style.display = 'block';
|
||
|
||
if (activeVideo.paused) {
|
||
activeVideo.play().catch((err) =>
|
||
{
|
||
console.log('视频播放失败(浏览器限制):', err);
|
||
activeVideo.style.display = 'none';
|
||
img.style.display = 'block';
|
||
});
|
||
}
|
||
} else {
|
||
stopAllVideos();
|
||
}
|
||
};
|
||
|
||
// 缩放处理
|
||
const handleVideoResize = () =>
|
||
{
|
||
clearTimeout(videoResizeTimer);
|
||
isVideoResizing = true;
|
||
videoResizeTimer = setTimeout(() =>
|
||
{
|
||
isVideoResizing = false;
|
||
// 保留视频播放状态
|
||
const playingVideo = document.querySelector('.fs-video[style*="display: block"]');
|
||
if (playingVideo) {
|
||
const img = playingVideo.parentElement.querySelector('.fs-img');
|
||
img.style.display = 'none';
|
||
playingVideo.style.display = 'block';
|
||
}
|
||
}, 200);
|
||
};
|
||
|
||
window.addEventListener('scroll', handleVideoScroll, { passive: true });
|
||
window.addEventListener('resize', handleVideoResize);
|
||
|
||
// 图片放大动效(修复缩放重置)
|
||
document.addEventListener('DOMContentLoaded', function ()
|
||
{
|
||
const zoomImages = document.querySelectorAll('.zoom-image');
|
||
let isResizing = false;
|
||
let resizeTimer = null;
|
||
|
||
// 判断图片是否在上方
|
||
const isImageAboveViewport = (image) =>
|
||
{
|
||
const rect = image.getBoundingClientRect();
|
||
return rect.bottom <= 0 || (rect.top < window.innerHeight * (2 / 3) && rect.bottom > 0);
|
||
};
|
||
|
||
const debounce = (fn) =>
|
||
{
|
||
let timer = null;
|
||
return () =>
|
||
{
|
||
clearTimeout(timer);
|
||
timer = setTimeout(() =>
|
||
{
|
||
if (!isResizing) fn();
|
||
}, 16);
|
||
};
|
||
};
|
||
|
||
const handleScroll = debounce(() =>
|
||
{
|
||
zoomImages.forEach(image =>
|
||
{
|
||
const imageRect = image.getBoundingClientRect();
|
||
const windowHeight = window.innerHeight;
|
||
const triggerPoint = windowHeight * (2 / 3);
|
||
|
||
if (imageRect.top < triggerPoint && imageRect.bottom > 0) {
|
||
image.classList.add('active');
|
||
} else {
|
||
image.classList.remove('active');
|
||
}
|
||
});
|
||
});
|
||
|
||
// 缩放处理
|
||
const handleResize = () =>
|
||
{
|
||
clearTimeout(resizeTimer);
|
||
isResizing = true;
|
||
resizeTimer = setTimeout(() =>
|
||
{
|
||
isResizing = false;
|
||
// 保留已放大状态
|
||
zoomImages.forEach(image =>
|
||
{
|
||
if (image.classList.contains('active')) {
|
||
image.classList.add('active');
|
||
}
|
||
});
|
||
}, 200);
|
||
};
|
||
|
||
// 初始化
|
||
const initZoomImages = () =>
|
||
{
|
||
zoomImages.forEach(image =>
|
||
{
|
||
if (isImageAboveViewport(image)) {
|
||
image.classList.add('active');
|
||
}
|
||
});
|
||
};
|
||
|
||
window.addEventListener('scroll', handleScroll, { passive: true });
|
||
window.addEventListener('resize', handleResize);
|
||
window.addEventListener('load', initZoomImages);
|
||
document.addEventListener('DOMContentLoaded', initZoomImages);
|
||
window.dispatchEvent(new Event('scroll'));
|
||
});
|
||
|
||
// 图片对比滑块
|
||
$(document).ready(function ()
|
||
{
|
||
$('.ba-slider').beforeAfter({
|
||
startPercent: 50,
|
||
handle: '.handle',
|
||
resize: '.resize'
|
||
});
|
||
});
|
||
|
||
// Tab切换(图/视频)
|
||
const tabItems = document.querySelectorAll('.tab-item');
|
||
const tabPanels = document.querySelectorAll('.tab-panel');
|
||
const tabPs = document.querySelectorAll('.tabs-p');
|
||
console.log(tabPs,'=tabPs=')
|
||
const indicator = document.querySelector('.tab-indicator');
|
||
const securityVideo = document.getElementById('securityVideo');
|
||
|
||
let prevIndex = 0;
|
||
const tabRects = [];
|
||
|
||
function cacheTabRects ()
|
||
{
|
||
tabRects.length = 0;
|
||
tabItems.forEach(item =>
|
||
{
|
||
tabRects.push({
|
||
left: item.offsetLeft,
|
||
width: item.offsetWidth
|
||
});
|
||
});
|
||
const initRect = tabRects[0];
|
||
indicator.style.width = initRect.width + 'px';
|
||
indicator.style.transform = `translateX(${initRect.left}px)`;
|
||
}
|
||
|
||
cacheTabRects();
|
||
|
||
// 重置视频
|
||
function resetVideo ()
|
||
{
|
||
if (securityVideo) {
|
||
securityVideo.pause();
|
||
securityVideo.currentTime = 0;
|
||
}
|
||
}
|
||
|
||
// 播放视频
|
||
function playVideo ()
|
||
{
|
||
if (securityVideo) {
|
||
securityVideo.play().catch(err =>
|
||
{
|
||
console.log('自动播放失败,请手动点击播放:', err);
|
||
});
|
||
}
|
||
}
|
||
|
||
// Tab点击事件
|
||
tabItems.forEach(item =>
|
||
{
|
||
item.addEventListener('click', () =>
|
||
{
|
||
const index = parseInt(item.dataset.index);
|
||
if (index === prevIndex) return;
|
||
|
||
tabItems[prevIndex].classList.remove('active');
|
||
item.classList.add('active');
|
||
|
||
tabPanels[prevIndex].classList.remove('active');
|
||
tabPanels[index].classList.add('active');
|
||
|
||
// console.log(tabPs[prevIndex],'========tabPs[prevIndex]==========')
|
||
tabPs[prevIndex].classList.remove('active');
|
||
tabPs[index].classList.add('active');
|
||
|
||
// 视频逻辑
|
||
if (index === 1) {
|
||
playVideo();
|
||
} else if (prevIndex === 1) {
|
||
resetVideo();
|
||
}
|
||
|
||
// 指示器动画
|
||
const rect = tabRects[index];
|
||
indicator.style.width = rect.width + 'px';
|
||
indicator.style.transform = `translateX(${rect.left}px)`;
|
||
|
||
prevIndex = index;
|
||
});
|
||
});
|
||
|
||
// 缩放适配
|
||
window.addEventListener('resize', () =>
|
||
{
|
||
cacheTabRects();
|
||
const currentRect = tabRects[prevIndex];
|
||
indicator.style.width = currentRect.width + 'px';
|
||
indicator.style.transform = `translateX(${currentRect.left}px)`;
|
||
});
|
||
|
||
// 移动端touch事件
|
||
tabItems.forEach(item =>
|
||
{
|
||
item.addEventListener('touchstart', (e) =>
|
||
{
|
||
e.preventDefault();
|
||
item.click();
|
||
}, { passive: false });
|
||
});
|
||
|
||
// 初始化视频状态
|
||
document.addEventListener('DOMContentLoaded', () =>
|
||
{
|
||
resetVideo();
|
||
});
|
||
|
||
// 自定义轮播(场景)
|
||
const carouselImgs = document.querySelector('.carousel-imgs');
|
||
const imgItems = document.querySelectorAll('.carousel-img');
|
||
const leftArrow = document.querySelector('.arrow-left');
|
||
const rightArrow = document.querySelector('.arrow-right');
|
||
const textItems = document.querySelectorAll('.carousel-text');
|
||
|
||
const imgCount = imgItems.length;
|
||
let imgWidth = imgItems[0]?.offsetWidth || 800;
|
||
let currentIndex = 0;
|
||
let autoPlayTimer = null;
|
||
let carouselResizeTimer = null;
|
||
|
||
// 缩放适配
|
||
const handleCarouselResize = () =>
|
||
{
|
||
clearTimeout(carouselResizeTimer);
|
||
carouselResizeTimer = setTimeout(() =>
|
||
{
|
||
imgWidth = imgItems[0].offsetWidth;
|
||
carouselImgs.style.transform = `translateX(-${currentIndex * imgWidth}px)`;
|
||
}, 200);
|
||
};
|
||
|
||
// 加载时初始化宽度
|
||
window.addEventListener('load', () =>
|
||
{
|
||
imgWidth = imgItems[0].offsetWidth;
|
||
carouselImgs.style.transform = `translateX(-${currentIndex * imgWidth}px)`;
|
||
});
|
||
|
||
// 切换轮播
|
||
function switchCarousel (index)
|
||
{
|
||
currentIndex = index;
|
||
if (currentIndex < 0) {
|
||
currentIndex = imgCount - 1;
|
||
} else if (currentIndex >= imgCount) {
|
||
currentIndex = 0;
|
||
}
|
||
|
||
carouselImgs.style.transform = `translateX(-${currentIndex * imgWidth}px)`;
|
||
// 文字联动
|
||
textItems.forEach((item, idx) =>
|
||
{
|
||
item.classList.toggle('active', idx === currentIndex);
|
||
});
|
||
}
|
||
|
||
// 箭头事件
|
||
leftArrow.addEventListener('click', () =>
|
||
{
|
||
switchCarousel(currentIndex - 1);
|
||
restartAutoPlay();
|
||
});
|
||
|
||
rightArrow.addEventListener('click', () =>
|
||
{
|
||
switchCarousel(currentIndex + 1);
|
||
restartAutoPlay();
|
||
});
|
||
|
||
// 自动轮播
|
||
function autoPlay ()
|
||
{
|
||
clearInterval(autoPlayTimer);
|
||
autoPlayTimer = setInterval(() =>
|
||
{
|
||
switchCarousel(currentIndex + 1);
|
||
}, 2500);
|
||
}
|
||
|
||
// 重启自动轮播
|
||
function restartAutoPlay ()
|
||
{
|
||
clearInterval(autoPlayTimer);
|
||
autoPlay();
|
||
}
|
||
|
||
// 悬停暂停
|
||
document.querySelector('.carousel-wrapper').addEventListener('mouseenter', () =>
|
||
{
|
||
clearInterval(autoPlayTimer);
|
||
});
|
||
|
||
// 离开恢复
|
||
document.querySelector('.carousel-wrapper').addEventListener('mouseleave', () =>
|
||
{
|
||
autoPlay();
|
||
});
|
||
|
||
// 初始化自动轮播
|
||
autoPlay();
|
||
|
||
// 事件绑定
|
||
window.addEventListener('resize', handleCarouselResize);
|
||
window.addEventListener('beforeunload', () =>
|
||
{
|
||
clearInterval(autoPlayTimer);
|
||
});
|
||
</script>
|
||
{/block} |