基于滑块值的平滑动画
Posted
技术标签:
【中文标题】基于滑块值的平滑动画【英文标题】:Smooth animation based on slider value 【发布时间】:2013-10-08 04:01:06 【问题描述】:我有一个基本的 html Slider 元素。我希望制作的内容很简单——当滑块位于一端时,会输出一张简单的笑脸。当它在另一端时,输出一张简单的悲伤脸。
我想要的关键是从动画的一侧到另一侧的平滑过渡 - 所以笑脸会经历冷漠和轻微快乐/轻微悲伤的不同阶段。
假设滑块输出了一个介于 1 到 10 之间的浮点数,对应于显示图像的“幸福度”。
您将如何解决这个问题?我试过搜索和谷歌搜索,但没有好的结果。可接受的所有技术 - 对如何存储图像/动画特别感兴趣。
【问题讨论】:
您可以像 Akismet 为他们的个人计划所做的那样做一些事情,即“akismet 对您有什么价值?” akismet.com/account/upgrade 处的滑块。他们只是拥有不同笑脸的图像,并在它们之间切换akismet.com/img/ab/smiley.png 【参考方案1】:如果您可以在 SVG 中绘制脸部,您可以使用 Raphael 之类的东西。例如,如果您要保持相同的圆脸并仅变形嘴巴。这将在形状之间设置动画。不太确定这是否是您的意思。这是我的 2 秒可怕的嘴巴路径。
var paper = Raphael( "canvas_container",400,400);
paper.circle(280, 210, 150);
// create the 2 paths to animate between in some app like inkscape
var pathStr1 = "m385,255l-197,-3l40,57l88,1l35,0l34,-55z",
pathStr2 = "m207,268l162,-1l-33,-45l-41,-2l-46,-1l-32,20l-10,29z";
var path = paper.path(pathStr1).attr(fill: "yellow", "stroke-width": 3);
setTimeout(function()path.animate(path: pathStr2, 3000, "linear");, 1000);
http://jsfiddle.net/YUhHw/1/ 有一个小提琴,http://cancerbero.mbarreneche.com/raphaeltut/#sec-animation 有更好的示例(上面的代码基于部分)的教程,http://raphaeljs.com/animation.html 有很好的示例我猜你需要更改 setTimeout 以对应于你的滑块。
【讨论】:
这也很酷。我担心使用这些路径创建设计的数学计算会太多,但看起来真的很复杂。有没有办法“绘制”图像,并让它为你绘制要转换的线的 pathStr? 是的,如果你使用类似 inkscape inkscape.org 的东西,你可以创建 svg 并在它们之间制作动画(你可能想要创建单独的头部,然后在 pathStr1 和 pathStr2 之间制作动画的两个嘴) .您可能需要查看 svg 标记本身,这样才有意义。要快速进行基本操作,您可以转到svg-edit.googlecode.com/svn-history/r1771/trunk/editor/… 然后画一些东西,然后单击 svg 按钮,它会显示标记以感受它。【参考方案2】:您可以使用 CSS 的 transform: rotateX
来做您想做的事。在我的版本中,我还使用了 HTML5 的 input
和 type="range"
,但如果您想影响旧浏览器,您可以使用相同的方法和更全局的滑块。该演示涉及使用两张图像,一张用于面部和背景,一张用于嘴唇,但如果您喜欢该技术,您可以以同样的方式将其应用于纯 CSS。只需确保在 javascript 中包含所需的所有浏览器前缀
Live Demo Here
/* HTML */
<div id='slimey'>
<div id='lips'></div>
</div>
<input id="smileSlide" type="range" onchange="changeSmile(this)" value="0" />
/* Javascript */
var lips = document.getElementById('lips');
function changeSmile(slider)
var sliderVal = slider.value,
rotateDegree = - sliderVal * 1.8;
lips.style.webkitTransform = "rotateX(" + rotateDegree + "deg)";
lips.style.transform = "rotateX(" + rotateDegree + "deg)";
/* CSS */
#slimey
margin:auto;
background:url(http://i.imgur.com/LGQMhc3.jpg);
background-size: 100% 100%;
height:100px;
width:100px;
position:relative;
#lips
width:50px;
height:20px;
position:absolute;
top:calc(70% - 10px);
left:calc(50% - 25px);
background:url(http://i.imgur.com/20EmUM7.gif);
background-size: 100% 100%;
-webkit-transform:rotateX(0deg);
transform:rotateX(0deg);
#smileSlide
width:100px;
position:absolute;
left:calc(50% - 50px);
灵感来自Marco Barria's(这家伙有一些很棒的项目)single element flying bird
如果您想让中间状态更明显,您可以在中间范围like this demo does 中切换一行的显示。像这个答案的其余部分一样,它只是一个近似的解决方案,但我认为它很好地展示了这项技术。如果你想获得 super 的幻想,你甚至可以为线条添加淡入/淡出,让它看起来更平滑一点
【讨论】:
哦,这真的很酷。我很喜欢。感谢分享,我真的很感激。 同意,这是一个非常巧妙的方法。 酷。我不能使用calc()
,所以我摆弄了它:jsfiddle.net/UV7gV/1(也没有图像):D【参考方案3】:
我使用纯 css 和 js 更改了 Zeaklous 的答案(没有任何图像或旋转) http://jsfiddle.net/sijav/PVvc4/3/
<!--HTML-->
<div id='slimey'>
<div id='leye' class='eye'></div>
<div id='reye' class='eye'></div>
<div id='lips'></div>
</div>
<input id="smileSlide" type="range" onchange="changeSmile(this)" value="0" />
//Java Script
var lips = document.getElementById('lips');
function changeSmile(slider)
var lh = lips.style.height, slide=0;
if ((50 - slider.value) > 0)
slide = (50 - slider.value);
lips.style.borderTop = "2px black solid";
lips.style.borderBottom = "none";
else
slide = (slider.value - 50);
lips.style.borderBottom = "2px black solid";
lips.style.borderTop = "none";
lips.style.height = slide * 0.4 + "px" ;
lips.style.top = "calc(70% + " + (- slide) * 0.2 + "px" ;
/**CSS**/
#leye
left:25%;
#reye
right:25%;
.eye
position:absolute;
background:black;
border-radius:100%;
height:15px;
width:15px;
top:20px;
#slimey
margin:auto;
background:Yellow;
border-radius:100%;
height:100px;
width:100px;
position:relative;
#lips
width:50px;
height:20px;
position:absolute;
top:calc(70% - 10px);
left:calc(50% - 25px);
background:transparent;
border-top:2px black solid;
-webkit-transform:rotateX(0deg);
border-radius:100%;
transform:rotateX(0deg);
#smileSlide
width:100px;
position:absolute;
left:calc(50% - 50px);
编辑:嘴唇在此处移动的细微差别http://jsfiddle.net/sijav/PVvc4/4/
【讨论】:
【参考方案4】:只需使用一个没有嘴巴的 png 脸,以及几个基于 Javascript 滑块位置切换的补间嘴巴。将文件存储在数组中,并从定时函数调用它们以检查面部位置。简单轻便。
var mouthArray = new Array('frown','half_frown','half_smile','smile');
var face = document.getElementById('face');
var faceLoc = parseInt(face.style.left);
function changeMouth()
if(faceLoc<10)
theMouth.setAttribute('src',mouthArray[0]);
if(faceLoc>10,faceLoc<=19)
theMouth.setAttribute('src',mouthArray[1]);
if(faceLoc>20,faceLoc<=29)
theMouth.setAttribute('src',mouthArray[2]);
if(faceLoc>30,faceLoc<40)
theMouth.setAttribute('src',mouthArray[3]);
如果对滑块的长度给予足够的迭代,那么沿着这些思路,应该会给你一个体面的“平滑”效果。
【讨论】:
【参考方案5】:为了好玩,我在午餐时用纯 CSS(没有图像或 JavaScript)编写了一个纯 Webkit 的小版本——here's a demo。我不一定推荐这种方法,但我忍不住试一试!
这是一个非常简单的方法。我使用了一组单选按钮而不是滑块,它允许您使用 :checked
伪类来根据所选值更改嘴巴的颜色和形状。仅使用height
和border-radius
描述嘴形。例如:
#feel-0:checked ~ #mouth
border-radius: 30px 30px 0 0;
height: 20px;
margin-top: -5px;
说明文本只是所选单选按钮的标签字段。最初所有标签都是隐藏的,但是一旦选中一个字段,相邻的标签就会变得可见:
#happiness input:checked + label
visibility: visible;
您可以使用箭头键更改选择的字段(视觉上向左或向右移动滑块) - 这是单选组的内置行为。
通过一些工作,您可以调整它以使滑块在非 WebKit 浏览器中看起来更好;但是,在某些较旧的浏览器中它可能会出现问题,并且您无法向左或向右拖动滑块。对于生产,我会使用 JavaScript 滑块(例如,许多 可用的 jQuery 选项之一)并将 CSS 伪类魔法换成少量 JS 和少数类。
【讨论】:
以上是关于基于滑块值的平滑动画的主要内容,如果未能解决你的问题,请参考以下文章