猫耳FM日期窗口实现

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

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

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

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

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

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

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

不同档期类型之间在展示效果上并无任何的差别,都是排列在同一行,如何区别不同的档期的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的移动动画

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

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

  1. 一般情况下日期标题的left都与每个档期的第一个元素的left值相等
  2. 只有当档期的一边在左边,还有一边在窗口中(当前档期的第一元素的left < 0,且下一个档期的第一元素的left值 > 0),则标题位置为 left = 0
  3. 标题的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: 模型的实现方法多样,上述方法仅供参考,希望大家能多尝试其他方法。

猫耳FM日期窗口实现相关推荐

  1. 猫耳FM轮播图模型制作

    猫耳FM轮播图模型制作 今天咱们来研究一下猫耳FM的轮播图,它的轮播效果和往常的有些不同.先来看看它的效果~ 可以看到它的切换效果的特别之处---相隔多个图片之间的切换时,当前图片到目标图片的切换是直 ...

  2. “Z世代”崛起,网易云信助力猫耳FM引领声音风潮

    2018年,Z世代以一种毋庸置疑的姿态闪亮登场,接棒互联网娱乐消费主力人群.作为移动互联网的"原住民", Z世代自出生之时就已经处在高度互联网化的时代.而高度自由的互联网环境为他们 ...

  3. 猫耳FM导出音频转换为音频格式(m4a/mp3)

    目录 旧方法(不可用) 新方法 提示:仅为个人学习使用,不得用于任何商业用途 旧方法(不可用) 找到文件:打开文件管理-内部储存-MaoerFM-Download-sound_blob 将下载的文件后 ...

  4. 猫耳FM音频转换成MP3格式

    原创文|Space9 猫耳FM音频与普通音频的差异 首先我们发现猫耳FM音频是没有后缀名的音频文件,然后我们通过对比发现猫耳FM音频文件并不是什么加密文件,只是将音频文件.封面图片.弹幕文件合并到了一 ...

  5. 智能车竞赛技术报告 | 智能车视觉 - 上海大学 - 猫耳麻花

    简 介: 本文设计的智能车系统以NXP RT1064微控制器为核心控制单元,通过车体前方的摄像头检测赛道信息:通过齿轮编码器检测模型车的实时速度,使用PID 控制算法调节驱动左右电机的转速,PD算法控 ...

  6. 猫耳荔枝等平台api汇总

    收集各个ASMR音视频平台,利用api进行网站的内容更新. 猫耳 搜索: https://www.missevan.com/dramaapi/search?s=关键字&page=1 助眠分类搜 ...

  7. 猫耳语音下载(missevandown)

    猫耳语音下载(missevandown) 一.介绍 猫耳语音下载,能够帮助你下载猫耳音频节目.如果你是会员,它还能帮你下载会员节目. 二.下载地址 下载:猫耳语音下载(missevandown) 百度 ...

  8. 3D模型欣赏:猫耳少女 唯美 可爱

    作者YUNJIA MA的作品,猫耳少女,唯美,可爱. 或许你还想了解这些内容: 文章推荐阅读 [ 学习企鹅圈:1072172722 ] : 3D游戏建模前景如何?是做什么的?大牛分享月薪2万教程工具笔 ...

  9. 萌萌哒意念猫耳创始人Tomonori Kagaya:物对人的体谅才是未来

    因"萌萌哒意念猫耳朵"这款产品而出名的日本neurowear公司创始人Tomonori Kagaya,将于11月8日在腾讯WE大会上发表演讲.这家公司专注于"意念&quo ...

最新文章

  1. My blog please navigate to http://hi.baidu.com/248828412
  2. 【278】◀▶ Python 数学函数说明
  3. AngularJS基本知识点
  4. linux开放2280端口,威联通推出适用于NAS/PC的双端口 M.2 2280 PCIe NVMe SSD含双端口2.5GbE扩展卡...
  5. Dubbo 一篇文章就够了:Dubbo遇到初恋
  6. 十二月份找工作好找吗_注会过两门好找工作吗?好找
  7. windows之如何刷新电脑DNS缓存
  8. coroutine php_PHP 协程实现
  9. PHP过滤常用标签的正则表达式
  10. 机器视觉:远心光学探秘
  11. ig 焊接机器人_发那科机器人焊接应用的IO配置(总线型)
  12. 【语音去噪】基于matlab低通+自适应滤波去噪【含Matlab源码 352期】
  13. 华为2019届校招笔试题及解法
  14. 如何快速比对表格数据
  15. ValueError: n_splits=4 cannot be greater than the number of members in each class
  16. 版号解禁,网络游戏却未解冻
  17. python16进制表示0xad_在 Python 中 0xad 是合法的十六进制数字表示形式。 (2.0分)_学小易找答案...
  18. 电路板参数有哪些参数
  19. 五大常用算法——回溯算法详解及经典例题
  20. 【HTTP-FLV播放】CicadaPlayer拉流:ffmpeg计算pkt duration

热门文章

  1. zpl指令打印中文内容_大疆机甲大师Python开发: 中文命名变量初尝试
  2. 个人身份认证接口介绍
  3. python arp协议分析_通过python对本局域网进行ARP扫描获取MAC
  4. 已经开源的阿里云播放器的播放内核
  5. 函数模板案例—选择排序
  6. 微信授权绑定手机号 java_微信小程序获取手机号授权用户登录功能
  7. c语言嵌入式开发键盘,C语言嵌入式系统编程修炼之键盘操作篇
  8. Linux笔记本电脑大调查:程序员最喜欢的电脑是什么配置?
  9. 使用Rosetta批量生成fasta
  10. 剑指offer | 面试题54:二叉搜索树的第k大节点