2000字范文,分享全网优秀范文,学习好帮手!
2000字范文 > 猫耳FM日期窗口实现

猫耳FM日期窗口实现

时间:2021-05-01 17:31:30

相关推荐

猫耳FM日期窗口实现

猫耳FM日期窗口实现

今天咱们继续来研究一下FM中 “精品周更” 的窗口滑动模型,这个模型比较新颖,但是只要找到规律后其实并复杂。

按照惯例,先来看看官方的效果图

再来看看模型最终实现效果图

我们可以发现,展示的item有6组,各组中的成员个数都不同,并且当有相应的组正在展示时,对应的标题才会出现,还可以发现比较有意思的是,有时候相应的标题并不会一直都与其下方的itemList保持相对的位置,有时候itemList发生了移动,但是标题并没有移动。是不是很有意思?别怕,其实只要你认真分析其中的规律,你会发现也就那样。

在这之前我们必须要确定好几个关系

不同档期类型之间的关系展示item之间的关系itemList 与 日期标题栏的关系日期标题之间的关系

一、不同档期类型之间的关系

不同档期类型之间在展示效果上并无任何的差别,都是排列在同一行,如何区别不同的档期的item,可以使用class属性来进行标识。

<div class="class1 item"></div><div class="class1 item"></div><div class="class1 item"></div><div class="class2 item"></div><div class="class2 item"></div><div class="class2 item"></div><div class="class2 item"></div><div class="class3 item"></div><div class="class3 item"></div><div class="class3 item"></div><div class="class4 item"></div><div class="class4 item"></div><div class="class5 item"></div><div class="class5 item"></div><div class="class5 item"></div><div class="class5 item"></div><div class="class5 item"></div><div class="class5 item"></div>

二、展示item之间的关系

由于各个item的展示只需左右并排移动若干个,所以我们可以直接将所有的item都并排在一行,每次移动直接移动一整行。

三、itemList 与 日期标题栏的关系

itemList的移动会影响日期标题,但是我们不能直接使用html结构把两者绑定起来,因为 itemList 与 日期标题的相对位置并非一直不变的,在移动itemList时需要使用一定的逻辑动态计算各个标题的下一个目标位置

<div class="titles"><span class="title1 title">今天 7.3</span><span class="title2 title">明天 7.4</span><span class="title3 title">后天 7.5</span><span class="title4 title">星期二 7.6</span><span class="title5 title">星期三 7.7</span><span class="title5 title">星期四 7.8</span></div><div class="itemList" id="itemList" style="left:0px;"><div class="class1 item"></div><div class="class1 item"></div><div class="class1 item"></div><div class="class1 item"></div><div class="class1 item"></div><div class="class2 item"></div><div class="class2 item"></div><div class="class2 item"></div><div class="class2 item"></div><div class="class3 item"></div><div class="class3 item"></div><div class="class3 item"></div><div class="class4 item"></div><div class="class4 item"></div><div class="class5 item"></div><div class="class5 item"></div><div class="class5 item"></div><div class="class5 item"></div><div class="class5 item"></div><div class="class5 item"></div><div class="class6 item"></div><div class="class6 item"></div><div class="class6 item"></div></div>

四、各个日期标题之间的关系

由于各个标题的之间相对位置也不是一直不变的,所以移动日期标题时,我们应该逐一确定各个标题的下一个位置。

确定好上述四个关系后,接下来就研究模型的规律已经实现的原理

一、itemList的移动动画

使用css3 transition 过渡 + js 改变itemList的left值来实现itemList向右移动:① item的左边突出的长度 d 的计算公式 d = -itemList.offsetLeft; ② 向右移动的距离:当 d > L (展示窗口的长度)时,移动距离为L,否则为ditemList向左移动:① item的左边突出的长度 d 的计算公式 d = itemList.clientWidth - L + itemList.offsetLeft;② 向左移动的距离:当 d > L 时,移动距离为L,否则为d

二、日期标题在移动时的位置确定

一般情况下日期标题的left都与每个档期的第一个元素的left值相等只有当档期的一边在左边,还有一边在窗口中(当前档期的第一元素的left < 0,且下一个档期的第一元素的left值 > 0),则标题位置为 left = 0标题的left值和每个档期的left值都是相对于展示窗口的左边界而言的

三、日期标题位置的移动

每次移动itemList时,都可以根据计算出来的将要移动的距离来预测itemList的未来位置,进而根据上述日期标题位置确定原则来确定日期标题的位置。

完整代码

<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><style>.platform {position: absolute;top: 50%;left: 50%;transform: translate(-50%, -50%);width: 980px;height: 290px;overflow: hidden;border: 1px solid #f00;}.itemList {position: absolute;top: 90px;overflow: hidden;box-sizing: border-box;transition: left 0.5s ease;}.item {float: left;width: 180px;height: 200px;box-sizing: border-box;margin-right: 20px;border: 1px solid #000;}#leftBtn,#rightBtn {display: inline-block;position: absolute;top: 63%;transform: translate(0, -50%);line-height: 30px;width: 30px;border-radius: 50%;background-color: #000;color: #fff;font-size: 26px;text-align: center;cursor: pointer;}.class1 {background-color: #0f0;}.class2 {background-color: #f00;}.class3 {background-color: #00f;}.class4 {background-color: #f0f;}.class5 {background-color: #ff0;}.class6 {background-color: #0ff;}#leftBtn {left: 10px;}#rightBtn {right: 10px;}.titles {position: relative;width: 100%;height: 60px;}.title {display: inline-block;position: absolute;top: 0px;width: 180px;height: 60px;line-height: 60px;text-align: left;border: 1px solid #f00;box-sizing: border-box;transition: left 0.5s ease;}</style></head><body><div class="platform"><div class="titles"><span class="title1 title">今天 7.3</span><span class="title2 title">明天 7.4</span><span class="title3 title">后天 7.5</span><span class="title4 title">星期二 7.6</span><span class="title5 title">星期三 7.7</span><span class="title5 title">星期四 7.8</span></div><div class="itemList" id="itemList" style="left:0px;"><div class="class1 item"></div><div class="class1 item"></div><div class="class1 item"></div><div class="class1 item"></div><div class="class1 item"></div><div class="class2 item"></div><div class="class2 item"></div><div class="class2 item"></div><div class="class2 item"></div><div class="class3 item"></div><div class="class3 item"></div><div class="class3 item"></div><div class="class4 item"></div><div class="class4 item"></div><div class="class5 item"></div><div class="class5 item"></div><div class="class5 item"></div><div class="class5 item"></div><div class="class5 item"></div><div class="class5 item"></div><div class="class6 item"></div><div class="class6 item"></div><div class="class6 item"></div></div><span id="leftBtn">&lt;</span><span id=rightBtn>&gt;</span></div><script>const items = document.querySelectorAll(".item");document.getElementById("itemList").style.width = 200 * items.length + 'px';const itemList = document.getElementById("itemList");const titles = document.getElementsByClassName('title');// 获取各个组的第一个元素const itemsFirst = (() => {const res = [];// 有6组,根据类名查找,类名、个数不能增减for (let i = 1; i <= 6; i++) {res.push(document.querySelector(`.class${i}`));}return res;})()itemList.moving = false; // 当前itemList的运动状态// 绑定点击事件document.getElementById("leftBtn").onclick = function () {if (itemList.moving) return;itemList.moving = true;// 0.5s 为移动期,该期间不能点击setTimeout(() => {itemList.moving = false;}, 500)const curValue = parseInt(itemList.style.getPropertyValue("left"));// 获取右移的最大移动量let distance = 200 * 5;let num = (- itemList.offsetLeft) / 200;if (num < 5) {distance = 200 * num;}displayTitles(distance);itemList.style.left = curValue + distance + 'px';}document.getElementById("rightBtn").onclick = function () {if (itemList.moving) return;itemList.moving = true;// 0.5s 为移动期,该期间不能点击setTimeout(() => {itemList.moving = false;}, 500)const curValue = parseInt(itemList.style.getPropertyValue("left"));// 获取左移的最大移动量let distance = 200 * 5;let num = (itemList.clientWidth - 1000 + itemList.offsetLeft) / 200;if (num < 5) {distance = 200 * num;}displayTitles(-distance);itemList.style.left = curValue - distance + 'px';}/*** 展示日期标题* 标题的放置* 1. 一般情况下日期标题的left都与每个档期的第一个元素的left值相等* * 2.只有当一边在左边,还有一边在窗口中(当前档期的第一元素的left < 0,且下一个档期的第一元素的left值 >0),则标题位置为 left = 0* * */// 定位各标题的位置function locateTitles(itemsFirst, titles, platformWidth, itemWidth, expected) {for (let i = 0; i < titles.length; i++) {// 一半在左边,一半在中间if (getRealOffset(itemsFirst[i]) + expected < 0 && itemsFirst.length > 1 && i < titles.length - 1 && getRealOffset(itemsFirst[i + 1]) + expected > 0) {titles[i].style.left = '0px';}// 其余情况else {titles[i].style.left = getRealOffset(itemsFirst[i]) + expected + 'px';}}}// 获取item 相对于platform的偏移量function getRealOffset(item) {return item.offsetLeft + item.offsetParent.offsetLeft;}// 初始定位标题位置locateTitles(itemsFirst, titles, 980, 200, 0)// 如果左移,则expected 为 负, 右移则 expected 为 正function displayTitles(expected) {// expected 将要移动的距离if (expected === 0) {return;}locateTitles(itemsFirst, titles, 980, 200, expected)}</script></body></html>

模型原理图

模型最终效果图

ps: 模型的实现方法多样,上述方法仅供参考,希望大家能多尝试其他方法。

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。