• Update 2016.12.7
  • 已封装为插件

    • 原生 js 插件$ npm install foldcontent-zhihu@">=3.0.12" --save Usage
    • jquery 插件 $ npm install foldcontent-zhihu-jquery@">=1.0.1" --save Usage

  • Update 2016.11.23
  • 此前demo 定义两个按钮,一个固定定位,一个绝对定位,因此滚动至底部时会出现两个按钮同时出现的问题,用户体验不是很好,因此更改为只有一个按钮,判断滚动至底部时添加 classname 更改样式。且精简了代码ヾ(≧∇≦*)ゝ
  • scroll 事件性能优化问题。

    • 鼠标滚动时 scroll 事件触发的间隔大约为 10~20 ms,相对于其他的鼠标、键盘事件,它被触发的频率很高,间隔很近。因此如果 scroll 事件涉及大量的位置计算、元素重绘等工作,且这些工作无法在下个 scroll 事件触发前完成,就会导致浏览器掉帧
    • 因此需要减少绑定给 scroll 中具体想要执行的业务逻辑的执行次数
    • 并将对象初始化、不变的高度值等缓存在 scroll 事件外部
    • 存在 bug : 当以很快的速度滚动时,有可能执行不到 scroll 绑定的事件(ó﹏ò),有没得更好的优化方案?
  • 示例代码及 github 均已更新 ٩(ˊᗜˋ*)و

  • Update 2016.11.22
  • 优化代码结构,存在命名不规范、jquery 方法和原生 js 方法混用、代码未封装、设计冗余等问题。。。review 代码被批了。。。

没有需求的话……就自己提一个 ୧(๑•̀⌄•́๑)૭

  • 起初是要做一个公司内部的 mongoDB 日志查询网站,前端用 bootstrap,后端用 nodejs 做了一个简单的页面,不得不说页面还是很粗陋的,因为一条日志的内容很多,如果直接显示的话内容太过冗长,往往滚动几次才能看完一条日志,而且经常查询的就是固定的几个 key,直接展示不利于迅速debug。
  • 问题确定了,要实现的就是显示日志时只显示经常查询的几个键值对,点击展开时显示全部日志,点击收起时变回原状。
  • 需求很简单,而且和知乎的显示全部&&收起功能非常相似,但是 Google 了一下没有找到类似的 demo,因此决定自己实现一个!

Here we go

  • 看了知乎的网页代码。原理是点击显示全部时,如果这条答案超出浏览器视窗,则收起按钮变成固定定位,js 计算出 right 值,bottom固定为12px;当这条答案底部滚动至浏览器视窗内,收起按钮变回绝对定位。ps 发现知乎是不是改版了,之前答案底部出现在浏览器视窗内后这个位置是有收起按钮的?,按钮从固定定位变为绝对定位并更改样式,就像旁边的作者保留权利这样的风格~(图一直传不上来。。暂时放弃了)
  • 现在的做法是直接隐藏掉固定定位的收起按钮。

  • 其实我的实现方法和知乎的不甚相同,因为他的 js 代码我真心……没看懂!谁能告诉我这种情况应该怎么调试(ノ°ο°)ノ

  • 所以想了另一种思路,在答案右下角定义一个按钮 A,判断答案顶部和底部的相对位置 x 和 y ,其中 y = x + 答案的高度(js 获取)。当答案出现在浏览器视窗内,即 x = $(window).height() 时,给 A 添加固定定位,动态定义 right 值;当答案即将滚出浏览器视窗,即 y = $(window).height() 时,A 变为相对定位,right 值始终为 20px。当 A 的文本内容为收起时,点击 A 文本内容变为展开,去掉固定定位。
  • 此处省去连接数据库等无关工作,仅用两段有趣的文字作为 demo ~
  • 首先,文字内容分为 all-content 和 part-content 两部分,分别为折叠前和折叠后要展示的内容,因为还未搞懂知乎折叠答案后显示哪一部分内容的算法,所以简单粗暴地分了折叠前和折叠后的内容。。此处有一个 TODO ?
<ul class="wrap"><li><div class="content all-content" style="display: none;"><h2>Sheldon 座位理论</h2><p>In the winter that seat is close enough to the radiator to remain warm and yet not so close as to cause perspiration. In the summer it's directly in the path of a cross breeze created by opening windows there, and there. It faces the television at an angle that is neither direct, thus discouraging conversation, nor so far wide to create a parallax distortion. I could go on,but ... I think I've made my point.</p><p>冬季的时候,这个地方离电暖器很近、最暖和,但是又不会近到让你感觉热、流汗;夏天的时候,这里又可以吹由那两扇窗户吹进来的徐徐微风;坐这的角度可以让我同时看电视又同时和他人聊天而不受影响,恰好不会太远也不会产生视觉上的错觉。</p><p>That is my spot. In an ever-changing world it is a simple point of consistency.If my life were expressed as a function in a four-dimensional Cartesian coordinate system,that spot, at the moment I first sat on it, would be 0000.</p><p>那是我的专座。在这个不断变化的世界里,这是不变的一点。假设我的生命用一个建立在四维直角坐标系里的方程来表示的话,这个座位从我坐上那一刻开始就成为了(0,0,0,0)。</p></div><div class="content part-content">In the winter that seat is close enough to the radiator to remain warm and yet not so close as to cause perspiration. In the summer<b> ...</b></div><div class="sign unfold">展开</div></li>
</ul>
var doc = $(document);
var win = $(window);
// 多次使用, 缓存起来
doc.on('click', '.unfold', function () {var unfold = $(this);if (unfold.text() !== '收起') {unfold.text('收起').siblings('.part-content').hide().siblings('.all-content').show();var panel = unfold.parent();var panelScroll = panel.offset().top + panel.height();var scrollHeight = doc.scrollTop() + win.height();var right = win.width() / 2 - 350 + 20 > 20 ? win.width() / 2 - 350 + 20 : 20;// 点击展开按钮时即判断是否出现收起按钮if (scrollHeight - panelScroll < 50) {unfold.addClass('fold-fix').css('right', right);}// 绑定在 scroll 事件上var cb = {onscroll: function() {var panelScroll = panel.offset().top + panel.height();var scrollHeight = doc.scrollTop() + win.height();var right = win.width() / 2 - 350 + 20 > 0 ? win.width() / 2 - 350 + 20 : 20;if (scrollHeight - panelScroll < 50 &&panel.offset().top - scrollHeight < -90 && unfold.text() !== '展开') {unfold.addClass('fold-fix').css('right', right);} else {changeStyle(unfold);}win.off("scroll", cb.onscroll);setTimeout(function() {win.on("scroll", cb.onscroll);}, 50);}};win.on("scroll", cb.onscroll);} else {var fold = $(this);changeStyle(fold);fold.text('展开').siblings('.part-content').show().siblings('.all-content').hide();}
});function changeStyle(i) {i.removeClass('fold-fix').css('right', '20px');
}
  • 此处涉及一个知识点:网页元素的绝对位置 && 相对位置

    • 网页元素的绝对位置,指该元素的左上角相对于整张网页左上角的坐标。jquery 中 offset() 方法返回元素相对于文档的偏移。该方法返回的对象包含两个整型属性:top 和 left。x.offset().top 即为 x 元素的绝对高度;
    • 网页元素的相对位置,指该元素左上角相对于浏览器窗口左上角的坐标。绝对位置减去页面的滚动条滚动的距离就是相对位置。x.offset().top - $(document).scrollTop() 即为 x 元素的相对高度。
    • 本例需要浏览器视窗刚刚滚动至答案a的绝对定位按钮出现的效果,因此此节点为答案底部的相对高度减去浏览器视窗高度正好等于负的按钮 A 的高度。即 a.offset().top + a.height() - $(document).scrollTop() - $(window).height() = - 按钮高度
    • 阮一峰老师的用Javascript获取页面元素的位置这篇文章讲解得十分清晰,如果要深入了解这个知识点建议看一下这篇文章,说不定就有茅塞顿开的感觉哦 ٩(ˊᗜˋ*)و
  • 如何动态设置固定定位的折叠按钮 的 right 值呢?

    • 答案的固定宽度是 700px,因此浏览器视窗宽度减去 700px 再除以 2 便始终是答案的 right 值,因为按钮为绝对定位时 right: 20px; 因此 right: $(window).width()/2 - 350 + 20 就保证了固定定位和绝对定位时按钮都在一条垂直线上,过渡衔接很自然。
    • 当浏览器窗口不断缩小时,上面计算出的固定定位时按钮的 right 值可能为负,这显然不符合需求,因此要设置当计算出的 right 值为负时设置 right 值为 20px。

catch the code

  • 源代码已上传至 my github (ㆆᴗㆆ) ?

用原生 js jquery 实现知乎收起答案功能相关推荐

  1. 【每日一练】原生js仿淘宝主图放大镜功能,附学习源码

    在我们的项目中,经常会遇到各种功能效果的实现,对于每一项功能的实现方式,都有很多种,这些实现方式没有好坏之分,只有适合与否,但是我个人建议,如果项目急就选择自己擅长的方式实现,比较完成工作更加重要嘛. ...

  2. dw按钮图片滚动js_轮播图--swiper插件/原生js/jQuery

    1.swiper插件: 需要下载该插件到本地,并用link标签引用其swiper-bundle.min.css文件,用script引用其swiper-bundle.min.js文件,下载地址及官方文档 ...

  3. 瀑布流布局(原生js,jQuery实现)

    项目地址: 瀑布流布局实战 阅读人群: 懂html,css,js,jquery的coder 阅读时间: 60minutes 1. 瀑布流式布局简介 什么是瀑布流布局 一种网站页面布局,视觉表现为参差不 ...

  4. 原生js实现ajax的文件异步提交功能、图片预览功能.实例

    采用html5使得选择图片改变时,预览框中图片随之改变.input文件选择框美化.原生js完成文件异步提交 效果图: 代码如下,可直接复制并保存为html文件打开查看效果 <html> & ...

  5. 原生js实现table表格的各行变色功能

    <!DOCTYPE html> <html lang="en"> <head><meta charset="UTF-8" ...

  6. 原生js实现table 横向纵向全选功能

    要实现这种功能,很明显用elment ui实现不了.element ui 纵向需要prop名字不一样才能展示,很明显,我这个一层二层是名字一样的数组 期望后台返回数组 是这种格式. 所有需要自己用ta ...

  7. 表格设置翻页 html,使用原生JS实现表格数据的翻页功能

    使用原生JS实现如下图所示表格数据的翻页功能: HTML代码: 表格标题 < > 简单处理一下样式,CSS代码: #pagination { text-align: center; } # ...

  8. html制作日历备忘录,原生JS代码制作带记事备忘功能的双月份显示效果的日历

    原生JS写的日历月历 - demo by js.alixixi.com window.onload = function(){ function $(id){return typeof id === ...

  9. html5实现下拉刷新页面,原生js实现简单的下拉刷新功能

    前言: 我们在浏览移动端web页面的时候,经常会用到下拉刷新. 现在我们用原生的js实现这个非常简单的下拉刷新功能. (温馨提示:本文比较基础,功能也很简单.写的不好的地方,希望大神提点一二.) 一. ...

最新文章

  1. 深度学习中的卷积网络简介
  2. WebView + jQuery
  3. 深度报告:芯片设计EDA 2.0时代,三大路径搞定六大挑战
  4. 分享:Gunicorn 0.17 发布,Python HTTP 服务器
  5. 【Linux】Linux添加系统调用以及内核编译过程
  6. 【dart学习】-- Dart之函数
  7. Selenium爬携程酒店评论+jieba数据分析实战
  8. 博客美化20150418
  9. python列表批量 修改_python实现多进程按序号批量修改文件名的方法示例
  10. 单一课和综合课的划分依据_缠论108课第105课:股票的操作中远离小聪明,保持机械性的操作...
  11. 微信公众号扫码登录(一)—— 获取微信公众号二维码
  12. mysql查看有哪些函数_MySQL函数一览_MySQL函数全部汇总
  13. Linux之flash流媒体服务器red5安装
  14. 通过TCP网络协议实现控制台多人聊天功能,另附私聊@功能。(java)
  15. D-Tale,实现Pandas GUI高效数据分析
  16. 如何从零创造一个围棋AI
  17. 生成100个p元素,隔行变色(红、黄、蓝、绿、紫)
  18. 专访Cisco 梁永健:网络会议撬动SaaS市场
  19. c语言五子棋游戏心得体会,下五子棋执白子之心得
  20. python书籍排行榜2020_2020年Python文章盘点,我选出了个人TOP10

热门文章

  1. ii7+php5.5+phpMyAdmin-4.1.0
  2. 使用golang的for打印三角形
  3. 通过JavaScript简单的操作DOM(一)
  4. dubbo学习之-常用功能
  5. Oracle创建表管理表
  6. JavaScript作用域学习笔记
  7. 数据库范式(1NF、2NF、3NF、BCNF)
  8. webkit qt版快速编译 支持wml版本
  9. 紫书 习题7-14 UVa 307(暴搜+剪枝)
  10. Lucene核心数据结构——FST存词典,跳表存倒排或者roarning bitmap 见另外一个文章...