技术难点总结
作者:互联网
1.景深滚轮动画切换,参考:https://blog.csdn.net/weixin_30596343/article/details/97304484
<template> <div class="swiper-certify"> <div @mouseenter="onMouseEnter" @mouseleave="onMouseLeave" class="swiper-certif-list"> <li v-for="(item,index) in swiperOption.equip" :key="index" :class="classRender[index]" @click="slideClick(classRender[index])" class="centerPosition" > <div class="equip"> <div class="equip__bottom"> <div :style="{backgroundImage:`url(${item.img})`}" class="equip__bottom-img" /> <div class="equip__bottom-name"> {{ item.name }} </div> </div> </div> </li> </div> <div @click="toLeft" @mouseenter="onMouseEnter" @mouseleave="onMouseLeave" class="left"> <div class="left__img" /> </div> <div @click="toRight" @mouseenter="onMouseEnter" @mouseleave="onMouseLeave" class="right"> <div class="right__img" /> </div> </div> </template> <script> export default { props: { swiperOption: { type: Object } }, data () { return { max: 0, index: 0, classCenter: "p4", classLeft: ['p2', 'p3'], classRight: ['p5', 'p6'], leftHide: "p0", rightHide: "p7", hideNum: "", classRender: [], timerT: null }; }, created () { this.equip = this.swiperOption.equip || []; this.max = this.equip.length; this.startIndex = this.swiperOption.startIndex || 0; this.hideNum = Math.floor((this.max - 5) / 2); this.change(0); }, mounted () { this.init(); this.timer = setInterval(() => { this.autoClick("p5"); }, 5000); }, beforeMount () { clearInterval(this.timer); }, methods: { init () { if (this.max <= 5) { this.refresh(); } else if (this.max > 5) { this.refresh(); } }, goDetail (e, url) { if (e === this.classCenter) { window.open(url); } }, change (dir) { let index = this.index; index = index + dir; if (index < 0) { index = this.max - 1; } if (index >= this.max) { index = 0; } this.index = index; // 当前展示第 index 个 this.refresh(); }, refresh () { const index = this.index; if (index < 0 || index >= this.max) { return; } // 因为只展示五个 const arr = new Array(this.max); let left = index - 1; let right = index + 1; arr[index] = this.classCenter; let count = this.hideNum + 1; // 左右都需要减两次 const classLeft = this.classLeft.slice(0); while (count >= 0) { if (left < 0) { left = this.max - 1; } if (classLeft.length >= 0) { arr[left] = classLeft.pop(); } else { arr[left] = this.leftHide; } left--; count--; } count = this.hideNum + 1; const classRight = this.classRight.slice(0); while (count >= 0) { if (right >= this.max) { right = 0; } if (classRight.length) { arr[right] = classRight.shift(); } else { arr[right] = this.rightHide; } right++; count--; } for (let i = 0; i < arr.length; i++) { if (!arr[i]) { arr[i] = this.rightHide; } } this.classRender = arr; }, slideClick (cls) { if (cls === this.classLeft[1]) { // 左 this.change(-1); this.$emit("change", this.index); } else if (cls === this.classLeft[0]) { this.change(-1); setTimeout(() => { this.change(-1); }, 100); this.$emit("change", this.index - 1); } else if (cls === this.classRight[0]) { // 右 this.change(1); this.$emit("change", this.index); } else if (cls === this.classRight[1]) { this.change(1); setTimeout(() => { this.change(1); }, 100); this.$emit("change", this.index + 1); } }, autoClick (cls) { if (cls === this.classLeft[1]) { // 左 this.change(-1); this.$emit("change", this.index); } else if (cls === this.classLeft[0]) { this.change(-1); setTimeout(() => { this.change(-1); }, 100); this.$emit("change", this.index - 1); } else if (cls === this.classRight[0]) { // 右 this.change(1); this.$emit("change", this.index); } else if (cls === this.classRight[1]) { this.change(1); setTimeout(() => { this.change(1); }, 100); this.$emit("change", this.index + 1); } }, toLeft () { this.change(-1); this.$emit("change", this.index); }, toRight () { this.change(1); this.$emit("change", this.index); }, onm ouseEnter (e) { clearInterval(this.timer); }, onm ouseLeave () { clearInterval(this.timer); this.timer = setInterval(() => { this.autoClick("p5"); }, 5000); } } }; </script> <style lang="scss" scoped> .swiper-certify { height: 400px; width: 100%; .centerPosition { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); } .swiper-certif-list { width: 100%; height: 100%; margin: auto; position: relative; li { width: 400px; position: absolute; transition: all 0.5s ease-out; cursor: pointer; .equip { width: 400px; height: 400px; background-size: cover; background-image: url("~@/assets/images/equip-bottom.png"); &__bottom { padding: 43px 100px; &-img { width: 200px; height: 200px; background-size: cover; background-image: url("~@/assets/images/equip-02.png"); } &-name { margin-top: 22px; font-family: pingfang SC, helvetica neue, arial, hiragino sans gb, microsoft yahei ui, microsoft yahei, simsun, sans-serif; font-size: 18px; color: #191919; text-align: center; line-height: 24px; font-weight: 700; } &-des { margin-top: 12px; font-family: pingfang SC, helvetica neue, arial, hiragino sans gb, microsoft yahei ui, microsoft yahei, simsun, sans-serif; font-size: 14px; color: #0a28e5; letter-spacing: 0; text-align: center; line-height: 20px; font-weight: 400; .go { margin-top: -20px; margin-left: 74px; transform: translateX(0); transition: all 0.5s ease-out; } } &-wait { margin-top: 12px; font-family: pingfang SC, helvetica neue, arial, hiragino sans gb, microsoft yahei ui, microsoft yahei, simsun, sans-serif; font-size: 14px; color: rgba(0, 0, 0, 0.3); letter-spacing: 0; text-align: center; line-height: 20px; font-weight: 400; } } } } } .left { position: absolute; left: 40px; top: 498px; width: 64px; height: 64px; padding: 20px; background: rgba(255, 255, 255, 0.5); border-radius: 50%; cursor: pointer; z-index: 2; &__img { width: 24px; height: 24px; opacity: 0.4; background-image: url("~@/assets/icons/arrow-left.svg"); } &:hover { background: rgba(255, 255, 255, 0.9); .left__img { opacity: 0.7; } } } .right { position: absolute; top: 498px; right: 40px; width: 64px; height: 64px; padding: 20px; background: rgba(255, 255, 255, 0.5); border-radius: 50%; cursor: pointer; z-index: 2; &__img { width: 24px; height: 24px; opacity: 0.4; background-image: url("~@/assets/icons/arrow-right.svg"); } &:hover { background: rgba(255, 255, 255, 0.9); .right__img { opacity: 0.7; } } } .p0 { opacity: 0; transform: translate3d(-202%, -59%, 0) scale(0.4); z-index: 0; } .p2 { opacity: 0.4; transform: translate3d(-202%, -59%, 0) scale(0.5625); z-index: 1; } .p3 { transform: translate3d(-137%, -54%, 0) scale(0.75); opacity: 0.7; z-index: 2; } .p4 { transform: translate3d(-50%, -50%, 0) scale(1); z-index: 3; opacity: 1; &:hover { .go { transform: translateX(8px) !important; } } } .p5 { transform: translate3d(37%, -54%, 0) scale(0.75); opacity: 0.7; z-index: 2; } .p6 { opacity: 0.4; transform: translate3d(102%, -59%, 0) scale(0.5625); z-index: 1; } .p7 { opacity: 0; transform: translate3d(102%, -59%, 0) scale(0.5625); z-index: 0; } } </style>
2.卡片切换,参考:https://blog.csdn.net/weixin_30596343/article/details/97304484
<template> <div class="swiper-certify"> <div class="swiper-certif-list"> <div class="label" /> <li v-for="(item,index) in swiperOption.open" :key="index" :class="classRender[index]" @click="slideClick(classRender[index],swiperOption.open[index])" class="centerPosition" > </li> </div> </div> </template> <script> export default { props: { swiperOption: { type: Object } }, data () { return { currentIndex: 0, modelList: [ { children: [] } ], max: 3, index: 0, classCenter: "modelCenter", classLeft: "modelLeft", classRight: "modelRight", classRender: [], timerT: null, icon: require("@/assets/icons/arrow-point.svg") }; }, created () { this.change(0); }, mounted () { this.$nextTick(() => { this.modelList = this.swiperOption.open[0].model; }); }, methods: { goPath (path) { window.open(path); }, change (dir) { this.currentIndex = 0; let index = this.index; index = index + dir; if (index < 0) { index = this.max - 1; } if (index >= this.max) { index = 0; } this.index = index; // 当前展示第 index 个 this.refresh(); this.$emit("change", this.index); }, refresh () { const index = this.index; if (index < 0 || index >= this.max) { return; } const arr = new Array(this.max); let left = index - 1; let right = index + 1; arr[index] = this.classCenter; if (left < 0) { left = this.max - 1; } arr[left] = this.classLeft; if (right === this.max) { right = 0; } arr[right] = this.classRight; this.classRender = arr; }, slideClick (cls, list) { this.modelList = list.model; if (cls == this.classLeft) { // 左 this.change(-1); } if (cls == this.classRight) { // 右 this.change(1); } }, modelChange (e, list) { this.currentIndex = e; this.modelList = list; } } }; </script> <style lang="scss" scoped> .swiper-certify { height: 100%; width: 100%; .swiper-certif-list { position: relative; width: 1520px; height: 100%; margin: auto; padding-top: 114px; .title { font-family: Microsoft YaHei; font-size: 36px; color: #000; letter-spacing: 0; text-align: center; font-weight: 400; } .des { margin-top: 20px; font-family: Microsoft YaHei; font-size: 16px; color: #000; letter-spacing: 0; text-align: center; font-weight: 400; } .label { position: absolute; width: 254px; height: 84px; left: 50%; top: 62px; background-image: url("~@/assets/images/open-label.png"); background-size: cover; transform: translateX(-50%); } li { position: absolute; transition: all 0.5s ease-out; .imgs { width: 100%; height: 100%; display: block; box-shadow: 0 0 8px 0 rgba(0, 0, 0, 0.16); border-radius: 16px; display: flex; justify-content: center; align-items: center; } } } @media screen and (max-width: 1600px) { .swiper-certif-list { width: 1242px !important; } } .centerPosition { position: absolute; top: 50%; transform: translateY(-50%); .inner { position: relative; width: 100%; height: 522px; overflow: hidden; background-size: 992px 822px; padding: 0 0 64px 0; box-shadow: 0 0 5px 0 rgba(0, 0, 0, 0.12), 0 4px 24px -8px rgba(0, 0, 0, 0.24); border-radius: 16px; &__title { margin-top: 32px; font-family: Microsoft YaHei; font-size: 20px; color: #000; letter-spacing: 0; text-align: center; font-weight: 400; transition: all 0.5s ease-out; transform: translateY(280px); } .flag { position: relative; display: block; margin: auto; opacity: 1; transition: all 0.5s ease-out; transform: translateY(277px); &__title { position: relative; font-family: Microsoft YaHei; font-size: 20px; color: #000; letter-spacing: 0; text-align: center; font-weight: 400; } &__des { position: relative; margin: 9px auto 0 auto; font-family: Microsoft YaHei; font-size: 14px; color: #4c4c4c; letter-spacing: 0; text-align: center; line-height: 20px; font-weight: 400; transition: all 0.5s ease-out; } } &__button { margin: 0 auto 0 auto; display: flex; justify-content: center; opacity: 0; transform: translateY(293px); transition: all 0.5s ease-out; cursor: pointer; &-item { min-width: 108px; height: 48px; margin-right: 14px; padding: 12px 22px; font-family: Microsoft YaHei; font-size: 16px; color: #4c4c4c; letter-spacing: 0; text-align: center; line-height: 24px; font-weight: 400; &:hover { background: rgba(255, 255, 255, 0.5); border-radius: 24px; color: #006734; } } &-point { min-width: 108px; height: 48px; margin-right: 14px; padding: 12px 22px; font-family: Microsoft YaHei; font-size: 16px; color: #000; letter-spacing: 0; text-align: center; line-height: 24px; font-weight: 400; opacity: 0.7; img { transform: translate(0, 2px); transition: transform 0.2s ease-in-out; } &:hover { opacity: 0.9; color: #000; img { transform: translate(4px, -2px); } } } .check { color: #006734; background: #fff; border-radius: 24px; } } &__model { position: relative; display: flex; justify-content: center; margin: 40px auto 0 auto; &-block { position: relative; width: 222px; height: 288px; margin-left: 8px; padding: 4px; background: rgba(255, 255, 255, 0.4); border: 0 solid rgba(255, 255, 255, 0.6); transform: translateY(50%) scale(0.01); transition: all 0.1s ease-out; cursor: pointer; .content { position: relative; width: 214px; height: 280px; padding: 24px 16px; background: #fff; text-align: center; .shading { position: absolute; width: 67px; height: 65px; top: 215px; right: 0; background-image: url("~@/assets/images/open-shading.png"); background-size: cover; opacity: 0; transition: all 0.3s ease-out; } .img { width: 48px; height: 48px; margin: auto; background-size: cover; } .title { margin-top: 12px; font-family: Microsoft YaHei-Bold; font-size: 14px; color: #191919; letter-spacing: 0; text-align: center; line-height: 20px; font-weight: 700; } .des { margin: 8px auto 0 auto; font-family: Microsoft YaHei; font-size: 14px; color: #4c4c4c; letter-spacing: 0; text-align: justify; line-height: 20px; font-weight: 400; } .detail { position: absolute; width: 71px; left: 50%; top: 244px; font-family: Microsoft YaHei; font-size: 14px; color: #244cf5; letter-spacing: 0; text-align: center; line-height: 24px; font-weight: 400; transform: translateX(-50%); cursor: pointer; .go { margin-top: -24px; margin-left: 68px; transform: translateX(0); transition: all 0.5s ease-out; } } .wait { position: absolute; width: 71px; left: 50%; top: 244px; font-family: Microsoft YaHei; font-size: 14px; color: rgba(0, 0, 0, 0.4); letter-spacing: 0; text-align: center; line-height: 24px; font-weight: 400; transform: translateX(-50%); } &:hover { box-shadow: 0 6px 24px -8px rgba(0, 0, 0, 0.4); .shading { opacity: 1; } .go { transform: translateX(8px); } } } &:nth-child(1) { margin-left: 0; } } } } @media screen and (max-width: 1600px) { .inner__model-block { width: 190px; .content { width: 182px; } } } } .modelLeft { width: 280px; height: 440px; transform: translate3d(2px, -37%, 0); transform-origin: 0 50%; z-index: 1; cursor: pointer; .imgs { background-position: center; background-repeat: no-repeat; } .inner { height: 440px; background-position-x: -359px; transition: all 0.5s ease-out; } .flag { width: 200px; } } .modelCenter { width: 992px; height: 522px; transform: translate3d(268px, -37%, 0); transform-origin: 0 50%; z-index: 5; opacity: 1; background-position: top; .inner__model-block { transform: translateY(0%) scale(1); transition: all 0.7s ease-out; } .flag { transform: translateY(0) !important; opacity: 0 !important; transition: all 0.5s ease-out; } .inner__button { transform: translateY(0) !important; opacity: 1; } .inner__title { transform: translateY(0) !important; } .inner { background-position-y: -300px; transition: all 0.5s ease-out; } .margin64 { margin-top: 64px !important; margin-bottom: -32px !important; } } .modelRight { width: 280px; height: 440px; transform: translate3d(1247px, -37%, 0); cursor: pointer; z-index: 1; .imgs { background-position: center; background-repeat: no-repeat; } .inner { height: 440px; background-position-x: -359px; transition: all 0.5s ease-out; } .flag { width: 200px; } } @media screen and (max-width: 1600px) { .modelLeft { width: 216px; .flag { width: 152px !important; } .inner { background-position-x: -388px; } } .modelCenter { width: 832px; transform: translate3d(205px, -37%, 0); .inner { background-position-x: -80px; } } .modelRight { width: 216px; transform: translate3d(1023px, -37%, 0); .flag { width: 152px !important; } .inner { background-position-x: -388px; } } } } </style>
3.滚动动画
lineClick (nav) { this.tabIndex = nav; const ele = document.documentElement; this.lineTop = this.$parent.$el.querySelector(`#${this.requestData.ids[this.tabIndex]}`).offsetTop; const targetTop = this.lineTop; const step = Math.abs((ele.scrollTop - targetTop) / 15); const smoothDown = () => { if (ele.scrollTop < targetTop) { // console.log(100) if (ele.scrollTop + step < targetTop) { ele.scrollTop += step; if (ele.scrollTop === (ele.scrollHeight - ele.clientHeight) || ele.scrollTop + ele.clientHeight + 1 >= ele.scrollHeight) { cancelAnimationFrame(smoothDown); } else { requestAnimationFrame(smoothDown); } } else { ele.scrollTop = targetTop; cancelAnimationFrame(smoothDown); } } }; const smoothUp = () => { if (ele.scrollTop > targetTop) { if (targetTop + step < ele.scrollTop) { ele.scrollTop -= step; requestAnimationFrame(smoothUp); } else { ele.scrollTop = targetTop; cancelAnimationFrame(smoothUp); } } }; if (ele.scrollTop < targetTop) { smoothDown(); } else { smoothUp(); } }
4.图片压缩,图片裁切:lzr插件,vue-cropper插件(cropper.js)
5.雪碧图帧动画:参考https://gitee.com/larntin/d-sprite
logo () { /* * obj:指定的父容器节点,其下运动对象是img * timespan: 动画播放,每一帧的时间间隔 * deltay:每一帧移动的高度 * maxHeight:图片的最大高度 */ const dsprite = (obj, timespan, deltay, maxHeight) => { // 获取 img 的 delta y const getCurDeltay = (obj) => { const img = obj.querySelector("img"); const _transform = img.style.transform; const reg = _transform.match(/\((.*?)px\)/); const deltay = parseInt(reg[1]) || 0; return deltay; }; // 设置 img 的 delta y const setCurDeltay = (obj, deltay) => { const img = obj.querySelector("img"); img.style.transform = `translateY(${deltay}px)`; }; let ani_time = null; const _maxHeight = maxHeight - deltay; let ani_diret = 1; // 1是正向,-1是反向 obj.addEventListener("mouseenter", (event) => { this.logoshow = false; // console.log("enter"); ani_diret = 1; if (!ani_time) { // 没有运行时间函数,就开始动画 // console.log("setup time"); ani_time = setInterval(() => { const _curY = getCurDeltay(obj); let newY = _curY - ani_diret * deltay; // console.log(`newY=${newY}`); if (newY <= -_maxHeight) { newY = -_maxHeight; setCurDeltay(obj, newY); } else if (newY >= 0) { newY = 0; setCurDeltay(obj, newY); if ((ani_diret === -1)) { clearInterval(ani_time); ani_time = null; } } else { setCurDeltay(obj, newY); } }, timespan); } }); obj.addEventListener("mouseleave", (event) => { if (ani_time) { this.logoshow = true; clearInterval(ani_time); ani_time = null; } }); }; const spr = document.querySelector(".header__top-spr"); dsprite(spr, 33, 40, 6000); } }
标签:总结,难点,index,技术,transform,height,width,font,change 来源: https://www.cnblogs.com/xiayihaoqing/p/16140031.html