无缝滚动图片效果

  日前,网页专题中经常会出现,无缝滚动的网页效果,这也已经成为广告门户网站的必有效果。先抛开这些不说,分析一下它的效果特征,一组图片反复地滚动而不像之前的marquee,总会有中断的一篇,这个效果从中也弥补了maruqee的bug,因此得到了用户的青睐。

  无缝滚动这一效果分析其本质,即使用了一魔术中的障眼法,比如我想让一组图片向左滚动,则当这组图片的最后一张图片的右边滚动到显示区域的右边时,迅速设置这一组图片的left属性,使之变成0,从而能快速实现紧接着滚出时是第一张图片。同样,如果想让一组图片向右滚动,则当这组图片的第一张图片的左边滚动到显示区域的左边时,迅速设置这一组图片的left属性,使之变成这组图片的1/2位置处。技术要点:

  1.这组图片在滚动之前设置成两组完全相同的html组成;

  2.这组图片的父元素宽度必须足够宽,否则会出现图片折行问题;

  3.滚动的是这组图片的父元素,而不是把每张图片进行设置;

  4.如上所述使用的障眼法;

  5.滚动方向其实就是与速度有关的一个参数;

  6.主要用到元素的offsetWidth,offsetLeft两个属性;

  7.显示图片的区域宽度必须小于所有图片的总宽度。

效果图:

代码:

<!DOCTYPE html>
<html>

	<head>
		<meta charset="utf-8">
		<title>无缝滚动</title>
		<style type="text/css">
			div,
			ul,
			li {
				margin: 0;
				padding: 0;
			}
			#div1 {
				margin: 100px auto 10px;
				width: 720px;
				height: 224px;
				background-color: green;
				position: relative;
				overflow: hidden;
			}
			#div1 ul {
				position: absolute;
				left: 0;
				top: 0;
			}
			#div1 ul li {
				list-style: none;
				float: left;
				cursor: pointer;
			}
			img{
			    height: 224px;
			}
			#div2 {
				text-align: center;
				margin: 0 auto;
			}
		</style>
	</head>

	<body>
		<div id="div1">
			<ul>
				<li>
					<img src="img/1.jpg" />
				</li>
				<li>
					<img src="img/2.jpg" />
				</li>
				<li>
					<img src="img/3.jpg" />
				</li>
				<li>
					<img src="img/4.jpg" />
				</li>
				<li>
					<img src="img/5.jpg" />
				</li>
				<li>
					<img src="img/6.jpg" />
				</li>
				<li>
					<img src="img/7.jpg" />
				</li>
				<li>
					<img src="img/8.jpg" />
				</li>
				<li>
					<img src="img/9.jpg" />
				</li>
				<li>
					<img src="img/10.jpg" />
				</li>
			</ul>
		</div>
		<div id="div2">
			<input type="button" value="←" />
			<input type="button" value="→" />
		</div>
		<script src="../js/jquery-1.11.1.min.js" type="text/javascript" charset="utf-8"></script>
		<script type="text/javascript">
			var oDiv1 = document.getElementById('div1');
			var oUl = oDiv1.children[0];
			var aLi = oUl.children;
			var speed = 2;

			oUl.innerHTML += oUl.innerHTML;
			oUl.style.width = aLi[0].offsetWidth * aLi.length + "px"; //设置ul的宽度,使它能够容纳所有的li,不至于li换行

			var timer = setInterval(move, 30);

			function move() {
				//左滚动:如果ul滚动到其宽度的一半时,调整其左边距为0
				if (oUl.offsetLeft < -oUl.offsetWidth / 2) {
					oUl.style.left = "0";
				}

				//右滚动:如果ul滚动距离左边距大于0时,调整其左边距位置为其宽度的一半
				if (oUl.offsetLeft > 0) {
					oUl.style.left = -oUl.offsetWidth / 2 + "px";
				}

				oUl.style.left = oUl.offsetLeft + speed + "px";
			}

			oDiv1.onmouseover = function() {
				clearInterval(timer);
			};
			oDiv1.onmouseout = function() {
				timer = setInterval(move, 30);
			};

			var oDiv2 = document.getElementById('div2');
			oDiv2.children[0].onclick = function() {
				speed = -Math.abs(speed);
			};

			oDiv2.children[1].onclick = function() {
				speed = Math.abs(speed);
			};
		</script>
	</body>

</html>

  至此,无缝滚动的效果就已完成,大家可以自行调试。

React版本的向上滚动hook

export interface ITimeRef {
  timer: any
  span: number
  mouseEnter: boolean
}
// 滚动
export const useScroll = (timeRef: React.RefObject<ITimeRef>, containerRef: React.RefObject<HTMLDivElement>) => {
  React.useEffect(() => {
    ;(timeRef.current as ITimeRef).timer = setInterval(() => {
      if (containerRef.current) {
        const chilrenDiv = containerRef.current.children[0] as HTMLDivElement
        const pHeight = containerRef.current.offsetHeight
        const cHeight = chilrenDiv.offsetHeight

        if (cHeight - pHeight > 0) {
          if (containerRef.current.children.length < 2) {
            // 克隆一份子节点追加到父节点中
            containerRef.current.appendChild(chilrenDiv.cloneNode(true))
          }

          // 滚动到底部
          const bottom = cHeight * 2 - pHeight
          let span = timeRef.current?.span || 0

          if (!timeRef.current?.mouseEnter) {
            span += 1
            ;(timeRef.current as ITimeRef).span = span
          }
          if (span <= bottom && !timeRef.current?.mouseEnter) {
            if (span > cHeight) {
              span = 0
              ;(timeRef.current as ITimeRef).span = span
            }
            for (let i = 0; i < containerRef.current.children.length; i += 1) {
              const element = containerRef.current.children[i] as HTMLDivElement
              element.style.transform = `translateY(-${span}px)`
            }
          }
        }
      }
    }, 30)

    // eslint-disable-next-line react-hooks/exhaustive-deps
    return () => clearInterval((timeRef.current as ITimeRef).timer)
  }, [containerRef, timeRef])
}

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值