【问题标题】:move image vertically from top to bottom by percentage of scroll按滚动百分比从上到下垂直移动图像
【发布时间】:2021-12-06 18:46:17
【问题描述】:

我正在尝试根据滚动百分比使某个图像从文档顶部移动到其底部,例如,当您加载网站时,该图像将位于页面顶部并且当用户向下滚动它时'将根据整体文档百分比一点一点下降,直到 100% 位于底部。
我在 stackoverflow 和其他网站上经历了很多类似的解决方案,但只有两个似乎接近我需要的解决方案。
第一个有效,但仅适用于在代码中手动调整的一个分辨率:
var imgscroll = document.getElementById('myimg');

window.addEventListener('scroll', function() {
  var scrollposition = window.scrollY;
  imgscroll.style.top = scrollposition * 0.1323 + 'vh';
}

第二个来自 stackoverflow 的答案 - located here and copied below - 我认为百分比部分是我需要的,但无法使其工作(图像停止移动):

var container = document.getElementById('container');
var windowHeight = window.innerHeight;
var windowWidth = window.innerWidth;
var scrollArea = 1000 - windowHeight;
var square1 = document.getElementsByClassName('square')[0];
var square2 = document.getElementsByClassName('square')[1];

// update position of square 1 and square 2 when scroll event fires.
window.addEventListener('scroll', function() {
  var scrollTop = window.pageYOffset || window.scrollTop;
  var scrollPercent = scrollTop/scrollArea || 0;

  square1.style.left = scrollPercent*window.innerWidth + 'px';
  square2.style.left = 800 - scrollPercent*window.innerWidth*0.6 + 'px';
});

对于如何获得答案的任何帮助或提示,我将不胜感激。

【问题讨论】:

  • 叫做“视差滚动”
  • @Dai 我在寻找解决方案时尝试了视差滚动,不幸的是这不是我所需要的,图像需要始终可见,并且每次滚动内容时向下移动一点,图片没有其他变化。
  • 如果视口比图片小怎么办?
  • 性能提示:不要使用阻塞的scroll 事件监听器,而是使用passive 事件:stackoverflow.com/questions/46542428/…,并避免设置position 样式属性。而是使用transform: translateY(...) - 这样效果会非常平滑,因为它不会导致追溯 DOM 更新(阻塞渲染循环)。
  • 图像宽度被限制在vw 单位,因此它会调整(还在其他分辨率上测试了这种调整大小并且图像确实调整了)。我还是新手,所以感谢您的提示,我会确保阅读有关转换方法的信息!

标签: javascript html css scroll responsive


【解决方案1】:

就我个人而言,我发现通过使用animation-play-state: paused 并将CSS 变量分配给animation-delay 来控制图像位置的方法是我在网上看到的最简洁的脚本之一。 Here's the pen 来自 Chris Coyier,它基于。以及他网站上描述该机制的引述:

积极的动画延迟是指动画等待一定时间才能开始。负动画延迟会立即开始动画,就好像这段时间已经过去了一样。换句话说,在动画循环中的某个状态开始动画。

当窗口加载完毕后,我们首先计算图像下方的可用空间和页面溢出量。第一个 CSS 变量--maximum 定义了动画的结束点。当用户调整屏幕大小时会重新计算。然后在滚动的时候,通过另一个CSS变量--epoch来设置进度的比例,这个变量控制关键帧动画的时间。

let aim = document.getElementById('image'), room, overflow;

window.addEventListener('load', setEdge);
window.addEventListener('resize', setEdge);

window.addEventListener('scroll', function() {

  let ratio = (this.pageYOffset || this.scrollY)/overflow;

  aim.style.setProperty('--epoch', ratio);
});

function setEdge() {

  room = window.innerHeight;
  overflow = document.body.scrollHeight-room;

  aim.style.setProperty('--maximum', room-aim.height + 'px');
}
body {
  margin: 0;
  height: 700vh;
}

#image {
position: fixed;
animation-duration: 1s;
animation-timing-function: linear;
animation-play-state: paused;
animation-iteration-count: 1;
animation-fill-mode: both;
animation-name: move;
animation-delay: calc(var(--epoch) * -1s);
}

@-webkit-keyframes move {

0% {
 transform: translateY(0);
}
100% {
 transform: translateY(var(--maximum));
}
}

@keyframes move {

0% {
 transform: translateY(0);
}
100% {
 transform: translateY(var(--maximum));
}
}
<img id="image" src="https://via.placeholder.com/140x100" alt="">

对于那些想玩它的人:https://jsfiddle.net/z2r40y8c/

【讨论】:

  • 谢谢,很好的方法,学到了很多我不熟悉的东西!你能解释一下为什么用animation-delay你乘以-1秒吗?
  • 这只是使数字为负数(根据引用中描述的机制)并遵守正确测量单位的一种方法。我从原始示例中获取它。您也可以在 CSS 中使用 animation-delay: var(--epoch),然后通过 aim.style.setProperty('--epoch', -ratio + 's') 使用 JS 设置值。结果相同。
猜你喜欢
  • 1970-01-01
  • 2011-07-29
  • 2014-09-25
  • 1970-01-01
  • 2020-01-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-11-13
相关资源
最近更新 更多