// ==================== 通过宽度判断使用PC还是mobile样式 start ==================== // 是否是PC let isPC = true; // 屏幕可视宽度 let clientWidth = document.body.clientWidth; /** * 通过宽度判断显示pc样式,还是移动端样式 */ function checkWidth() { const scrollbarWidth = window.innerWidth - document.documentElement.clientWidth; let $el = document.querySelector("html"); let isPcClass = $el.classList.contains("pc-style"); let isMobileClass = $el.classList.contains("mobile-style"); // // PC端 if (clientWidth > (749 - scrollbarWidth)) { if (!isPcClass) { $el.classList.remove("mobile-style"); $el.classList.add("pc-style"); } isPC = true; } // 移动端 else if (clientWidth <= 749) { if (!isMobileClass) { $el.classList.remove("pc-style"); $el.classList.add("mobile-style"); } isPC = false; } return isPC; } window.isPC = checkWidth(); /** * 监听页面尺寸发生变化 */ window.addEventListener("resize", function () { // 实时监听浏览器窗口宽度 clientWidth = document.body.clientWidth; window.isPC = checkWidth(); }); // ==================== 通过宽度判断使用PC还是mobile样式 end ==================== // ==================== 基于Jq的锚点平滑过渡 start ==================== $('a[href*="#"]:not([href="#"])').click(function () { if ( location.pathname.replace(/^\//, "") == this.pathname.replace(/^\//, "") && location.hostname == this.hostname ) { var target = $(this.hash); target = target.length ? target : $("[name=" + this.hash.slice(1) + "]"); const headerHeight = window.isPC ? $("header .pc-nav").height() + 50 || 0 : $("header .head").height() || 0; if (target.length) { $("html, body").stop().animate( { scrollTop: target.offset().top - headerHeight, }, 700 ); return false; } } }); // ==================== 基于Jq的锚点平滑过渡 end ==================== // ==================== 禁止IOS双击放大网页 start ==================== // 缩放 try { // 禁用双击缩放 document.addEventListener("touchstart", function (event) { if (event.touches.length > 1) { event.preventDefault(); } }); var lastTouchEnd = 0; document.addEventListener( "touchend", function (event) { var now = new Date().getTime(); if (now - lastTouchEnd <= 300) { event.preventDefault(); } lastTouchEnd = now; }, false ); // 禁用双指手势操作 document.addEventListener("gesturestart", function (event) { event.preventDefault(); }); } catch (error) { } // ==================== 禁止IOS双击放大网页 end ==================== // ==================== 通用数字滚动 start ==================== // 判断是否有要滚动的数字,有的话给每个元素添加 data-scroll 属性 // 该属性用于判断元素是否滚动过 if ($(".scrolling-numbers").length > 0) { // jq设置属性如果是布尔值的话,需要使用prop不能使用attr $(".scrolling-numbers").prop("data-scroll", true); } // 窗口滚动事件 $(window).scroll(function () { // 当前滚动条距离顶部的距离 let scrollTop = $(window).scrollTop(); // 如果有要滚动的数字 if ($(".scrolling-numbers").length > 0) { // 遍历滚动的数字元素 $(".scrolling-numbers").each(function () { // 如果屏幕滚动到该元素可视范围,且该元素 data-scroll 属性为true(数字未滚动过),则执行滚动数字动画 if ( scrollTop > $(this).offset().top - 824 && $(this).prop("data-scroll") ) { let num = parseInt($(this).text()); $(this).animateNumber({number: num}, 5000); // 数字只滚动一次,执行过滚动动画后,把元素 data-scroll 属性设置为 false $(this).prop("data-scroll", false); } }); } }); // ==================== 通用数字滚动 end ==================== // ==================== 置顶按钮 start ==================== $("#goto-top").click(function () { $("html,body").animate( { scrollTop: 0, }, 500 ); }); $("#goto-top2").click(function () { $("html,body").animate( { scrollTop: 0, }, 500 ); }); // 监听页面滚动 $(document).scroll(function () { // if ($(window).scrollTop() >= $(window).height()) { $("#goto-top").addClass("show"); } else { $("#goto-top").removeClass("show"); } }); // ==================== 置顶按钮 end ==================== // ==================== 通用swiper切换初始化 start ==================== function initSwiperTab(id, el, pagination, option) { this.id = id; this.el = $(el); this.isPC = window.isPC; this.spaceBetween = this.isPC ? 20 : 10; this.pagination = pagination; this.option = option ? option : {}; this.even = "mouseover"; this.init = function () { const option = this.option; const id = this.id; const el = this.el; const spaceBetween = this.spaceBetween; const pagination = this.pagination; const even = this.even; let swiperObj; if (!$(id).length) return this; if (Object.keys(option).length) { if (!option.on) { option.on = { slideChange: function () { el.removeClass("active"); el.eq(this.activeIndex).addClass("active"); }, init: function () { el.eq(0).addClass("active"); }, }; } swiperObj = new Swiper(id, option); } else { swiperObj = new Swiper(id, { preventClicks: false, allowTouchMove: false, observer: true, observeParents: true, watchSlidesProgress: true, watchSlidesVisibility: true, autoHeight: true, spaceBetween: spaceBetween, speed: 1000, on: { slideChange: function () { el.removeClass("active"); el.eq(this.activeIndex).addClass("active"); }, init: function () { el.eq(0).addClass("active"); }, }, pagination: { el: pagination || "", clickable: true, }, }); } el.off(); el.on(even, function () { el.removeClass("active"); $(this).addClass("active"); swiperObj.slideTo($(this).index()); }); return { data: this, swiper: swiperObj }; }; } // ==================== 通用swiper切换初始化 end ==================== // ==================== 通用无缝滚动 start ==================== /** * 传入 swiper 初始化的容器对象,即可实现无缝滚动 * @param {*} el 需要滚动的父级容器 * @param {*} step 移动的距离,越大速度越快 * @param {*} direction 滚动方向,默认false(向右滚动) */ function autoSwiper(el, step, direction) { this.el = $(el); this.moveEl = $(el).find(".swiper-wrapper"); this.child = $(el).find(".swiper-slide"); this.direction = direction; this.step = step || 1; this.moveDistance = this.child.outerWidth(true) * this.child.length; this.moveEl.append(this.moveEl.html()); this.moveEl.css("transform", "translate3d(0,0,0)"); this.number = 0; this.animationFrame = null; } autoSwiper.prototype.init = function () { var self = this; var lastTime = null; function animate(timestamp) { if (!lastTime) { lastTime = timestamp; } var progress = timestamp - lastTime; if (self.direction) { if (self.number <= 0) { self.moveEl.css( "transform", "translate3d(" + (self.number += self.step) + "px,0,0)" ); } else { self.moveEl.css( "transform", "translate3d(-" + self.moveDistance + "px,0,0)" ); self.number = -self.moveDistance; } } else { if (self.number >= -self.moveDistance) { self.moveEl.css( "transform", "translate3d(" + (self.number -= self.step) + "px,0,0)" ); } else { self.number = 0; } } lastTime = timestamp; self.animationFrame = requestAnimationFrame(animate); } self.animationFrame = requestAnimationFrame(animate); }; autoSwiper.prototype.stop = function () { cancelAnimationFrame(this.animationFrame); }; autoSwiper.prototype.progress = function () { return this.number; }; autoSwiper.prototype.start = function (direction) { this.stop(); direction && (this.direction = direction) this.init(); }; // ==================== 通用无缝滚动 end ==================== // ==================== 滚动图帧实现 Start ==================== class InitScroll { /** * * @param {String} id 初始化的元素id * @param {String} source 图帧资源路径(文件夹路径) * @param {Number} number 图帧数量 * @param {String} type 图帧类型(png/jpg/webp) * @param {number} scrollDuration - 滚动的距离/可以理解成动画持续时间(默认为6000px) * @param {Object} scrollConfig - 滚动的插件配置项 */ constructor(id, source, number, type, scrollDuration = 6000, scrollConfig) { // 元素对象 this.element = document.getElementById(id); // 图帧资源路径 this.source = source; // 图帧数量 this.number = number; // 画布元素 this.canvas = document.createElement("canvas"); this.context = this.canvas.getContext("2d"); // this.canvas.width = this.element?.offsetWidth; this.canvas.height = this.element?.offsetHeight; this.progress = { el: null, // 进度条文案 text: null, // 进度条位置 width: null, }; // 文件类型 this.type = type; // 滚动距离 this.scrollDuration = scrollDuration; // 滚动的插件配置项 this.scrollConfig = scrollConfig } /** * 初始化进度条 */ initProgress() { // 进度条容器 this.progress.el = document.createElement("div"); this.progress.el.classList.add("mxw-loading"); // 进度条 this.progress.width = document.createElement("div"); this.progress.width.classList.add("mxw-progress-bar"); // 进度条数字 this.progress.text = document.createElement("span"); this.progress.width.append(this.progress.text); // this.progress.el.append(this.progress.width); this.element.append(this.progress.el); } /** * 初始化 */ init() { return new Promise(resolve => { // 获取图帧的长度 const length = this.number.toString().length; // 图帧路径 const currentFrame = index => `${this.source}/${(index + 1).toString().padStart(length, "0")}.${this.type }`; this.initProgress(); // 实例化一个加载对象 const loader = new PxLoader(); // 图帧数组 const images = []; // 视频当前帧 const video = { frame: 0 }; const canvas = this.canvas; const context = this.context; // for (let i = 0; i < this.number; i++) { images[i] = loader.addImage(currentFrame(i)); } // 监听下载进度 loader.addProgressListener(obj => { const { width, text } = this.progress; // 通过图帧总数求出百分比基数 let num = 100 / obj.totalCount; let progressWidth = (obj.completedCount * num).toFixed(0); // 设置进度条长度 width.style.width = progressWidth + "%"; // 设置进度条文本 text.textContent = progressWidth + "%"; }); // 监听下载完成的回调 loader.addCompletionListener(() => { }); // 隐藏占位图 this.element.getElementsByTagName("img")[0].style.display = "none"; // 将画布插入到元素中 this.element.append(this.canvas); // 隐藏加载时的占位 this.progress.el.remove(); let scrollTrigger = { trigger: this.element, scrub: 0.5, // markers: true, start: `top top`, end: `+=${this.scrollDuration}`, pin: true, }; scrollTrigger = this.scrollConfig ? { ...scrollTrigger, ...this.scrollConfig } : scrollTrigger; let tl = gsap.timeline({ scrollTrigger, }); tl.to(video, { frame: this.number - 1, snap: "frame", ease: "none", onUpdate: render, // use animation onUpdate instead of scrollTrigger's onUpdate }); // 绘制图片 function render() { context.clearRect(0, 0, canvas.width, canvas.height); context.drawImage( images[video.frame], 0, 0, canvas.width, canvas.height ); } render(); const that = this // 监听页面尺寸发生变化 window.addEventListener("resize", function () { setTimeout(function() { canvas.width = that.element?.offsetWidth; canvas.height = that.element?.offsetHeight; render(); // console.log(canvas.width); // console.log(canvas.height); },500) }); resolve(); // 开始加载 loader.start(); }); } } // ==================== 滚动图帧实现 End ====================