如何制作HTML5旋转列表/转轮选择器/选择器

How to make a HTML5 spinning list/rotating wheel selector/picker

本文关键字:选择器 列表 何制作 HTML5 旋转      更新时间:2023-09-26

我的问题是关于用户ByteHamster在这里给出的答案:如何创建带有图像的JavaScript/HTML5旋转列表?在回答中,他/她给出了一个如何用html, css和Javascript创建滚动动画的例子。该动画允许用户通过单击屏幕上所选数字的上方或下方来滚动数字,所选数字将显示在动画下方的div中。

我想知道是否有可能做类似的事情,而不是有一个图像上下移动,它可以变成一个数字轮?我的意思是,在上面的例子中,当数字达到0时,滚动停止在一个方向上,我想知道是否可以创建一个轮子,用户可以不断地从上到下旋转它,或者从下到上,如果他们想这样做的话。这是否需要使用3d交互式动画软件?

我看到这个问题:HTML5/CSS3 -如何使"无尽"旋转背景- 360度全景,但我不确定答案是否适用于我的项目,因为他们似乎没有互动。

作为用户ByteHamster的答案是超过3岁,我想知道是否有更好的方法来实现这种效果与html5动画?我是否正确地认为,在例子中的Javascript会使它不能在一些设备/浏览器上工作,没有启用Javascript ?html5方法是确保效果适用于大多数设备/浏览器的最佳方法吗?

这是我从提供的信息中整理出来的…与鼠标滚轮一起工作,在顶部和底部数字上滑动和点击。当然是无限的。没有特别的透视风格(还没有),但我认为它看起来相当体面。当然也可能是一种选择。没有使用我在评论或requestAnimationFrame链接的插件,但jQuery animate()是一个很好的工具。该库具有出色的跨浏览器支持(这实际上是它的优势),它所需要的只是一个链接,以便JavaScript能够执行。你可以使用CDN,这个版本也适用于IE8-:

<script src="//cdnjs.cloudflare.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>

为了在使用鼠标滚轮时获得最佳的跨浏览器支持,包含了这个插件:

<script src="//cdnjs.cloudflare.com/ajax/libs/jquery-mousewheel/3.1.12/jquery.mousewheel.js"></script>
https://plugins.jquery.com/mousewheel/

只是一个基本的父元素和样式,每个数字都有跨度,如果向上,则提前几个。

$(function() {
var gate = $(window),
cog = $('#rotator'),
digit = cog.find('span'),
field = $('#result'),
slot = digit.height(),
base = 1.5*slot,
up, swipe;
if (document.readyState == 'complete') interAction();
else gate.one('load', interAction);
function interAction() {
	field.text(0);
	cog.scrollTop(base).fadeTo(0,1).mousewheel(function(turn, delta) {
		if (isBusy()) return false;
		up = delta > 0;
		nextNumber();
		return false;
	});
	digit.on('touchstart', function(e) {
		var begin = e.originalEvent.touches[0].pageY;
		digit.on('touchmove', function(e) {
			var yaw = e.originalEvent.touches[0].pageY-begin;
			up = yaw < 0;
			swipe = Math.abs(yaw) > 30;
		});
		gate.one('touchend', function() {
			digit.off('touchmove');
			if (swipe && !isBusy()) nextNumber();
		});
	})
	.on('mousedown touchstart', function(e) {
		if (e.which && e.which != 1) return;
		var zest = this, item = $(this).index();
		$(this).one('mouseup touchend', function(e) {
			digit.off('mouseup');
			var quit = e.originalEvent.changedTouches;
			if (quit) var jab = document.elementFromPoint(quit[0].clientX, quit[0].clientY);
			if (swipe || item == 2 || quit && jab != zest || isBusy()) return;
			up = item == 1;
			nextNumber();
		});
		return false;
	})
	.mouseleave(function() {
		digit.off('mouseup');
	});
}
function isBusy() {
	return cog.is(':animated');
}
function nextNumber() {
	var aim = base;
	swipe = false;
	up ? aim += slot : aim -= slot;
	cog.animate({scrollTop: aim}, 250, function() {
		up ? digit.eq(0).appendTo(cog) : digit.eq(9).prependTo(cog);
		digit = cog.find('span');
		cog.scrollTop(base);
		field.text(digit.eq(2).text());
	});
}
});
body {
  background: grey;
}
#ticker {
  width: 150px;
  text-align: center;
  margin: auto;
}
#rotator {
  height: 140px;
  font-family: "Times New Roman";
  font-size: 50px;
  line-height: 70px;
  background-image:
  url(http://ataredo.com/external/image/flip.png),
  url(http://ataredo.com/external/image/flip.png),
  url(http://ataredo.com/external/image/flip.png);
  background-position: 0 0, 50% 50%, 100% 150%;
  background-size: 300% 50%;
  background-repeat: no-repeat;
  margin: 0 0 10px;
  overflow: hidden;
  opacity: 0;
}
#rotator span {
  width: 100%;
  height: 50%;
  display: inline-block;
  cursor: default;
  -webkit-tap-highlight-color: rgba(0,0,0,0);
  -webkit-tap-highlight-color: transparent;
}
#result {
  height: 30px;
  font-size: 20px;
  color: white;
  line-height: 30px;
  letter-spacing: 3px;
  -webkit-box-shadow: 0 0 3px black;
  box-shadow: 0 0 3px black;
}
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/jquery-mousewheel/3.1.12/jquery.mousewheel.js"></script>
<div id="ticker">
 <div id="rotator">
   <span>8</span>
   <span>9</span>
   <span>0</span>
   <span>1</span>
   <span>2</span>
   <span>3</span>
   <span>4</span>
   <span>5</span>
   <span>6</span>
   <span>7</span>
 </div>
 <div id="result"></div>
</div>

非常简单,使滚动位置向上或向下移动,然后根据方向追加或追加第一个或最后一个数字。动画的持续时间可以在这里设置:

cog.animate({scrollTop: current}, 250, function() {

更新-有了一些新的见解后,例如touchend事件总是在原始元素上发射,我已经彻底检查了代码。除此之外,它现在有一个精灵背景,将保持与数字本身的大小成比例。还改进了整体逻辑,并删除了嵌套侦听器故障。

进行此编辑的另一个原因是插入一个允许拥有多个报价器(并预设数字)的演示。由于我甚至已经超越了这一点(添加直接响应功能),我认为在这里留下最小的工作代码也是一个好主意:

$(function() {
var gate = $(window),
orb = document,
cog = $('.rotator'),
field = $('#result'),
slot = cog.height()/2,
base = 1.5*slot,
list = [],
niche = [7,7,7],
term = 250, // duration of animation
mass, up = true,
yaw = 'mousemove.ambit touchmove.ambit',
hike = 'mouseup.turf touchend.turf',
part = 'mouseleave.range';
tallyCells();
if (orb.readyState == 'complete') interAction();
else gate.one('load', interAction);
gate.on('mouseleave touchcancel', function(e) {
	!(e.type == 'mouseleave' && e.relatedTarget) && lotRelease();
});
function interAction() {
cog.scrollTop(base).each(function(unit) {
	var pinion = $(this),
	digit = pinion.find('.quota'),
	cipher = Number(niche[unit])%10 || 0;
	list[unit] = digit;
	niche[unit] = 0;
	field.append(0);
	for (var i = 0; i < cipher; i++) nextNumber(pinion, unit, true);
	pinion.mousewheel(function(turn, delta) {
		if (isBusy(pinion)) return false;
		up = delta > 0;
		nextNumber(pinion, unit);
		return false;
	});
	digit.on('mousedown touchstart', function(e) {
		if (e.which && e.which != 1) return;
		var zest = this, ken = {}, item = $(this).index();
		tagPoints(e, ken);
		digit.on(part, wipeSlate).on(hike, function(e) {
			wipeSlate();
			var quit = e.originalEvent.changedTouches;
			if (quit) var jab = orb.elementFromPoint(quit[0].clientX, quit[0].clientY);
			if (item == 2 || quit && jab != zest || isBusy(pinion)) return;
			up = item == 1;
			nextNumber(pinion, unit);
		});
		gate.on(yaw, function(e) {
			hubTrace(e, ken);
		})
		.on(hike, function() {
			lotRelease();
			if (!ken.hit || isBusy(pinion)) return;
			up = ken.way < 0;
			nextNumber(pinion, unit);
		});
		return false;
	});
}).fadeTo(0,1);
function tagPoints(act, bit) {
	var nod = act.originalEvent.touches;
	bit.mark = nod ? nod[0].pageY : act.pageY;
	bit.veer = false;
}
function hubTrace(task, gob) {
	var peg = task.originalEvent.touches,
	fly = peg ? peg[0].pageY : task.pageY;
	gob.way = fly-gob.mark;
	gob.hit = Math.abs(gob.way) > 30;
	if (!gob.veer && gob.hit) {
	gob.veer = true;
	wipeSlate();
	}
}
function wipeSlate() {
	mass.off(part + ' ' + hike);
}
function isBusy(whirl) {
	return whirl.is(':animated');
}
function nextNumber(aim, knob, quick) {
	var intent = base, hook = list[knob];
	up ? intent += slot : intent -= slot;
	if (quick) {
	aim.scrollTop(intent);
	revolveTooth();
	}
	else aim.animate({scrollTop: intent}, term, revolveTooth);
function revolveTooth() {
	up ? hook.eq(0).appendTo(aim) : hook.eq(9).prependTo(aim);
	list[knob] = aim.find('.quota');
	niche[knob] = Number(list[knob].eq(2).text());
	aim.scrollTop(base);
	field.text(niche.join(''));
}
}
}
function lotRelease() {
	gate.off(yaw).add(mass).off(hike);
	mass.off(part);
}
function tallyCells() {
	cog.each(function() {
		for (var i = 0; i < 10; i++) {
		var n; !i ? n = 8 : (i == 1 ? n = 9 : n = i-2);
		$(this).append('<div></div>').find('div').eq(i).text(n).addClass('quota');
		}
	});
	mass = $('.quota');
}
});
body {
  text-align: center;
  background: grey;
}
#ticker, .rotator {
  display: inline-block;
}
.rotator {
  width: 100px;
  height: 140px;
  font-family: "Times New Roman";
  font-size: 50px;
  line-height: 80px;
  background-image:
  url(http://ataredo.com/external/image/flip.png),
  url(http://ataredo.com/external/image/flip.png),
  url(http://ataredo.com/external/image/flip.png);
  background-position: 0 0, 50% 50%, 100% 150%;
  background-size: 300% 50%;
  background-repeat: no-repeat;
  margin: 0 0 10px;
  overflow: hidden;
  opacity: 0;
}
.quota {
  height: 50%;
  cursor: default;
  -webkit-tap-highlight-color: rgba(0,0,0,0);
  -webkit-tap-highlight-color: transparent;
}
#result {
  height: 35px;
  font-size: 20px;
  color: white;
  line-height: 35px;
  letter-spacing: 3px;
  -webkit-box-shadow: 0 0 3px black;
  box-shadow: 0 0 3px black;
}
<script src="//ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/jquery-mousewheel/3.1.12/jquery.mousewheel.js"></script>
<div id="ticker">
  <div class="rotator"></div>
  <div class="rotator"></div>
  <div class="rotator"></div>
  <div id="result"></div>
</div>

它将自动填充数字,因此不需要编写标记。也响应鼠标拖动。


脚本的最新演变可以在这里找到:

codepen.io/Shikkediel/钢笔/avVJdG


最终更新-一个3d版本,使用transition而不是jQuery .animate。轮子是由围绕x轴单独旋转的元素组成的,创造了一个基本上无限的十角形,而不需要添加或附加元素:

codepen.io/Shikkediel/钢笔/qpjGyq

齿轮是"可闪烁的",使它们以用户指定的速度前进-然后在点击时再次停止。它们对鼠标滚轮事件的反应也比原始演示快得多。这两个原因都是我省略了单击事件的原因,而不是像前面的脚本那样。浏览器支持也有一些限制,但仍然很好-我已经做了额外的努力,使其与IE10+兼容。