【问题标题】:Multiple elements moving circularly - smooth transition多个元素循环移动 - 平滑过渡
【发布时间】:2013-09-01 15:50:22
【问题描述】:

我正在尝试创建一个带有n 元素的循环导航,可通过单击键盘的左右箭头进行导航。我使用具有特定 CSS3 rotatetranslate 值的类以及一些 javascript 来更改这些类。

我的问题是具有fourfive 类的元素之间的转换,即360deg30deg 之间的转换,这与我想要的方向相反它到。你可以看到明显的不需要的行为here in this jsFiddle

.one    { transform: rotate(270deg) translate(200px); }
.two    { transform: rotate(300deg) translate(200px); }
.three  { transform: rotate(330deg) translate(200px); }
.four   { transform: rotate(360deg) translate(200px); }<-- Problematic transition
.five   { transform: rotate(30deg)  translate(200px); }<-- Problematic transition
.six    { transform: rotate(60deg)  translate(200px); }
.seven  { transform: rotate(90deg)  translate(200px); }
.eight  { transform: rotate(120deg) translate(200px); }
.nine   { transform: rotate(150deg) translate(200px); }
.ten    { transform: rotate(180deg) translate(200px); }
.eleven { transform: rotate(210deg) translate(200px); }
.twelve { transform: rotate(240deg) translate(200px); }

我更喜欢 CSS 修复,但我也尝试了一个可以在 here 找到的 JavaScript 修复。在这个例子中,我只尝试使用左箭头。我使用 javascript 的方法是获取字符串形式的当前翻译值,从中去除 rotate 度数,然后根据是否按下右箭头或左箭头来添加或减去 30 度。这种方法目前的问题是它没有给我element.style.webkitTransform 的值(我正在使用Chrome),它只是出于某种原因是空的。此外,我不希望在 javascript 中为所有内容添加前缀,这就是我想要仅修复 CSS 的原因

我对 javascript 的尝试(未经测试,因为第一行由于某种原因无法工作):

var thisTransform = circleArray[i].style.webkitTransform;
if (thisTransform.indexOf("rotate(") >= 0) {
    var newDeg = parseInt(thisTransform.split("rotate(")[1].substring(thisTransform.indexOf("deg"))) - 30;
    circleArray[i].style.webkitTransform = "rotate(" + newDeg + "deg) translate(200px) !important;";
}

旁注:我在我的项目中使用 prefixfree.min.js 来防止表单必须手动输入所有浏览器前缀

是否有针对我不知道的问题的仅 CSS 解决方案?尝试使用 javascript 获取 translate 值时导致错误的原因是什么?

【问题讨论】:

    标签: javascript css rotation css-transitions


    【解决方案1】:

    首先,让我说,我认为最好的解决方案可能是旋转基圆;我几乎可以肯定结果会更好、更容易。

    但这只是一个附带的想法,让我们看看你发布的问题。

    我已经解决了您的问题,创建了一个可以正确移动有问题的类的类。我的想法是提供一个可以正常运动的动画:

    .foura   { -webkit-transform: rotate(360deg) translate(200px); 
        -webkit-animation: aclock .3s linear 1;
        transform: rotate(360deg) translate(200px); 
        animation: aclock .3s linear 1;
        transition: none;
    }
    @keyframes aclock {
        0% {transform: rotate(30deg) translate(200px);}
       100% {transform: rotate(0deg) translate(200px);}
    }
    

    这个想法是通过动画完成从 30 度到 360 度的运动,可以将其从 30 度更改为 0 度。

    我为五班提供另一个类似的课程。

    剩下的问题是脚本必须根据旋转方向将元素设置为四类或四类,五类和五类也是如此。

    这导致了那个(有些混乱的)脚本:

    document.onkeydown = function (e) {
        e = e || window.event;
        switch(e.which || e.keyCode) {
            case 37:
                for (var i = 0, j = circleArray.length; i < j; i++) {
                    var curClassList = circleArray[i].classList,
                        curClass = curClassList.toString().split(' ')[1];
                        baseClass = curClass;
                        if (baseClass == "fivea") {
                            baseClass = "five";
                }
                        if (baseClass  == "foura") {
                            baseClass  = "four";
                }
    
                    if(circleClassArray.indexOf(baseClass) - 1 >= 0)
                    {
                        var newClass = circleClassArray[circleClassArray.indexOf(baseClass) - 1];
                        if (newClass == "four") {
                            newClass = "foura";
                }
                        curClassList.add(newClass)
                        curClassList.remove(curClass);
                    } else {
                        curClassList.add(circleClassArray[j - 1]);
                        curClassList.remove(curClass);
                    }
                }
                break;
            case 39:
                for (var i = 0, j = circleArray.length; i < j; i++) {
                    var curClassList = circleArray[i].classList,
                        curClass = curClassList.toString().split(' ')[1];
                        baseClass = curClass;
                        if (baseClass == "fivea") {
                            baseClass = "five";
                }
                        if (baseClass  == "foura") {
                            baseClass  = "four";
                }
                    if(circleClassArray.indexOf(baseClass) + 1 < j)
                    {
                        var newClass = circleClassArray[circleClassArray.indexOf(baseClass) + 1];
                        if (newClass == "five") {
                            newClass = "fivea";
                }
                        curClassList.add(newClass)
                        curClassList.remove(curClass);
                    } else {
                        curClassList.add(circleClassArray[0]);
                        curClassList.remove(curClass);
                    }
                }
                break;
        }
    }
    

    这是完整的 CSS:

    .circle-big {
        position: relative;
        height:500px;
        width:500px;
        background:red;
        border-radius: 50% 50%;
        margin: 10% 10%;
        border:5px solid black;
    }
    .circle-inner {
        border-radius: 50%;
        width: 300px;
        height: 300px;
        border: 5px solid white;
        background-color: black;
        display: block;
        position: absolute;
        overflow: hidden;
        top: 50%;
        left: 50%;
        margin-top:-155px;
        margin-left:-155px;
    }
    .circle {
        border-radius: 50%;
        width: 70px;
        height: 70px;
        background-color: white;
        display: block;
        position: absolute;
        overflow: hidden;
        top: 50%;
        left: 50%;
        margin-top:-35px;
        margin-left:-35px;
        transition: all .3s linear;
    }
    .one    { -webkit-transform: rotate(270deg) translate(200px); 
              transform: rotate(270deg) translate(200px); 
              background:blue; }
    .two    { -webkit-transform: rotate(300deg) translate(200px); 
              transform: rotate(300deg) translate(200px); }
    .three  { -webkit-transform: rotate(330deg) translate(200px);
              transform: rotate(330deg) translate(200px);
    }
    .four   { -webkit-transform: rotate(360deg) translate(200px);
              transform: rotate(360deg) translate(200px);}
    .foura   { -webkit-transform: rotate(360deg) translate(200px); 
              -webkit-animation: aclock .3s linear 1;
              transform: rotate(360deg) translate(200px); 
              animation: aclock .3s linear 1;
              transition: none;
    }
    .five   { -webkit-transform: rotate(30deg)  translate(200px);
              transform: rotate(30deg)  translate(200px);}
    .fivea   { -webkit-transform: rotate(30deg)  translate(200px); 
              -webkit-animation: clock .3s linear 1;
              transform: rotate(30deg)  translate(200px); 
              animation: clock .3s linear 1;
              transition: none;
    }
    .six    { -webkit-transform: rotate(60deg)  translate(200px);
              transform: rotate(60deg)  translate(200px);}
    .seven  { -webkit-transform: rotate(90deg)  translate(200px);
               transform: rotate(90deg)  translate(200px);}
    .eight  { -webkit-transform: rotate(120deg) translate(200px);
              transform: rotate(120deg) translate(200px);}
    .nine   { -webkit-transform: rotate(150deg) translate(200px); 
              transform: rotate(150deg) translate(200px); }
    .ten    { -webkit-transform: rotate(180deg) translate(200px); 
              transform: rotate(180deg) translate(200px);}
    .eleven { -webkit-transform: rotate(210deg) translate(200px);
              transform: rotate(210deg) translate(200px);}
    .twelve { -webkit-transform: rotate(240deg) translate(200px);
              transform: rotate(240deg) translate(200px);}
    
    @-webkit-keyframes clock {
        0% {-webkit-transform: rotate(0deg) translate(200px);}
      100% {-webkit-transform: rotate(30deg) translate(200px);}
    }
    
    @-webkit-keyframes aclock {
        0% {-webkit-transform: rotate(30deg) translate(200px);}
      100% {-webkit-transform: rotate(0deg) translate(200px);}
    }
    
    @keyframes clock {
        0% {transform: rotate(0deg) translate(200px);}
      100% {transform: rotate(30deg) translate(200px);}
    }
    
    @keyframes aclock {
        0% {transform: rotate(30deg) translate(200px);}
      100% {transform: rotate(0deg) translate(200px);}
    }
    

    updated fiddle

    按照我的第一个想法,我在脚本中添加了以下代码:

       case 38:
        angle = angle + 30;
        var circleBig = document.getElementsByClassName("circle-big")[0];
        var style = "rotate(" + angle + "deg)";
        circleBig.style.webkitTransform = style;
        break;
    case 40:
        angle = angle - 30;
        var circleBig = document.getElementsByClassName("circle-big")[0];
        var style = "rotate(" + angle + "deg)";
        circleBig.style.webkitTransform = style;
        break;
    

    并添加了过渡到大圆圈。现在我认为它可以正常工作(在向上和向下箭头上!)

    second version

    全新版本

    为了新的要求(保持内圈直立),我重新设计了大部分小提琴。我改编了我从 Lea Verou 那里看到的一个想法,在没有辅助 div 的情况下进行旋转。它包括将变换设置为角度+平移+相反角度。这使得 div 去你想要的地方,不旋转。

    一旦决定走这条路,脚本就必须修改内圈的样式,而不是基圈的样式。为了轻松做到这一点,我在每个元素中存储了该特定元素的角度(在数据属性中)。

    Brand New demo

    生成的 HTML 类似:

    <div class="circle-big">
        <div class="circle one" data-angle=270>1</div>
        <div class="circle two" data-angle=300>2</div>
        <div class="circle three" data-angle=330>3</div>
        <div class="circle four" data-angle=0>4</div>
        <div class="circle five" data-angle=30>5</div>
        <div class="circle six" data-angle=60>6</div>
        <div class="circle seven" data-angle=90>7</div>
        <div class="circle eight" data-angle=120>8</div>
        <div class="circle nine" data-angle=150>9</div>
        <div class="circle ten" data-angle=180>10</div>
        <div class="circle eleven" data-angle=210>11</div>
        <div class="circle twelve" data-angle=240>12</div>
        <div class="circle-inner"></div>
    </div>
    

    脚本是

    var circleArray = document.getElementsByClassName("circle");
    var angle = 0;
    
    window.onload = chargearray;
    
    function chargearray () {
        for (var i = 0, j = circleArray.length; i < j; i++) {
            var circle = circleArray[i];
            var circleAngle = parseInt (circle.dataset.angle);
            var totalAngle = angle + circleAngle
            var style = "rotate(" + totalAngle + "deg) translate(200px)";
            totalAngle = - totalAngle;
            style = style + " rotate(" + totalAngle + "deg)"
            circle.style.webkitTransform = style;
            circle.style.Transform = style;
        }
    }
    
    document.onkeydown = function (e) {
        e = e || window.event;
        switch(e.which || e.keyCode) {
            case 37:
                angle = angle + 30;
                chargearray ();
                break;
            case 39:
                angle = angle - 30;
                chargearray ();
                break;
        }
    }
    

    【讨论】:

    • 很好的解决方案,+1!当单击按钮并且过渡有足够的时间完成时,它可以完美地工作。话虽如此,如果在过渡完成之前单击箭头,它会出现我希望避免的另一种行为。除了在过渡期间限制箭头被点击之外,还有什么帮助吗?我很想尝试旋转基圆并附加其他圆,但我不确定如何定位元素并将它们绑定到当前设置位置的父级。对这个想法有帮助吗?
    • 我在上面评论中提到的跳跃性是我试图远离 CSS 动画的原因
    • 真的,我不知道如何解决紧张的用户引起的跳动。基于我旋转基圆的第一个想法,我添加了另一个解决方案。我现在注意到我只包含了 webkit 翻译,对此感到抱歉!
    • 我不介意唯一的 webkit 翻译,正如我所说的,无论如何我都使用前缀。谢谢你的第二个版本!这正是我在尝试修复 javascript 时所寻找的,只是你消除了对给我一个错误的部分的需求。我只是把你的工作拿走了,把不必要的部分拿出来清理了一下jsfiddle.net/Zeaklous/jGAze/18(对于可能有兴趣使用它的其他人)
    • 很高兴为您提供帮助。顺便说一句,当您获得变换的当前值时,它始终是矩阵格式;将其转换回旋转并非易事。最好将它保存在脚本中的变量中。
    猜你喜欢
    • 2013-07-01
    • 2020-09-17
    • 1970-01-01
    • 1970-01-01
    • 2018-08-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-02-28
    相关资源
    最近更新 更多