likes
comments
collection
share

30天JS挑战(第十三天)-----滑动图片滚入

作者站长头像
站长
· 阅读数 3

第十三天挑战(滑动图片滚入)

地址:javascript30.com/

所有内容均上传至gitee,答案不唯一,仅代表本人思路

中文详解:github.com/soyaine/Jav…

该详解是Soyaine及其团队整理编撰的,是对源代码的详解强烈推荐大家观看学习!!!!!!!

本人gitee:gitee.com/thats-all-r…

效果

30天JS挑战(第十三天)-----滑动图片滚入

  • 样式分析

    • 组件整体居中,文本中插入图片
  • 逻辑分析

    • 当滚动条划入到图片范围内时,图片从两侧滑入展示
    • 当滚动条划出图片范围时,图片滑出

本人代码及思路分析

仅提供布局及逻辑代码

结构:

<p>文本内容</p>
<img src="http://unsplash.it/400/401" class="align-right slide-in">

逻辑:

//挑战自带函数,用来限制滚动触发频率
function debounce(func, wait = 20, immediate = true) {
  var timeout;
  return function() {
    var context = this, args = arguments;
    var later = function() {
      timeout = null;
      if (!immediate) func.apply(context, args);
    };
    var callNow = immediate && !timeout;
    clearTimeout(timeout);
    timeout = setTimeout(later, wait);
    if (callNow) func.apply(context, args);
  };
}
//图片展示代码
const img = document.querySelectorAll('img')
function moveActive(){
  img.forEach((item,index) => {
    if(Math.abs(item.offsetTop - document.documentElement.scrollTop)  <= 700 ){
      item.classList.add('active')
    }else {
      item.classList.remove('active')
    }
  })
}
window.addEventListener('scroll',debounce(moveActive))

分析:

  • 整体思路:获取图片元素,监听滑动事件,设定图片显示范围(这里利用的是当滑动距离 - 图片相对于其 offsetParent元素的顶部内边距的距离),根据范围对图片进行展示或隐藏

  • 具体实现:

    • querySelectorAll获取图片元素用来控制图片
    • 通过scrollTop视图顶部到展示窗口的距离,即该页面被滑动的距离
    • 通过offsetTop获取img图片内边距距离其父级元素顶部的距离
    • 让offsetTop - scrollTop ,并取其绝对值,作为图片展示的范围,即当滑动的距离距离图片所在位置差值为X的时候,图片展示,否则隐藏
    • 根据范围展示或隐藏图片
  • 弊端分析(与官方方法对比):

    • 判断不够精确: 这个条件只考虑了图片顶部与视口顶部的距离,没有考虑图片底部的位置。这可能导致一些情况下判断不够精确,例如图片只是部分进入视口时。

官方代码

官方代码仅代表该案例原作者思路,不唯一

结构

<p>文本内容</p>
<img src="http://unsplash.it/400/401" class="align-right slide-in">

逻辑

//节流函数
function debounce(func, wait = 20, immediate = true) {
  var timeout;
  return function() {
    var context = this, args = arguments;
    var later = function() {
      timeout = null;
      if (!immediate) func.apply(context, args);
    };
    var callNow = immediate && !timeout;
    clearTimeout(timeout);
    timeout = setTimeout(later, wait);
    if (callNow) func.apply(context, args);
  };
};
//动效函数
const sliderImages = document.querySelectorAll('.slide-in');

function checkSlide() {
  sliderImages.forEach(sliderImage => {
    // half way through the image
    const slideInAt = (window.scrollY + window.innerHeight) - sliderImage.height / 2;
    // bottom of the image
    const imageBottom = sliderImage.offsetTop + sliderImage.height;
    const isHalfShown = slideInAt > sliderImage.offsetTop;
    const isNotScrolledPast = window.scrollY < imageBottom;
    if (isHalfShown && isNotScrolledPast) {
      sliderImage.classList.add('active');
    } else {
      sliderImage.classList.remove('active');
    }
  });
}

window.addEventListener('scroll', debounce(checkSlide));

分析

仅代表本人对该代码的分析

建议直接去看Soyaine的中文详解

  • **整体思路:**整体思路与上述保持一致,这里添加了图片底部对于视窗底部的判断,更加完善
  • 具体实现:
    • slideInAt:该变量确定滚动视口到达的位置,即视口底部减去图片高度的一半。这样计算是为了确保图片至少在视口的一半以上,从而产生视觉上的渐显效果。
    • imageBottom:这是图片底部距离页面顶部的位置。通过将图片顶部偏移量和图片高度相加,可以得到图片底部的位置。
    • isHalfShown:这个变量检查滚动视口是否超过了图片的顶部位置。如果滚动视口的位置大于图片顶部位置,那么意味着图片至少被滚动了一半以上。
    • isNotScrolledPast:这个变量检查当前滚动的位置是否小于图片底部的位置。如果滚动位置小于图片底部位置,说明图片还没有完全滚出视口。
  • 优点:
    • 性能较好: 代码使用了节流函数 debounce,它可以控制滚动事件的触发频率,避免了过多的计算和页面重绘,提高了性能。
    • 精确控制: 通过计算图片的位置和窗口滚动的距离,精确地判断图片是否已经滚动到了页面的一半,并且没有滚动超过图片的底部,这样可以确保动画效果只在图片完全进入视口时才触发,避免了不必要的动画播放。
    • 灵活性: 代码中使用了变量来保存计算结果,使得后续对滚动条件的调整更加灵活,可以根据实际需要对滚动触发条件进行调整。