首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >具有有限元素的列表轮换

具有有限元素的列表轮换
EN

Stack Overflow用户
提问于 2015-10-29 10:50:39
回答 5查看 2.9K关注 0票数 17

我有container和名单(卡片)在里面。当我将它悬停时,卡片开始移动(translateX animation)。containerwidth300px,元素在container:3中计数,每个元素width:100px

所以您可以看到容器中的3个元素在一起,overflow:hidden。我想要做的是,当没有元素显示translateX动画-100 in =100 in空白后的第三个元素,它从列表中的最后一个元素开始,没有空格。

就目前而言,我不知道如何才能做到没有重复等等。

下面是我现在要做的:小提琴 (汉弗卡看翻译动画)

UPD 1:代码和数据(卡片计数,容器大小)被拿来举例,我将尝试更好地解释我想要的内容:我的目标是构建卡片列表,按下按钮后,列表将开始移动(例如translateX动画)一段时间(例如translateX:12491 of ,动画-持续时间:15s;)和停止。但问题是,名单中的骰子数量将在3-40张牌的范围内(每张卡的宽度和高度为100 40)。因此,例如,当我设置translateX:12491px时,它将超出范围,在列表中的最后一张卡片之后将出现空白。我希望第一张和最后一张牌以某种方式打成平局,在最后一张卡之后,立即出现在名单中的第一张牌,等等。也许我是在错误地寻找解决方案,但我想你明白主要的想法。

UPD 2:我发现cs:go使用了我想在html\css\js上写的动画。这是视频:youtube.com

html:

代码语言:javascript
复制
<div class="container">
    <div class="cards">
        <div class="card">
        1
    </div>
    <div class="card">
        2
    </div>
    <div class="card">
        3
    </div>
    </div>
</div>

css:

代码语言:javascript
复制
.container
{
    width:300px;
        height: 100px;
    border: 2px solid black;
    overflow: hidden;
}
.card
{
    float:left;
    height: 100px;
    width: 100px;
    background-color:blue;
    box-sizing: border-box;
    border: 2px solid red;
    color: white;
    font-size: 23px;
}
.cards:hover
{
    transform: translateX(-100px);
    transition-duration: 3s;
    animation-duration: 3s;
    animation-fill-mode: forwards;
}
EN

回答 5

Stack Overflow用户

回答已采纳

发布于 2015-11-02 09:56:32

从列表中的最后一个元素开始,没有空白处。

这超出了CSS的范围,为此您需要Javascript。因为,您已经用Javascript而不是jQuery标记了这个问题,所以我的回答将仅限于纯Javascript。看,妈妈,没有JQuery ;)

我不知道没有复制件怎么能做到

这里有一个DIY (自己动手)的想法。

  1. 主要的窍门是至少显示一个项目比你的总数少。如果你有3张卡,只显示2张。如果你有4张卡,只显示3张。为什么,因为你需要重新定位一张卡,当它离开视野,并包装在最后。如果你显示的牌数与你的相同,那么你不能打破半张牌并包装它,你会看到一些空白处,直到第一个离开视野。你知道这个主意吗?
  2. 不要使用translate,否则您最终会在编写脚本时使事情复杂化。保持简单。
  3. 请勿为您的卡片使用包装。为什么?因为,我们将重新定位那些已经消失的卡片。当我们这样做的时候,下一张牌就会占据它的位置,立即离开视线,使事情对你来说更加困难。
  4. 为了保持简单,使用相对于容器的absolute定位来安排您的卡片。首先,让所有的卡片在top:0; and left: 0;堆起来。
  5. 下一个连接Javascript定位left属性,基于每个卡的width,并将它们线性排列。
  6. 使用requestAnimationFrame控制动画。
  7. 跟踪最左边的卡及其left位置.当这超出视图(0减去宽度)时,将此卡appendChild到其容器中。这将把卡片移到卡片的末尾。另外,根据列表中的最后一张卡将left属性更改为它。
  8. 这就是一切。

下面是一个演示。为了便于您进行实验,我使用了一个设置对象来保持可配置的属性,您可以轻松地调整和查看这些属性。仔细看看代码,你会发现它很容易理解。您可以将iterations设置设置为0,以使动画无限。

此外,请注意,您不需要重复或伪造的卡。尝试演示,并添加尽可能多的卡片,你想。

代码片段中的内联代码注释将进一步帮助您理解每一行代码,并与上述步骤相关联。

片段:

代码语言:javascript
复制
var list = document.querySelector('.cardList'), // cache the container
    cards = document.querySelectorAll('.card'), // cache the list of cards
    start = document.getElementById('start'),   // buttons
    stop = document.getElementById('stop'), 
    reset = document.getElementById('reset'), 
    raf, init = 0, counter = 0, lastCard, currentIteration = 0, // general purpose variables
    settings = { // settings object to help make things configurable
        'width': 100, 'height': 100, 'speed': 2, 
        'iterations': 2, 'count': cards.length 
    }
;
start.addEventListener('click', startClick); // wire up click event on buttons
stop.addEventListener('click', stopClick);
reset.addEventListener('click', resetClick);
initialize(); // initialize to arrange the cards at start

function initialize() {
    // loop thru all cards and set the left property as per width and index position
    [].forEach.call(cards, function(elem, idx) { 
        elem.style.left = (settings.width * idx) + 'px';
    }); 
    init = -(settings.width); // initialize the view cutoff
    lastCard = cards[settings.count - 1]; // identify the last card
    counter = 0; currentIteration = 0; // reset some counters
    settings.speed = +(document.getElementById('speed').value);
    settings.iterations = +(document.getElementById('iter').value);
}
function startClick() { 
    initialize(); raf = window.requestAnimationFrame(keyframes); // start animating
}
function stopClick() { window.cancelAnimationFrame(raf); } // stop animating
function resetClick() { // stop animating and re-initialize cards to start again
    window.cancelAnimationFrame(raf); 
    document.getElementById('speed').value = '2';
    document.getElementById('iter').value = '2';
    initialize(); 
}

// actual animation function
function keyframes() {
    var currentCard, currentLeft = 0, newLeft = 0;
    // iterate all cards and decrease the left property based on speed
    [].forEach.call(cards, function(elem, idx) {
        elem.style.left = (parseInt(elem.style.left) - settings.speed) + 'px';
    }); 
    currentCard = cards[counter]; // identify left-most card
    currentLeft = parseInt(currentCard.style.left); // get its left position
    if (currentLeft <= init) { // check if it has gone out of view
        // calculate position of last card
        newLeft = parseInt(lastCard.style.left) + settings.width;
        list.appendChild(currentCard); // move the card to end of list
        currentCard.style.left = newLeft + 'px'; // change left position based on last card
        lastCard = currentCard; // set this as the last card for next iteration
        counter = (counter + 1) % settings.count; // set the next card index
        if ((settings.iterations > 0) && (counter >= (settings.count - 1))) { 
            currentIteration++; // check settings for repeat iterations
        }
    }
    if (currentIteration >= settings.iterations) { return; } // when to stop
    raf = window.requestAnimationFrame(keyframes); // request another animation frame
};
代码语言:javascript
复制
* { box-sizing: border-box; padding: 0; margin: 0; }
.cardList { 
    position: relative; height: 100px; width: 300px; 
    margin: 10px; border: 2px solid #33e; 
    overflow: hidden; white-space: nowrap; 
}
.card { 
    position: absolute; left: 0; top: 0; text-align: center;
    height: 100px; width: 100px; line-height: 100px;
    background-color: #99e; 
    font-family: monospace; font-size: 2em; color: #444;
    border-left: 1px solid #33e; border-right: 1px solid #33e;
}

div.controls, button { margin: 10px; padding: 8px; font-family: monospace; }
div.controls input { width: 48px; padding: 2px; text-align: center; font-family: monospace; }
代码语言:javascript
复制
<div class="controls">
    <label>Speed <input id="speed" type="number" min="1" max="8" value="2" />x</label>
    &nbsp;|&nbsp;
    <label>Iterations <input id="iter" type="number" min="0" max="8" value="2" /></label>
</div>
<div class="cardList">
    <div class="card">1</div>
    <div class="card">2</div>
    <div class="card">3</div>
    <div class="card">4</div>
</div>
<button id="start">Start</button>
<button id="stop">Stop</button>
<button id="reset">Reset</button>

Fiddle: http://jsfiddle.net/abhitalks/1hkw1v0w/

注意:,我在演示中遗漏了一些东西。特别是,虽然卡的宽度和高度是设置对象的一部分,但目前它是固定的。您可以很容易地使用设置对象,使卡的尺寸以及配置。

编辑:

(根据Op的评论)

如果你想更好地控制距离,滚动,持续时间和计时功能(放松),那么你可以自己使用一个库来实现这些功能。有两个这样好的库是罗伯特·彭纳( Robert Penner)的宽松功能GSGD的jQuery插件。尽管您可以使用纯Javascript实现所有这些,但是如果使用像jQuery这样的库,则会更容易。

要想有效地做到这一点,就必须复制卡片。通过多次克隆整个列表,您可以轻松地做到这一点。

虽然您还没有用jQuery标记这个问题,但这里有一个小演示(使用jQuery快速完成),您可以在这里配置速度和距离。

代码片段2:

代码语言:javascript
复制
var $cardList 	= $('.cardList').first(), 
    $cards 		= $('.card'), 
    $speed 		= $('input[name=speed]'), 
    width 		= 100, 
    randomize 	= true, 
    distance 	= 20 * width 
;

for (var i = 0; i < 50; i++) {
    $cards.clone().appendTo($cardList);
}

function spin() {
    var newMargin = 0, newDistance = distance, 
        speed = +($speed.filter(':checked').val());
    if (randomize) {
        newDistance = Math.floor(Math.random() * $cards.length * 5);
		newDistance += $cards.length * 5;
        newDistance *= width;
    } 
	newMargin = -(newDistance);
    $cards.first().animate({
        marginLeft: newMargin
    }, speed);
}

$('#spin').click(function() {
    $cards.first().css('margin-left', 0);
    spin();
    return false;
});
代码语言:javascript
复制
* { box-sizing: border-box; padding: 0; margin: 0; }
.cardList { 
    height: 100px; width: 302px; position: relative;
    margin: 10px; border: 1px solid #33e; 
    overflow: hidden; white-space: nowrap; 
}
.card { 
    display: inline-block; text-align: center;
    height: 100px; width: 100px; line-height: 100px;
    background-color: #99e; 
    font-family: monospace; font-size: 2em; color: #444;
    border-left: 1px solid #33e; border-right: 1px solid #33e;
}
.cardList::before, .cardList::after {
    content: ''; display: block; z-index: 100;
    width: 0px; height: 0px; transform: translateX(-50%);
	border-left: 8px solid transparent;
	border-right: 8px solid transparent;    
}
.cardList::before {
    position: absolute; top: 0px; left: 50%;
	border-top: 12px solid #33e;
}
.cardList::after {
    position: absolute; bottom: 0px; left: 50%;
	border-bottom: 12px solid #33e;
}
div.controls, button { margin: 10px; padding: 8px; font-family: monospace; }
div.controls input { width: 48px; padding: 2px; text-align: center; font-family: monospace; }
代码语言:javascript
复制
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="controls">
    <label>Speed: </label>
    &nbsp;|&nbsp;
    <label><input name="speed" type="radio" value='6000' />Slow</label>
    <label><input name="speed" type="radio" value='5000' checked />Medium</label>
    <label><input name="speed" type="radio" value='3000' />Fast</label>
</div>
<div class="cardList"><!--
    --><div class="card">1</div><!--
    --><div class="card">2</div><!--
    --><div class="card">3</div><!--
    --><div class="card">4</div><!--
--></div>
<button id="spin">Spin</button>

Fiddle 2: http://jsfiddle.net/abhitalks/c50upco5/

票数 6
EN

Stack Overflow用户

发布于 2015-10-31 14:32:50

如果不想修改dom元素,可以利用属性

要做到这一点,在动画结束后仍然需要一些JS来添加这个属性;

我也改变了动画,而不是转换,所以它会在动画结束时自动重置transform属性。

代码语言:javascript
复制
$('.cards').mouseenter(function() {
  setTimeout(function() {
    $('.card').first().css("order", "2");
  }, 3000);
});

$('.cards').mouseleave(function() {
  $('.card').first().css("order", "-1");
});
代码语言:javascript
复制
.container {
  width: 300px;
  height: 100px;
  border: 2px solid black;
  overflow: hidden;
}
.card {
  float: left;
  /* height: 100px;
    width: 100px;*/
  background-color: blue;
  box-sizing: border-box;
  border: 2px solid red;
  color: white;
  font-size: 23px;
  flex: 0 0 25%;
}
.cards:hover {
  animation: trans 3s;
}
/**/

.cards {
  width: 400px;
  height: 100%;
  display: flex;
  transition: transform 3s;
}
@keyframes trans {
  0% {
    transform: translateX(0)
  }

  100% {
    transform: translateX(-100px)
  }
}
代码语言:javascript
复制
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>

<div class="container">
  <div class="cards">
    <div class="card">1</div>
    <div class="card">2</div>
    <div class="card">3</div>
  </div>
</div>

小提琴

但是如果您可以使用JS,我建议您直接操作DOM元素的顺序,使用.cards的第一个子元素并将其附加到每个动画末尾的list末尾;

试试这个:

代码语言:javascript
复制
var anim;

$('.cards').mouseenter(function(){
        
    anim = setInterval(function(){
        $('.cards').append($('.card').first())
    },3000)
    	
});

$('.cards').mouseleave(function(){
    clearInterval(anim)                   
});
代码语言:javascript
复制
.container{
    width:300px;
    height: 100px;
    border: 2px solid black;
    overflow: hidden;
}
.card{
    float:left;
   /* height: 100px;
    width: 100px;*/
    background-color:blue;
    box-sizing: border-box;
    border: 2px solid red;
    color: white;
    font-size: 23px;
    /**/
    flex:0 0 25%;
}
.cards:hover{
    animation: trans 3s infinite;
}

/**/
.cards{
    width:400px;
    height:100%;
    display:flex;
}


@keyframes trans {
  0% {
    transform: translateX(0)
  }
  100% {
    transform: translateX(-100px)
  }

}
代码语言:javascript
复制
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>
<div class="container">
    <div class="cards">
        <div class="card">
        1
    </div>
    <div class="card">
        2
    </div>
    <div class="card">
        3
    </div>
    </div>
</div>

如果您希望一张卡片同时出现在卡片列表的开头和结尾,那么您需要对元素进行深拷贝/克隆;

下面是一个例子

票数 3
EN

Stack Overflow用户

发布于 2015-10-31 17:35:22

http://jsfiddle.net/baktash93/x4f3reja/2/和您提到的效果是一样的,您的CSS上有一点调整,jQuery也有帮助。

CSS

更改translateX动画的选择器,以便在每个.card框上应用,而不是.cards (后者是.card的直系亲属)。这是因为你希望卡片向左移动,而不是让它们在移动时通过窗口出现。

那是,

代码语言:javascript
复制
.cards:hover .card {   
    transform: translateX(-100px);
    transition-duration: 1.5s;
    animation-duration: 1.5s;
    animation-fill-mode: forwards;
}

jQuery

代码语言:javascript
复制
var $container = $('.container');
var cardWidth = 100;

$container.on('mouseenter', function (e) {
    e.preventDefault();
    var $card0Clone = $('.card').eq(0).clone();    // clone of the first .card element
    $('.cards').append($card0Clone);
    updateWidth();
});
$container.on('mouseleave', function (e) {
    e.preventDefault();
    var $cards = $('.card');
    $cards.eq(0).remove();    // remove the last .card element
});

function updateWidth() {
    $('.cards').width(($('.card').length) * cardWidth);  // no of cards in the queue times the width of each card would result in a container fit enough for all of them
}

代码解释

在鼠标指针中移动时,将创建第一张卡片的克隆,并将其附加到卡片集合的末尾。此外,当您将鼠标移出悬停区域时,原始的.card (之前克隆的)将从队列的头上移除-因此,会产生循环效应。

不过,真正的诀窍是使用updateWidth函数。每次鼠标进入.container时,.card的直系亲属(即.cards div)的宽度都会被更新,这样.cards div就足够宽,可以容纳所有的.card,因此,确保每一张卡片在完成翻译动画时互相推送并保持在一行中。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/33412192

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档