不知各位遇到特别长的图片时是怎么处理的?
是 截取符合长宽的部分做临时展示?
还是 硬要长宽100%模糊(啥也看不清)展示?
还是 先拿一个压缩的图片做占位,在鼠标移入或点击时放大预览?

今天偶然打开PC端QQ空间时,我发现了一种似乎更好的方式 —— 鼠标移入时在范围内上下滚动图片预览,移出时停止滚动。直到用户点击图片跳转到详情展示:


分析

这种方式着实让我“眼前一亮”,一定程度上带给了用户新奇的体验感。顺着思路,一键 f12 打开源码,我看到了这样的代码:


显而易见,QQ应该是采用了js监听鼠标位置的做法,动态改变 img 标签中自定义属性的值,并根据此去改变图片的 margin-top 值,用 transition 属性去制造动画效果。


模拟实现

为了方便些,这里笔者采用两个空标签分割“包裹图片的元素”,然后分别在上面监听鼠标事件的做法,实现效果如下:

首先,“科普”几个API,它们将会是你的助力:

  1. image.naturalHeight :看到前面的image没?这是用来获取图片原始高度的(同系的还有 image.naturalWidth ,你可以用它来确定包裹元素的最大/最小宽度);
  2. dom.offsetTop :offset系的API,用来获取dom元素和离它最近的父元素顶部的距离(同系的还有 offsetLeftoffsetWidth/offsetHeight (返回元素的像素宽高,包含该元素的内边距和边框,是一个整数且不包含:before或:after等伪类元素的宽高)、offsetParent (获取父元素));
  3. dom.getBoundingClientRect() :它有四个常用值:left、top、right、bottom,分别是相对于当前视口(即此tab网页窗口左侧、顶部、右侧、底部)的位置;
  4. dom.scrollHeight :scroll系的API,用来获取元素的真实高度(同系的还有scrollWidth/scrollLeft/scrollTop ),一般不会用它来作用于图片上,因为它必须等元素加载出来才能确定;
  5. window.innerHeight :inner系的API,它们只作用在window对象上,返回窗口的文档显示区的高度(同系的还有一个 window.innerWidth ) <-> 相对的两个 outerWidthouterHeight ,用于获取加上工具条与滚动条窗口的宽度与高度;

顺便说一句,像 img.getBoundingClientRect().topimg.offsetTop 这些都是 只读 值,所以不要妄想用它们来改变元素位置!

布局如下:

<div class="box"><i class="before"></i><img src="img/nan.png" class="img" /><i class="after"></i>
</div>

这里class为before和after的两个标签就是前面所说的“占位”元素(至于QQ是怎么实现的,等笔者稍作研究后再回来更新),它们负责判断“图片是应该向上滑还是向下滑”!

本来这里笔者想采用伪元素的方式:用 ::before::after 占位并触发事件,但是在查遍资料以后我突然想到一件事:不是经常说伪元素的优势是脱离文档流吗?那还如何能够获取到?
唉,大意了,,,

html,body{margin: 0;padding: 0;
}.box{width: 400px;height: 200px;overflow: hidden;position: relative;
}
.lang::after{content: "长图";position: absolute;right: 0;bottom: 0;padding: 2px 3px;background-color: rgba(0,0,0,.36);color: white;
}
i{position: absolute;width: 100%;height: 50%;left: 0;
}
i.before{top: 0;
}
i.after{bottom: 0;
}
.img{margin-top: 0;transition: all 2s linear;
}

对img元素设置一个初始的margin-top,就是为了配合下面的transition使得在js中改变top值时能够有动画效果!

有了上面的布局方式和API解读,其实js实现就非常简单了 —— 根据上面分析的按部就班来就行:

let box=document.querySelector('.box');
let img=document.querySelector('.img');
let i_before=document.querySelector('i.before');
let i_after=document.querySelector('i.after');
let box_height=box.offsetHeight;
let img_height=img.naturalHeight;
// 只有图片高度大于盒子高度时才有下面的事件
if(img_height>box_height){console.log(1)box.classList.add('lang');let img_top=0;// 鼠标移入下半部分时图片向下滑动i_after.addEventListener('mouseenter',(e)=>{console.log(img.offsetTop)img.style.marginTop=-(img_height-box_height)+'px';},false)i_after.addEventListener('mouseout',(e)=>{console.log(img.offsetTop)img_top=img.offsetTop;img.style.marginTop=img.offsetTop+'px';},false)// 鼠标移入上半部分时图片向上滑动i_before.addEventListener('mouseenter',(e)=>{if(img_top){img.style.marginTop=0;}},false)i_before.addEventListener('mouseout',(e)=>{if(img_top){img.style.marginTop=img.offsetTop+'px';}},false)
}

至此,效果就全部实现了。
但是如果你仔细看,你会发现由于transition动画效果的时间是固定的,在向上/下滑动过短的情况下再向下/上滑动那么滑动的会特别慢!

!当然,我们可以改变策略,让图片的 margin-top 不断--++ 直到临界值,但这样势必会带来巨大的性能开销。

再回到PC端QQ空间 —— 我们发现,它的transition时间竟然是动态变化的:

这…我猜测可能是设定了一个从上到下固定的时间,然后在JS中按照滑出部分高度(已经滑动的距离)占总高度的比例动态调节时间。。。相关代码笔者正在尝试ing


当然,本文对QQ前端团队对图片的处理来说也许只是沧海一粟,,,更多的还有比如:根据图片整体平均色差调整说明文字的颜色黑/白(canvas-getImageData API)、图片内容的延迟展示、多图上传性能调优(promise API)等等。

那咱就 再见了?

QQ空间对图片的处理之仿QQ长图预览相关推荐

  1. java仿qq空间音乐播放_完美实现仿QQ空间评论回复特效

    评论回复是个很常见的东西,但是各大网站实现的方式却不尽相同.大体上有两种方式 1. 像优酷这种最常见,在输入框中@要回复的人,这种方式下,用www.cppcns.com户可以修改@. 新浪微博则是在这 ...

  2. qq空间的相册名称java_jsp实现仿QQ空间新建多个相册名称并向相册中添加照片功能...

    工具:Eclipse,Oracle,smartupload.jar:语言:jsp,Java:数据存储:Oracle. 实现功能介绍: 主要是新建相册,可以建多个相册,在相册中添加多张照片,删除照片,删 ...

  3. qq空间的相册名称java_jsp实现仿QQ空间新建多个相册名称,向相册中添加照片

    public class UpDAOImpl implementsUpDAO {/*(non-Javadoc) * @see cn.jvsun.DAO.UpDAO#creAlbum(cn.jvsun. ...

  4. qq相册传照片显示服务器,为什么上传到QQ空间的高清照片,时间一长就变得模糊了?...

    原标题:为什么上传到QQ空间的高清照片,时间一长就变得模糊了? 如今的一些年轻人最喜欢玩的社交软件主要是QQ和微信,实用的功能和口碑使得它们在五花八门的软件中一直成为大家的宠儿,但随着网络科技的不断发 ...

  5. android qq空间效果,更新UI设计 Android手机QQ空间1.2详测

    近日,腾讯发布了Android手机QQ空间1.2版.经过一周的试用,小编认为该版QQ空间的多项创新,大大地发挥了Android平台的价值. 从测试结果来看,Android手机QQ空间1.2版在原有便捷 ...

  6. python爬取网页版QQ空间,生成词云图、柱状图、折线图(附源码)

    python爬取网页版QQ空间,生成词云图.柱状图.折线图 最近python课程学完了,琢磨着用python点什么东西,经过一番搜索,盯上了QQ空间,拿走不谢,欢迎点赞收藏,记得github给个sta ...

  7. Android高仿微信照片选择器+预览+显示照片

    转载请说明出处: http://blog.csdn.net/lyhhj/article/details/49046109 前阵子写过一片博客,是关于选择多图上传的一个小demo,那个demo是从网上找 ...

  8. android 酷狗demo_Android仿酷狗皮肤预览界面的实现(利用canvas缩放的原理)

    GitHub_ AnJiaoDe/Scale-Master APKdemo_ AnJiaoDe/Scale-Master/blob/master/app/build/outputs/apk/app-d ...

  9. 小程序 图片上传php后台,微信小程序图片选择、上传到服务器、预览(PHP)实现实例...

    微信小程序图片选择.上传到服务器.预览(php)实现实例 小程序实现选择图片.预览图片.上传到开发者服务器上 后台使用的tp3.2 图片上传 请求时候的header参考时可以去掉(个人后台验证权限使用 ...

最新文章

  1. css 中文字旋转,css
  2. 微信支付-我遇到的那些问题
  3. 听说,他用报表关联数据库表,运维效率提升70%?
  4. 一起学习C语言:初谈指针(二)
  5. 28muduo_net库源码分析(四)
  6. debian查询端口进程_Linux入门-端口和进程号
  7. R语言meta包的预后meta分析复现
  8. nbu备份脚本 linux,NBU60网络备份大全之Linux设备管理(参考Word)
  9. ”在禁用UAC时,无法激活此应用“问题
  10. 定时器触发STM32 ADC的采样转换示例
  11. 磁盘阵列RAID卡组建设置
  12. linux 模拟usb键盘,在Linux下模拟键盘按键
  13. 手把手教你搭建免流服务器(只限于联通)
  14. 折腾:如何让你的老电脑快起来
  15. 魅族手机便签的备忘录内容误删了怎么办?
  16. Vue学习笔记(六)--- 前端路由 Vue Router
  17. mac上启动nginx遇到80端口被占用的解决方法(猜了好久的坑我擦)
  18. 开心消消乐在屏幕中向下移动的完整代码
  19. 如何切换不同的python环境
  20. 磁盘处于脱机状态解决办法

热门文章

  1. ipmitool常用命令详解
  2. 【机器学习】什么是决策树模型?如何去构建决策树?何时使用决策树?何时使用神经网络?
  3. PTA C语言找不同
  4. entityManager.createNativeQuery查询返回实体或vo及提示setResultTransformer过时处理
  5. mysql 两个查询合并_mysql – 合并这两个查询
  6. 快手信息流广告怎么投放?奢侈品可以在快手推广广告吗
  7. Ubuntu系统安装sougou输入法
  8. 创造与魔法java语言_创造与魔法战宠技能详解 战宠技能汇总
  9. Nginx rewrite 规则详解
  10. 被不良商家欺骗怎么投诉,启中教育有办法