简体   繁体   English

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

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

My question is about an answer given by user ByteHamster here: How to create JavaScript/HTML5 Spinner List with images? 我的问题是关于用户ByteHamster给出的答案: 如何使用图像创建JavaScript / HTML5 Spinner列表? in the answer he/she gives an example of how to create a scrolling animation with html, css and Javascript. 在答案中,他/她给出了如何使用html,css和Javascript创建滚动动画的示例。 The animation allows the user to scroll through the numbers by clicking above or below the selected number on screen, and the selected number is shown in a div below the animation. 动画允许用户通过单击屏幕上所选数字的上方或下方滚动数字,所选数字显示在动画下方的div中。

I was wondering if it's possible to do something similar to this but instead of having an image moving up and down, can it be turned into a number wheel? 我想知道是否可以做类似的事情,但不是让图像上下移动,它可以变成数字轮吗? By that I mean, in the example above, the scrolling stops in one direction once the number reaches 0, I'm wondering if it's possible to create a wheel, where a user could constantly spin it from top to bottom, or bottom to top if they wished to do so. 我的意思是,在上面的例子中,一旦数字达到0,滚动停在一个方向,我想知道是否可以创建一个轮子,用户可以不断地从上到下,或从下到上旋转如果他们愿意这样做。 Would this require using 3d interactive animation software? 这需要使用3D交互式动画软件吗?

I've seen this question: HTML5/CSS3 - how to make "endless" rotating background - 360 degrees panorama but I'm unsure if the answers are applicable to my project as they don't seem to be interactive. 我已经看到了这个问题: HTML5 / CSS3 - 如何制作“无尽的”旋转背景 - 360度全景,但我不确定答案是否适用于我的项目,因为它们似乎不是交互式的。

As user ByteHamster's answer is over 3 years old, I was wondering if there's a better way to achieve this effect with a html5 animation? 用户ByteHamster的答案超过3年,我想知道是否有更好的方法来实现html5动画效果? And am I correct in thinking that the Javascript in the example would make it not work on some devices/browsers that don't have Javascript enabled? 我是否正确认为示例中的Javascript会使某些设备/浏览器无法启用Javascript? Would a html5 approach be the best way to ensure the effect works on most devices/browsers? html5方法是否是确保效果适用于大多数设备/浏览器的最佳方法?

Here's what I put together from the info provided... works with the mousewheel, swiping and clicking on the top and bottom numbers. 这是我从提供的信息中汇总的内容...使用鼠标滚轮,滑动并单击顶部和底部数字。 Infinite as requested of course. 当然要求无限。 No special perspective style (yet) but I thought it looked quite decent as is. 没有特殊的透视风格(但)我觉得它看起来很不错。 Could still be an option naturally. 仍然可以自然选择。 Didn't use the plugin I linked to in the comments or requestAnimationFrame but jQuery animate() is quite a good tool for this. 没有使用我在评论或requestAnimationFrame链接的插件,但jQuery animate()是一个非常好的工具。 The library has great cross browser support (that's it's strength actually), all it needs is a link to it for the JavaScript to be able to get executed. 该库具有很好的跨浏览器支持(实际上它的强度),它需要的只是一个链接,以便JavaScript能够执行。 You could use a CDN, this version also works for IE8- : 您可以使用CDN,此版本也适用于IE8-:

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

For the best cross browser support on using the mousewheel, this plugin was included : 为了获得使用鼠标滚轮的最佳跨浏览器支持,此插件包括在内:

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

https://plugins.jquery.com/mousewheel/ https://plugins.jquery.com/mousewheel/

Just a basic parent and styling with spans for each number, a few prepended in case of going up. 只是一个基本的父母和造型与每个数字的跨度,一些前置的情况下升。

 $(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> 

Pretty straightforward, animates the scroll position up or down and then appends or prepends the first or last number depending on the direction. 非常简单,向上或向下动画滚动位置,然后根据方向追加或预先添加第一个或最后一个数字。 The duration of the animation can be set here : 可以在此处设置动画的持续时间:

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

Updated - after having some new insights, for example the touchend event always firing on the original element, I've overhauled the code. 更新 - 在获得一些新的见解后,例如touchend事件总是触发原始元素,我已经彻底检查了代码。 Besides that, it now has a sprite background that will stay in proportion with the size of the numbers themselves. 除此之外,它现在有一个精灵背景,它将与数字本身的大小成比例。 Also improved the overall logic and removed a nested listener glitch. 还改进了整体逻辑并删除了嵌套侦听器故障。

Another reason for this edit is to insert a demo that allows to have multiple tickers (and preset the numbers). 这种编辑的另一个原因是插入一个允许有多个代码(并预设数字)的演示。 As I've even moved on beyond that (adding direct response functionality), I thought it would be a good idea to leave the minimal working code for that here as well: 由于我甚至已经超越了这一点(添加了直接响应功能),我认为最好还是留下最小的工作代码:

 $(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> 

It will populate the numbers automatically so there's no need to write the markup. 它将自动填充数字,因此无需编写标记。 Responds to mouse dragging as well. 响应鼠标拖动。


The latest evolution of the script can be found here : 脚本的最新发展可以在这里找到:

codepen.io/Shikkediel/pen/avVJdG codepen.io/Shikkediel/pen/avVJdG


Final update - a 3d version that uses transition instead of jQuery .animate . 最终更新 - 使用transition而不是jQuery .animate的3d版本。 The wheel is made up of individually rotated elements around the x-axis, creating a basically infinite decagon without the need for prepending or appending elements: 轮子由围绕x轴的单独旋转元件组成,创建一个基本无限的十边形,无需预先添加或附加元素:

codepen.io/Shikkediel/pen/qpjGyq codepen.io/Shikkediel/pen/qpjGyq

The cogs are "flickable", making them progress at the speed that the user gives them - then stop again when clicking. 齿轮是“可以轻弹的”,使它们以用户给出的速度前进 - 然后在点击时再次停止。 They also respond much quicker to mouse wheel events than the original demo. 与原始演示相比,它们对鼠标滚轮事件的响应速度更快。 Both reasons why I've left out click events, as opposed to the earlier scripts. 我遗漏点击事件的两个原因,而不是早期的脚本。 Browser support is also a bit more limited but good nonetheless - I've made an extra effort to make it IE10+ compatible. 浏览器支持也有点受限但很好 - 我已经做了额外的努力使其与IE10 +兼容。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM