', {
id: 'pinElementPlaceholder',
css: {
'height': progressBarFullHeight + 'px',
'width': '100%',
'visibility': 'hidden',
'pointer-events': 'none'
}
})
$swiperContainer.before($newPlaceholder)
const parentPosition = $parent.css('position')
if (parentPosition === 'static') {
$parent.css('position', 'relative')
}
} else {
$placeholder.css('height', progressBarFullHeight + 'px')
}
$swiperContainer.css({
'position': 'absolute',
'top': '0',
'left': '0',
'width': '100%',
'height': '100%',
'z-index': '7'
})
placeholderInitialized = true
// 重新获取占位div位置
if ($placeholder.length) {
placeholderTop = $placeholder.offset().top
}
// 重新触发滚动检查
handleScroll()
}
// 延迟初始化占位div,确保DOM完全加载
setTimeout(() => {
updatePlaceholderHeight()
}, 300)
// ========== 平滑滚动函数 ==========
function smoothScrollTo(targetScrollTop) {
if (isScrolling) {
$htmlBody.stop()
}
isScrolling = true
$htmlBody.animate({
scrollTop: targetScrollTop
}, {
duration: 150,
easing: 'swing',
complete: function() {
setTimeout(() => {
isScrolling = false
// 滚动完成后强制检查一次滚动状态
handleScroll()
}, 50)
}
})
}
// ========== 核心:根据滚动位置计算进度 ==========
function calculateCurrentProgress(scrollTop) {
if (!placeholderInitialized || progressBarFullHeight <= 0) return 0
// 重新获取当前位置(可能在resize后变化)
if (!initCriticalPositions()) return 0
// 当滚动位置小于section2顶部时,进度为0
if (scrollTop < section2Top) {
return 0
}
// 当滚动位置超过进度结束位置时,进度为100%
if (scrollTop >= progressEndScrollTop) {
return 1
}
// 正常情况:计算在section2顶部和进度结束位置之间的进度
const progressScroll = scrollTop - section2Top
return Math.min(1, progressScroll / progressBarFullHeight)
}
// ========== 核心:根据进度计算滚动位置 ==========
function calculateScrollFromProgress(progress) {
if (!placeholderInitialized || progressBarFullHeight <= 0) return 0
// 重新获取当前位置(可能在resize后变化)
if (!initCriticalPositions()) return 0
progress = Math.max(0, Math.min(1, progress))
// 当进度为100%时,滚动到进度结束位置
if (progress >= 1) {
return progressEndScrollTop
}
// 正常情况:根据进度计算滚动位置
return section2Top + (progress * progressBarFullHeight)
}
// ========== 更新pinElement的定位状态 ==========
function updatePinElementPosition(scrollTop, isSection3AtBottom) {
if (!$swiperContainer.length || !placeholderInitialized) return
// 确保占位div位置正确
const $placeholder = $('#pinElementPlaceholder')
if ($placeholder.length) {
placeholderTop = $placeholder.offset().top
}
// 当section3出现在页面底部时,停止固定
if (isSection3AtBottom && isPinned) {
// 计算绝对定位的top值,使元素保持在当前视觉位置
const absoluteTop = scrollTop - placeholderTop
$swiperContainer.css({
'position': 'absolute',
'top': `${absoluteTop}px`,
'left': '0',
'width': '100%',
'z-index': '7'
})
isPinned = false
$swiperContainer.removeClass('pinned')
return
}
// 当滚动到section2顶部,且section3未出现在底部时,开始固定
if (scrollTop >= section2Top && !isPinned && !isSection3AtBottom) {
$swiperContainer.css({
'position': 'fixed',
'top': '0',
'left': '0',
'width': '100%',
'z-index': '1000'
})
isPinned = true
$swiperContainer.addClass('pinned')
} else if (scrollTop < section2Top && isPinned) {
// 切换回绝对定位(滚动到section2上方时)
const absoluteTop = Math.max(0, section2Top - placeholderTop)
$swiperContainer.css({
'position': 'absolute',
'top': `${absoluteTop}px`,
'left': '0',
'width': '100%',
'z-index': '7'
})
isPinned = false
$swiperContainer.removeClass('pinned')
}
// 如果不是固定状态,需要实时更新绝对定位的top值
if (!isPinned && !isSection3AtBottom && scrollTop >= section2Top) {
const absoluteTop = scrollTop - placeholderTop
$swiperContainer.css({
'position': 'absolute',
'top': `${absoluteTop}px`
})
}
}
// ========== 滚动监听函数 ==========
function handleScroll() {
// 如果在滚动动画中或正在拖拽,不处理滚动事件
if (isScrolling || isDragging || !placeholderInitialized) return
if (!$swiperContainer.length || !$section2.length || !$section3.length) return
const scrollTop = $window.scrollTop()
const windowHeight = $window.height()
// 重新获取关键位置
if (!initCriticalPositions()) return
// 计算section3是否出现在页面底部
const isSection3AtBottom = scrollTop + windowHeight >= section3Top
// 更新进度条
const newProgress = calculateCurrentProgress(scrollTop)
if (Math.abs(newProgress - currentProgress) > 0.001) {
currentProgress = newProgress
updateProgressDisplay(currentProgress)
updateSlideVisibilityByProgress(currentProgress)
}
// 更新pinElement的定位状态
updatePinElementPosition(scrollTop, isSection3AtBottom)
}
$window.on('scroll', function() {
if (!isDragging) {
handleScroll()
}
})
// 初始检查一次
setTimeout(() => {
handleScroll()
}, 500)
// ========== 初始化Swiper ==========
swiper = new Swiper(".ias-nianbao .mySwiper", {
slidesPerView: 2.5,
spaceBetween: 30,
allowTouchMove: false,
draggable: false,
mousewheel: false,
simulateTouch: false,
grabCursor: false,
observer: true,
observeParents: true,
speed: 600,
on: {
init: function () {
createProgressTicks()
updateProgressDisplay(0)
initializeSlideVisibility()
}
}
})
// ========== 进度条相关函数 ==========
function createProgressTicks() {
$progressContainer.find('.progress-tick, .progress-label').remove()
for (let i = 0; i < totalSlides; i++) {
const tickPosition = (i / (totalSlides - 1)) * 100
$('
')
.addClass('progress-tick')
.css('left', `${tickPosition}%`)
.appendTo($progressContainer)
const labelText = getSlideLabel(i + 1)
$('
')
.addClass('progress-label progress-label' + i)
.text(labelText)
.css('left', `${tickPosition}%`)
.appendTo($progressContainer)
}
}
function getSlideLabel(slideNumber) {
const labels = {
1: "步骤 01",
2: "步骤 02",
3: "步骤 03",
4: "步骤 04"
}
return labels[slideNumber] || `Slide ${slideNumber}`
}
function initializeSlideVisibility() {
if (swiper && swiper.slides && swiper.slides.length > 0) {
for (let i = 0; i < swiper.slides.length; i++) {
const slide = swiper.slides[i]
const $slide = $(slide)
$slide.toggleClass('visible', i === 0)
}
}
}
function updateProgressDisplay(progress) {
progress = Math.max(0, Math.min(1, progress))
const progressPercent = progress * 100
$progressFill.css('width', `${progressPercent}%`)
$progressHandle.css('left', `${progressPercent}%`)
const isAtBottom = progress >= 0.99
const isAtTop = progress <= 0.01
if (isAtBottom || isAtTop) {
$progressHandle.addClass('at-boundary')
} else {
$progressHandle.removeClass('at-boundary')
}
}
function updateSlideVisibilityByProgress(progress) {
if (!swiper) return
if (swiper.slides && swiper.slides.length > 0) {
$(swiper.slides[0]).addClass('visible')
$(swiper.slides[1]).toggleClass('visible', progress >= thresholds.slide2)
$(swiper.slides[2]).toggleClass('visible', progress >= thresholds.slide3)
$(swiper.slides[3]).toggleClass('visible', progress >= thresholds.slide4)
}
if (progress >= thresholds.startSlide) {
if (!isSlidingEnabled) {
isSlidingEnabled = true
setTimeout(() => {
swiper.slideTo(1, 800)
}, 150)
} else {
let targetSlide = 1
if (progress >= thresholds.slide4) targetSlide = 2
if (progress >= 0.95) targetSlide = 3
swiper.slideTo(targetSlide, 600, false)
}
} else {
if (isSlidingEnabled) {
isSlidingEnabled = false
swiper.slideTo(0, 800)
} else if (swiper.activeIndex !== 0) {
swiper.slideTo(0, 0, false)
}
}
}
// ========== 修复的滚轮处理函数 - 更小的增量 ==========
function handleWheelOnElement(e, isInPinElementArea) {
// 如果正在拖拽或滚动,直接返回允许默认行为
if (isDragging || isScrolling) return true
// 如果占位div还没初始化,允许默认滚动
if (!placeholderInitialized || progressBarFullHeight <= 0) return true
// ========== 关键修改:如果鼠标在pinElement区域但pinElement没有固定,允许默认滚动 ==========
if (isInPinElementArea && !isPinned) {
return true // 允许默认滚动行为
}
const now = Date.now()
// 节流处理:防止滚轮事件过于频繁
if (now - lastWheelTime < WHEEL_THROTTLE_TIME) {
return false // 忽略过于频繁的事件
}
lastWheelTime = now
// 获取滚轮delta值
const deltaY = e.originalEvent.deltaY
// 计算滚动方向
const isScrollingDown = deltaY > 0
// 获取当前滚动位置
const scrollTop = $window.scrollTop()
// 检查边界条件
// 如果正在向上滚动且已经在section2顶部之前,允许默认滚动
if (!isScrollingDown && scrollTop <= section2Top) {
return true
}
// 如果正在向下滚动且已经到达进度结束位置,允许默认滚动
if (isScrollingDown && scrollTop >= progressEndScrollTop) {
return true
}
// 计算滚轮delta对应的滚动距离 - 使用更小的因子
// WHEEL_SPEED_FACTOR = 0.0005 比之前的0.002小4倍
const scrollDelta = deltaY * WHEEL_SPEED_FACTOR * progressBarFullHeight
// 计算目标滚动位置
let targetScroll = scrollTop + scrollDelta
// 限制目标滚动位置在有效范围内
if (targetScroll < section2Top) {
// 如果向上滚动到section2之前,允许默认滚动
if (currentProgress <= 0.01) {
return true
}
targetScroll = section2Top
} else if (targetScroll > progressEndScrollTop) {
targetScroll = progressEndScrollTop
}
// 计算新进度
const newProgress = calculateCurrentProgress(targetScroll)
// 更新进度
if (Math.abs(newProgress - currentProgress) > 0.001) {
currentProgress = newProgress
updateProgressDisplay(currentProgress)
updateSlideVisibilityByProgress(currentProgress)
}
// 直接设置滚动位置
$window.scrollTop(targetScroll)
// 立即更新pinElement位置
const windowHeight = $window.height()
const isSection3AtBottom = targetScroll + windowHeight >= section3Top
updatePinElementPosition(targetScroll, isSection3AtBottom)
// 阻止默认滚轮行为
return false
}
// ========== 事件监听 ==========
// 点击进度条跳转
function handleProgressClick(e) {
if (isDragging || isScrolling) return
// 如果占位div还没初始化,不处理
if (!placeholderInitialized || progressBarFullHeight <= 0) return
// 检查是否点击了手柄区域
const $target = $(e.target)
if ($target.is('#progressHandle') || $target.closest('#progressHandle').length > 0) {
return
}
// 获取点击位置
const rect = $progressContainer[0].getBoundingClientRect()
const clickX = e.clientX - rect.left
const containerWidth = rect.width
// 计算点击的进度位置
const newProgress = Math.max(0, Math.min(1, clickX / containerWidth))
// 直接更新进度
currentProgress = newProgress
updateProgressDisplay(currentProgress)
updateSlideVisibilityByProgress(currentProgress)
// 跳转到对应位置
const targetScroll = calculateScrollFromProgress(currentProgress)
// 在滚动前先检查并更新pinElement状态
const windowHeight = $window.height()
const isSection3AtBottom = targetScroll + windowHeight >= section3Top
// 如果目标位置在section2和section3之间,应该固定
if (targetScroll >= section2Top && !isSection3AtBottom && !isPinned) {
$swiperContainer.css({
'position': 'fixed',
'top': '0',
'left': '0',
'width': '100%',
'z-index': '1000'
})
isPinned = true
$swiperContainer.addClass('pinned')
}
smoothScrollTo(targetScroll)
}
// 绑定点击事件
$progressContainer.on('click', handleProgressClick)
$progressFill.on('click', handleProgressClick)
// ========== 拖拽进度条手柄 ==========
$progressHandle.on('mousedown', function (e) {
e.preventDefault()
e.stopPropagation()
// 如果占位div还没初始化,不处理
if (!placeholderInitialized || progressBarFullHeight <= 0) return
isDragging = true
// 添加拖拽状态类
$progressHandle.addClass('dragging')
$progressContainer.addClass('dragging-active')
$(".ias-tpl-header").hide();
// 获取初始值
const containerRect = $progressContainer[0].getBoundingClientRect()
const containerWidth = containerRect.width
const startX = e.clientX
const startProgress = currentProgress
// 关键修复:监听整个document的mousemove,而不是限制在进度条区域
function onHandleDrag(moveEvent) {
moveEvent.preventDefault()
// 计算鼠标位置
const currentX = moveEvent.clientX
const deltaX = currentX - startX
// 计算进度变化
const deltaProgress = deltaX / containerWidth
const newProgress = Math.max(0, Math.min(1, startProgress + deltaProgress))
// 更新进度
if (Math.abs(newProgress - currentProgress) > 0.0001) {
currentProgress = newProgress
// 只更新left样式
const progressPercent = currentProgress * 100
$progressHandle.css('left', `${progressPercent}%`)
$progressFill.css('width', `${progressPercent}%`)
// 更新swiper可见性
updateSlideVisibilityByProgress(currentProgress)
// 计算目标滚动位置
const targetScroll = calculateScrollFromProgress(currentProgress)
// 直接设置滚动位置
$window.scrollTop(targetScroll)
// 立即更新pinElement位置
const windowHeight = $window.height()
const isSection3AtBottom = targetScroll + windowHeight >= section3Top
updatePinElementPosition(targetScroll, isSection3AtBottom)
}
}
// 拖拽结束函数
function stopHandleDrag() {
$(".ias-tpl-header").show();
// 移除事件监听器
$document
.off('mousemove', onHandleDrag)
.off('mouseup', stopHandleDrag)
// 移除拖拽状态类
$progressHandle.removeClass('dragging')
$progressContainer.removeClass('dragging-active')
// 确保最终位置正确
const finalScrollTop = $window.scrollTop()
const finalProgress = calculateCurrentProgress(finalScrollTop)
if (Math.abs(finalProgress - currentProgress) > 0.01) {
currentProgress = finalProgress
updateProgressDisplay(currentProgress)
updateSlideVisibilityByProgress(currentProgress)
}
// 重置状态
isDragging = false
// 拖拽结束后强制检查一次
setTimeout(() => {
handleScroll()
}, 50)
}
// 绑定事件监听器到整个document,这样即使鼠标离开进度条区域也能继续拖拽
$document
.on('mousemove', onHandleDrag)
.on('mouseup', stopHandleDrag)
// 防止选中文本
$document.on('selectstart', function(e) {
e.preventDefault()
return false
})
// 防止拖拽时触发其他事件
return false
})
// 绑定滚轮事件到pinElement区域
$swiperContainer.on('wheel', function(e) {
// 处理滚轮事件,传入true表示在pinElement区域
const allowDefault = handleWheelOnElement(e, true)
if (!allowDefault) {
e.preventDefault()
e.stopPropagation()
}
return allowDefault
})
// 绑定滚轮事件到进度条区域 - 注意:进度条区域不受限制
$progressContainer.on('wheel', function(e) {
// 处理滚轮事件,传入false表示在进度条区域(进度条区域总是可以控制)
const allowDefault = handleWheelOnElement(e, false)
if (!allowDefault) {
e.preventDefault()
e.stopPropagation()
}
return allowDefault
})
// 初始更新
setTimeout(() => {
if (swiper && swiper.initialized) {
createProgressTicks()
updateProgressDisplay(0)
}
}, 300)
// 窗口大小变化时更新
let resizeTimeout
$window.on('resize', function () {
clearTimeout(resizeTimeout)
resizeTimeout = setTimeout(() => {
// 重新初始化关键位置
initCriticalPositions()
createProgressTicks()
updateProgressDisplay(currentProgress)
// 更新占位div的高度
updatePlaceholderHeight()
// 重新触发滚动检查
if (!isDragging) {
handleScroll()
}
}, 200)
})
} else {
// 移动端代码保持不变
var mySwiper = new Swiper('.mySwiper', {
loop: false,
pagination: {
el: '#progressContainer',
clickable: true,
renderBullet: function (index, className) {
let text = ''
switch (index) {
case 0: text = '步骤 01'; break
case 1: text = '步骤 02'; break
case 2: text = '步骤 03'; break
case 3: text = '步骤 04'; break
}
return `${text}`
},
},
navigation: {
nextEl: '.swiper-button-next01',
prevEl: '.swiper-button-prev01',
},
slidesPerView: 1,
speed: 500,
autoplay: false,
spaceBetween: 14,
keyboard: true,
observer: true,
observeParents: true,
on: {
transitionStart: function (mySwiper) {
$('.mySwiper').find('img').trigger('appear')
},
slideChangeTransitionEnd: function () {
gatabswiper(this)
},
},
})
}
})
$(function () {
var screenwidth = $(window).width()
// WebP支持检测(首次运行时缓存结果)
function checkWebPSupport(callback) {
if (
typeof localStorage !== "undefined" &&
localStorage.getItem("webpSupport") !== null
) {
return callback(localStorage.getItem("webpSupport") === "true")
}
const img = new Image()
img.onload = function () {
const result = img.width > 0 && img.height > 0
localStorage.setItem("webpSupport", result)
callback(result)
}
img.onerror = function () {
localStorage.setItem("webpSupport", false)
callback(false)
}
img.src =
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkYAAAAAYAAjCB0C8AAAAASUVORK5CYII="
}
checkWebPSupport(function (isSupported) {
$("img").each(function () {
const $img = $(this)
const webpSrc = $img
.closest("picture")
.find('source[type="image/webp"]')
.data("srcset")
const fallbackSrc = $img.data("src")
// 动态设置真实图片路径
$img.data("original", isSupported ? webpSrc : fallbackSrc)
})
$("img").lazyload({
threshold: 200,
effect: "fadeIn",
appear: function () {
const realSrc = $(this).data("original")
$(this).attr("src", realSrc)
$(this).addClass("lazy-loaded")
},
load: function () {
$(this).addClass("lazy-loaded")
},
error: function () {
$(this).attr("src", "img/error.jpg")
},
})
})
// 初始化懒加载
$("img").lazyload({
effect: "fadeIn", // 淡入效果
threshold: 100, // 提前300px加载
failure_limit: 15, // 最大容错数量
skip_invisible: true, // 加载隐藏图片
appear: function () {
// 加载前回调
$(this).css("background", "transparent")
$(this).removeClass("lazyload")
},
load: function () {
// 加载完成回调
$(this).addClass("lazy-loaded")
},
})
// 20260202
// 轮播一
var mySwiper = new Swiper('.as-tpl-hm-banner01', {
loop: false,
pagination: {
el: '.swiper-pagination01',
clickable: true,
renderBullet: function (index, className) {
switch (index) {
case 0:
text = '步骤 01'
break
case 1:
text = '步骤 02'
break
case 2:
text = '步骤 03'
break
}
return (
'' +
text +
''
)
},
},
navigation: {
nextEl: '.swiper-button-next01',
prevEl: '.swiper-button-prev01',
},
slidesPerView: 1,
speed: 500,
autoplay: false,
spaceBetween: 14,
keyboard: true,
observer: true,
observeParents: true,
breakpoints: {
900: {
// PC端
loop: false,
slidesPerView: 3,
spaceBetween: 18,
keyboard: true,
observer: true,
observeParents: true,
// slideToClickedSlide: true,
},
},
on: {
transitionStart: function (mySwiper) {
},
slideChangeTransitionEnd: function () {
$('.as-tpl-hm-banner01').find('img').trigger('appear')
gatabswiper(this)
},
},
})
if (screenwidth < 900) {
setTimeout(function () {
$('.ias-tpl-hmpc-show ').remove()
}, 50)
// 华为乾崑app
$(document).on('click', '.ias-car-section06 .section06-con .wechat-con li h4', function (e) {
e.stopPropagation()
if ($(this).hasClass('active')) {
$(this).removeClass('active')
$(this).next('.mob-wechat-pop').hide()
} else {
$(this).addClass('active')
$(this).next('.mob-wechat-pop').show()
$(this).parent('li').siblings().find('.mob-wechat-pop').hide()
$(this).parent('li').siblings().find('h4').removeClass('active')
}
})
$(document).on('click', '.mob-wechat-pop', function (e) {
e.stopPropagation()
$(this).show()
})
$(document).on('click', function () {
$('.mob-wechat-pop').hide()
$('.ias-car-section06 .section06-con .wechat-con li h4').removeClass('active')
})
var kv_vd01 = $('.slide-ab01').data('url')
$('.slide-ab01').find('video').attr('src', kv_vd01)
// $('.slide-ab01').find('video')[0].play()
} else {
$('.ias-tpl-hmmob-show ').remove()
var vd01 = $('.vd01').data('url')
$('.vd01').find('video').attr('src', vd01)
}
$(".setion5_desc .tit").click(function(){
var _this = $(this)
_this.parent().toggleClass('active').siblings().removeClass('active');
_this.next().slideToggle();
_this.parent().siblings().find('.txt').slideUp();
if(screenwidth < 900){
$(".ias-mobile-tpl-header").hide();
setTimeout(function(){
$('html, body').animate({ scrollTop: _this.parent().offset().top - 150 }, 500);
setTimeout(function(){
$(".ias-mobile-tpl-header").show();
},500)
},500)
}
})
$(".setion5_desc .all.all1").click(function(){
$(".setion5_desc").addClass('active');
for(let i=0;i<$(".setion5_desc .list").length;i++){
$(".setion5_desc .list").eq(i).addClass('active');
$(".setion5_desc .list").eq(i).find('.txt').slideDown();
}
})
$(".setion5_desc .all.all2").click(function(){
$(".setion5_desc").removeClass('active');
for(let i=0;i<$(".setion5_desc .list").length;i++){
$(".setion5_desc .list").eq(i).removeClass('active');
$(".setion5_desc .list").eq(i).find('.txt').slideUp();
}
})
})
document.addEventListener('DOMContentLoaded', function() {
var video = document.getElementById('myVideo');
// 微信环境检测
function isWeixin() {
return /MicroMessenger/i.test(navigator.userAgent);
}
if (isWeixin()) {
// 微信环境下使用WeixinJSBridge
if (typeof WeixinJSBridge != "undefined") {
WeixinJSBridge.invoke('getNetworkType', {}, function() {
video.play();
});
} else {
document.addEventListener('WeixinJSBridgeReady', function() {
WeixinJSBridge.invoke('getNetworkType', {}, function() {
video.play();
});
}, false);
}
} else {
// 非微信环境正常播放
video.play().catch(function(e) {
console.log("Autoplay prevented:", e);
});
}
});