2016-11-28 25 views
1

我能找到的最接近的線程是this one here但是我在執行這個時遇到了麻煩。解釋jQuery transitionend停止CSS動畫被中斷

的設置(想法表示歡迎)

我做了一個jQuery滑塊 - 這個特殊的滑塊將具有一個單頁上幾個滑塊實例,以及每個滑塊內的人數不詳的兒童(」卡片「,每個」幻燈片「呈現4張可見卡片) - 因爲我已經實現的代碼比較了容器本身的偏移量,孩子的數量,並且在內部包含卡片容器上使用CSS過渡來滑過所述偏移量同時確保它不會過度。

這是一個原型,所以我有幾個替代版本供與我合作的人查看,但我更感興趣的是我所做的「按鈕」變體。

我有什麼在單頁上工作

  • 多個滑塊
  • 的「卡」,有多少是在一個容器
  • 基於正確數量的跨越滑動可以正確檢測容器偏移
  • 動態確定開始和結束值以確保在滑動時不會出現「過沖」

問題

目前用戶可以通過「垃圾郵件點擊」按鈕,中斷本CSS過渡(500毫秒)過早地開始一個新的CSS3過渡,使滑塊是完全脫離的位置:(

潛在的解決方案

它好像jQuery的transitionend屬性是我以後(在jQuery中完成CSS轉換時檢測的能力),但是我完全不確定實現!

在我想學習的解釋中有很多術語術語,但它們好像循環地指向更多的術語文檔或截斷的論壇答覆。只是想知道是否有人可以幫助解釋我做錯了什麼,以及原因。

注意事項

我完全相信被告誡,叫愚蠢等等 - 我主要是一個自學成才的編碼器 - 完全自學成才jQuery中。我來自平面設計(Hiss!Scowl!)和計算機科學半學位。禮貌和簡單的解釋(附帶鏈接到適當的手動點)總是感激!雖然完整的代碼如下,如前所述混亂的我特別的一點是「transitionend」這我試圖以下列方式使用:

$(cardsToShift).on('transitionend webkitTransitionEnd oTransitionEnd', function() { 
     cardsToShift.css("margin-left",margin); 
    }); 

凡卡轉移是我轉移l所有卡的容器/ R通過我預先計算的「邊距」變量。

我在上面這段代碼背後的邏輯是「這個容器在轉換髮生時不會發生移位,因爲我已經將它包裝在transition end行中,並且 - 沒有發生轉換 - 它應該執行內部代碼。如果轉換發生,那麼該代碼將不會執行,用戶需要再次單擊「」。 (注意,可能會有一些輕微的語法問題,可以很容易地清理它們,但我已經被剪切並粘貼成一個瘋狂的東西 - 就像這個片段大部分解釋的那樣)。

預先感謝您(目前正在退出一段時間,但會盡快回復並提供更多信息)。

HTML

<!doctype html> 
<html> 
<head> 
<meta charset="UTF-8"> 
<title>Untitled Document</title> 
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script> 
<link href="style.css" rel="stylesheet" type="text/css" /> 
</head> 

<body> 
    <div class="section"> 
     <div class="card-container" id="fixed-long"> 
      <div class="card-set-buttons"> 
       <div class="card">card 1</div> 
       <div class="card">card 2</div> 
       <div class="card">card 3</div> 
       <div class="card">card 4</div> 
       <div class="card">card 5</div> 
       <div class="card">card 6</div> 
       <div class="card">card 7</div> 
       <div class="card">card 8</div> 
      </div> 
     </div> 
    </div> 
    <!-- As we have multiple sliders, I've opted for functions to be fully dynamic that work based off 
    which one the user is interacting with. The caveat to this is that there are "levels" of nesting that 
    need to be adhered to - you will notice you can set whatever class names you like in the jQuery "scripts.js" file--> 
    <div class="section alt"> 
     <div class="nav-container"> 
      <div class="set-button left" id="left-one"></div><!--LEVEL 1: The buttons must not be put in the same level as the container for cards--> 
      <div class="card-container" id="long-buttons"><!--LEVEL 2: this level needs a unique ID based on which slider is selected. This is the "viewport" or "tableau" that displays current sets of cards and serves to hide the rest--> 
       <div class="card-set-buttons"><!--LEVEL 3: necessary div class which is the "long" container holding all the cards, name what you want--> 
        <div class="card">card 1</div><!--LEVEL 4: Nothing but cards at this level, name whatever class you like--> 
        <div class="card">card 2</div> 
        <div class="card">card 3</div> 
        <div class="card">card 4</div> 
        <div class="card">card 5</div> 
        <div class="card">card 6</div> 
        <div class="card">card 7</div> 
        <div class="card">card 8</div> 
        <div class="card">card 9</div> 
        <div class="card">card 10</div> 
        <div class="card">card 11</div> 
        <div class="card">card 12</div> 
        <div class="card">card 13</div> 
       </div> 
      </div> 
      <div class="set-button right" id="right-one"></div> 
     </div> 
    </div> 
    <div class="section"> 
     <div class="card-container short" id="fixed-short"> 
      <div class="card-set-buttons"> 
       <div class="card">card 1</div> 
       <div class="card">card 2</div> 
       <div class="card">card 3</div> 
       <div class="card">card 4</div> 
       <div class="card">card 5</div> 
       <div class="card">card 6</div> 
       <div class="card">card 7</div> 
       <div class="card">card 8</div> 
       <div class="card">card 9</div> 
       <div class="card">card 10</div> 
       <div class="card">card 11</div> 
       <div class="card">card 12</div> 
       <div class="card">card 13</div> 
       <div class="card">card 14</div> 
       <div class="card">card 15</div> 
       <div class="card">card 16</div> 
      </div> 
     </div> 
    </div> 
    <div class="section alt"> 
     <div class="nav-container four"> 
      <div class="set-button left" id="left-two"></div> 
      <div class="card-container short" id="short-buttons"> 
       <div class="card-set-buttons"> 
        <div class="card">card 1</div> 
        <div class="card">card 2</div> 
        <div class="card">card 3</div> 
        <div class="card">card 4</div> 
        <div class="card">card 5</div> 
        <div class="card">card 6</div> 
        <div class="card">card 7</div> 
        <div class="card">card 8</div> 
        <div class="card">card 9</div> 
        <div class="card">card 10</div> 
        <div class="card">card 11</div> 
        <div class="card">card 12</div> 
        <div class="card">card 13</div> 
       </div> 
      </div> 
      <div class="set-button right" id="right-two"></div> 
     </div> 
    </div> 
    <script src="card-script.js" type="text/javascript"></script> 
</body> 
</html> 

CSS

@charset "UTF-8"; 
/* CSS Document */ 
/*=========== BODY ============*/ 
body 
{ 
    overflow-x:hidden; 
    max-width: 100%; 
} 

.section { 
    height: 600px; 
    width: 100%; 
    display:inline-block; 
} 

.alt 
{ 
    background:#f0f0f0; 
} 

.section:nth-child(4) 
{ 
    height: 1000px; 
} 

/*============ SHARED LAYOUT ===========*/ 
.card 
{ 
    background:#B3E9FA; 
    height: 350px; 
    width: 250px; 
    display:inline-block; 
    margin-right: 30px; 
    box-sizing:border-box; 
    padding: 0; 
} 

.card-container 
{ 
    width: 800px; 
    margin: 125px auto 0 auto; 
    height: 350px; 
    overflow-x:hidden; 
    overflow-y:hidden; 
} 

/*=========== LONG FORMAT ===========*/ 

.card-container#fixed-long 
{ 
    overflow-x:scroll; 
} 

.card-container .card:last-child 
{ 
    margin-right: 0; 
} 

/*============ SQUARE FORMAT =================*/ 

.nav-container.four 
{ 
    width: 650px; 
} 
.card-container.short 
{ 
    height: 740px; 
    margin-top: 100px; 
    margin-bottom: 100px; 
} 
.card-container#fixed-short 
{ 
    overflow-x:scroll; 
} 
.card-container#short-buttons 
{ 
    width: 530px; 
} 
.card-container#short-buttons .card,.card-container#fixed-short .card 
{ 
    margin-bottom: 30px; 
} 
.card-container#short-buttons .card:last-child 
{ 
    margin-right: 0; 
} 
.card-container.short .card-set-buttons 
{ 
    display:flex; 
    flex-flow:row wrap; 
    justify-content:flex-start; 
    align-content: flex-start; 
} 

.card-container.short .card:nth-child(4n+1),.card-container.short .card:nth-child(4n+2) 
{ 
    order: 1; 
} 
.card-container.short .card:nth-child(4n+4),.card-container.short .card:nth-child(4n+3) 
{ 
    order: 2; 
    align-self: flex-start; 
} 

/*============= SHARED BUTTON NAV ============*/ 

.card-set-buttons 
{ 
    width: 3000px; 
} 

.set-button 
{ 
    height: 200px; 
    width: 40px; 
    background:#791719; 
} 

.nav-container 
{ 
    width: 1200px; 
    margin:125px auto 0 auto; 
} 
.nav-container .card-container 
{ 
    margin: 0; 
    width: 1100px; 
    display: inline-block; 
} 

.set-button 
{ 
    display:inline-block; 
    z-index: 3; 
} 
.card-set-buttons 
{ 
    -webkit-transition: all 0.5s ease-in-out; /* Safari */ 
    transition: all 0.5s ease-in-out; 
} 

的Javascript

// JavaScript Document 

/*===================== VARIABLES =======================*/ 

/*this is the class used as the "viewing glass" or "tableau" for the cards*/ 
var cardContainerClass = ".card-container"; 

/*class used for the card*/ 
var cardClass = ".card"; 

/*class used for the left nav*/ 
var navLeft = ".set-button.left"; 

/*class used for the right nav*/ 
var navRight = ".set-button.right"; 

/*how many cards to scroll by (serves as a "minimum" that doesn't change)*/ 
var scrollAmount = 4; 

/*This set amount let's us know what offset to test against to see if a card is in position 1 or not*/ 
var positionOneOffsetX; 
var positionOneOffsetY; 

/*to keep track of toal number of cards (serves as a "maximum" that doesn't change) set on document load*/ 
var numOfCards; 

/*numeral position of next card*/ 
var nextCardNum; 

/*currentCard is the "position 1" card OBJECT. We must use relative cards to shift other cards for consistency*/ 
var currentCard; 

/*numeral position of card in 1st place*/ 
var currentCardNum = 0; 

/*scroll length amount*/ 
var shiftValue; 

/*since we need to know what slider we are dealing with - we store the object we are managing in here*/ 
var container; 


/*================= FUNCTIONS ===================*/ 

function calculateCards(containerId) 
{ 
    /*As we have many sliders on the same page - 
    We will need to dynamically calculate what we are dealing with every time 
    we use the button clicked to find it's container's ID (done previously on button click function) 
    after this, we see which card child is in first spot and set it as current*/ 

    /*get container we are dealing with*/ 
    var container = "#"+containerId; 

    /*set the container's 1st position spot based off the container itself*/ 
    positionOneOffsetX = $(container).offset().left; 
    positionOneOffsetY = $(container).offset().top; 

    console.log("containers first child offset is: "+positionOneOffsetX+" "+positionOneOffsetY); 
    console.log("containers offset is: "+$(container).offset().left+" "+$(container).offset().top); 


    $(container+" "+cardClass).each(function(){ 

     /*test if the card position matches the 1st spot, if so - set as "current" card*/ 
     if(($(this).offset().left === positionOneOffsetX) && ($(this).offset().left === positionOneOffsetX)){ 

      currentCardNum = $(this).index()+1; 
      currentCard = $(this); 

     } 
    }); 

    numOfCards = $(container+" "+cardClass).length; 
} 

function nextCards(containerId) 
{ 
    /*get container we are dealing with*/ 
    var container = "#"+containerId; 

    /*set the number of the next card to load*/ 
    nextCardNum = currentCardNum + scrollAmount; 

    adjustButtons(containerId); 

    console.log("next card: "+nextCardNum); 

    /*set the nextCard Object of the upcoming set*/ 
    var nextCard = $(container+" "+cardClass+":nth-child("+(nextCardNum)+")"); 

    /*get pixel value to shift by*/ 
    shiftValue = currentCard.offset().left - nextCard.offset().left; 

    /*make the shift*/ 
    shiftCards(containerId); 
} 

function prevCards(containerId) 
{ 
    /*get container we are dealing with*/ 
    var container = "#"+containerId; 

    /*set the number of the next card to load*/ 
    nextCardNum = currentCardNum - scrollAmount; 

    console.log("next card = "+nextCardNum); 

    adjustButtons(containerId); 

    /*set the nextCard Object of the upcoming set*/ 
    var nextCard = $(container+" "+cardClass+":nth-child("+(nextCardNum)+")"); 

    /*get pixel value to shift by*/ 
    shiftValue = currentCard.offset().left - nextCard.offset().left; 

    /*make the shift*/ 
    shiftCards(containerId); 
} 

function shiftCards(containerId) 
{ 
    /*get the container we are moving*/ 
    var container = $("#"+containerId); 

    console.log("#"+containerId); 
    /*select the container's direct div child to shift*/ 
    var cardsToShift = container.children("div"); 

    /*we will shift with margin-left value. Do some math to add or subtract our change*/ 
    var margin = parseInt(cardsToShift.css("margin-left")); 

    if(margin > $(container).offset().left){ 
     margin = $(container).offset().left + cardsToShift.offset().left; 
     currentCard = 1; 
    } 
    margin = margin + shiftValue; 

    $(cardsToShift).on('transitionend webkitTransitionEnd oTransitionEnd', function() { 
     cardsToShift.css("margin-left",margin); 
    }); 
} 

function adjustButtons(containerId) 
{ 
    /*get the container we are moving*/ 
    var container = $("#"+containerId); 
    var leftButton = $(container).siblings(navLeft); 
    var rightButton = $(container).siblings(navRight); 

    /*adjust nav buttons for various circumstances to appear as unselectable*/ 
    if(numOfCards < scrollAmount) 
    { 
     /*less cards than size of "viewport"*/ 
     rightButton.css("opacity","0.5"); 
     leftButton.css("opacity","0.5"); 

    } else if(nextCardNum > (numOfCards - scrollAmount + 1)){ 

     /*max reached but room on left - set next card to the total cards minus our scroll amount*/ 
     nextCardNum = $("#"+containerId+" "+cardClass).length; 

     console.log("max reach: "+nextCardNum); 
     rightButton.css("opacity","0.5"); 

    } else if((nextCardNum <= 1)&&(numOfCards > scrollAmount)){ 

     /*min reached but room on right - set next card to the total cards minus our scroll amount*/ 
     nextCardNum = 1; 
     leftButton.css("opacity","0.5"); 

    } else { 

     /*room either side - set all buttons to clickable*/ 
     leftButton.css("opacity","1"); 
     rightButton.css("opacity","1"); 
    } 
} 

function setWidth(cardContainerClass) 
{ 
    /*adds up all cards, sets width of container to be their total*/ 

    var container; 

    $(cardContainerClass).each(function() { 
     console.log("container here"); 
     container = $(this).prop("id"); 

     /*set total number of cards*/ 
     numOfCards = $("#"+container+" "+cardClass).length; 

     var containerWidth = 0; 

     $("#"+container+" "+cardClass).each(function(){ 
      containerWidth += parseInt($(this).width()); 
      containerWidth += parseInt($(this).css("margin-right")); 
      containerWidth += 4; 
     }); 

     /*set width of container based on cards calculated for this slider*/ 
     if ($("#"+container).hasClass("short")){ 
      /*short form*/ 
      containerWidth = containerWidth/2+100; 
      $("#"+container+" .card-set-buttons").css("width",containerWidth+"px"); 

     } else { 
      /*long form*/ 
      $("#"+container+" .card-set-buttons").css("width",containerWidth+"px");  } 

    }); 

} 


function navCall(button) 
{ 
    /*set which slider we are using by it's ID */ 
    container = $(button).siblings(cardContainerClass).prop("id"); 

    console.log("container "+container); 

    /*set some variables based on the unique container ID interacted with*/ 
    calculateCards(container); 

    if (numOfCards > 1) 
    { 
     if($(button).hasClass("left")) 
     { 
      prevCards(container);  
     } else { 
      nextCards(container); 
     } 

    } 

} 


/*==================== CALLS =====================*/ 

$(document).ready(function() { 

    /*disable left scroll on load*/ 
    $(cardContainerClass).siblings(navLeft).css("opacity","0.5"); 

    /*set width of all sliders based on cards in each one. Works for short and long form*/ 
    setWidth(cardContainerClass); 

    $(navLeft).click(function(){ 
     navCall($(this)); 
    }); 

    $(navRight).click(function(){ 
     navCall($(this)); 
    }); 

}); 

回答

0

好了 - 一個很好的業務邏輯執行環境好後p和一些咖啡我有這一個答案(像往常一樣更合理,更容易比預期的):

所以transitionend火災一旦過渡完成的東西,正在轉變 - 所以我選擇來設置一個被用作我可以尋找的「測試」的類 - 如果班級在那裏,我不會繼續進行進一步的轉換,但如果它不在那裏,我會照常進行。

在這種情況下 - 我可以申請一個CSS類......嗯,以什麼真正的 - 但重要的是,我使用的過渡CSS類transitionend並在transitionend呼叫我刪除I類先前設置 - 所以我的「禁止」類過渡完成後只刪除,過渡只能運行沒有類:

/*MOVE - note "cardsToShift" has CSS transition applied to it*/ 
cardsToShift.css("margin-left",margin); 

/*add class - while added no more moving will happen*/ 
$(container).addClass("disabled"); 

/*end of transition - removed disabled */ 
$(cardsToShift).one('webkitTransitionEnd otransitionend oTransitionEnd msTransitionEnd transitionend', function() { 

$(container).removeClass("disabled"); 

這就是魔術發生 - 你應該能夠衡量從我原來的代碼在哪裏TS這發生(在我shiftCards()函數)

關於'禁用類的單向然後充當「門衛」鏈向上從而:

/*check for the class as a gate keeper!!! The class can only be removed upon transition completion*/ 
if($("#"+container).hasClass("disabled")) 
{ 
    /*do nothing*/ 
    console.log("DOUBLE FIRE!!!"); 
} else { 
    /*else - no gatekeeper class - go ahead with transition etc. 

    /*arbitrary to problem - check to make sure there's stuff to move*/ 
    if (numOfCards > 1) 
    { 
     /*arbitrary to problem, check if left or right button was clicked*/ 
     if($(button).hasClass("left")) 
     { 
      prevCards(container);  
     } else { 
      nextCards(container); 
     } 
    } 
}