1

私は jQuery での作業に慣れているため、単純な Javascript でこれを行う方法を理解できないようです。これは私がサイトで使用する唯一のスニペットであり、ライブラリはその目的には大きすぎるため、jQuery を使用したくありません。

これはjQueryスクリプトです(動作中): http://jsfiddle.net/1jt6dhzu/2/

$(document).ready(function () {
    var whatAmI = ["Fruit", "Not a vegetable", "A phone", "Yummie in tummy"];
    var j, i = 4,
        n = whatAmI.length;

    function changeSubTitle() {
        setTimeout(function () {
            j = Math.floor(Math.random() * n - 1);
            if (j >= i) j += 1;

            $(".page-header > h2").animate({
                "opacity": 0
            }, 700, function () {
                $(this).children("span").text(whatAmI[j]);
                $(this).animate({
                    "opacity": 1
                }, 700, changeSubTitle);
            });
        }, 1000);
        i = j;
    }
    changeSubTitle();
});

そして、それをvanilla JSに交換したいと思います。ループの大部分はそのままで構いませんが、タイムアウトとコールバックを置き換える必要があります。私はIE9のサポートを必要としないので、css3トランジションでこれを行い、クラスを追加できると考えました。これは私がこれまでに持っているものです:

h2 {
    opacity: 1;
    transition: opacity 700ms;
}
h2.fade-out {
    opacity: 0;
}


document.addEventListener("DOMContentLoaded", function () {
    var whatAmI = ["Fruit", "Not a vegetable", "A phone", "Yummie in tummy"];
    var j, i = 4,
        n = whatAmI.length,
        heading = document.querySelector(".page-header > h2");

    function changeSubTitle() {
        setTimeout(function () {
            j = Math.floor(Math.random() * n - 1);
            if (j >= i) j += 1;

            heading.classList.add("fade-out");

            setTimeout(function () {
                heading.children("span")[0].innerHTML = whatAmI[j];
                heading.classList.remove("fade-out");
                setTimeout(changeSubTitle, 700);
            }, 700);
        }, 1000);
        i = j;
    }
    changeSubTitle();
});

残念ながら、これは機能しません。transitionend のイベントの timeOuts (最も外側のものを除く) を交換する方がおそらく良いでしょう。しかし、このクロスブラウザー (IE 10 以降、およびその他の主要なブラウザー) を実装する方法がわかりません。

4

1 に答える 1

2

childrenjQuery に固有の方法で実装されているメソッドを削除して、ほぼすべてのことを正しく行いました。前に投稿した内容とは逆に、JS にはchildren関数があり、HTMLCollection を返しますが、型を param として指定して要素の型に基づいてフィルター処理することはできません。すべての子ノードを返すため、子要素のインデックスを使用するか、要素のタイプを確認して、正しいノードを選択する必要があります。

この例では (そして簡単にするために)、次のように置き換えます。

heading.children("span")[0].innerHTML = whatAmI[j];

heading.children[0].innerHTML = whatAmI[j]; // since span is the first and only child

また

heading.querySelector("span").innerHTML = whatAmI[j];

期待どおりに動作するはずです。

document.addEventListener("DOMContentLoaded", function() {
  var whatAmI = ["Fruit", "Not a vegetable", "A phone", "Yummie in tummy"];
  var j, i = 2,
    n = whatAmI.length,
    heading = document.querySelector(".page-header > h2");

  function changeSubTitle() {
    setTimeout(function() {
      j = Math.floor(Math.random() * (n - 1));
      if (j >= i) j += 1;

      heading.classList.add("fade-out");

      setTimeout(function() {
        heading.querySelector("span").innerHTML = whatAmI[j];
        heading.classList.remove("fade-out");
        setTimeout(changeSubTitle, 700);
      }, 700);
      i = j;
    }, 1000);
  }
  changeSubTitle();
});
h2 {
  opacity: 1;
  transition: opacity 700ms;
}
h2.fade-out {
  opacity: 0;
}
<header class="page-header">
  <h1>Bananas</h1>

  <h2><span>A phone</span></h2>

</header>


使用 transitionend:

transitionend要素のプロパティの遷移が終了するたびにアタッチされ、起動される単一のイベント リスナーです。フェードアウトクラスの追加と削除の両方の後に発生するため、イベントが発生したときの要素の状態を手動で確認し、それに基づいて処理する必要があります。

ここでは、getComputedStyleプロパティを使用しopacityて要素の状態を確認し、フェードアウト状態にある場合はテキストを変更し、フェードアウト クラスを削除します (または) それ以外の場合は、changeSubTitle関数を再度呼び出します。

if (window.getComputedStyle(heading).opacity == 0) {
  heading.querySelector("span").innerHTML = whatAmI[j];
  heading.classList.remove("fade-out");
} else
  changeSubTitle();

document.addEventListener("DOMContentLoaded", function() {
  var whatAmI = ["Fruit", "Not a vegetable", "A phone", "Yummie in tummy"];
  var j, i = 2,
    n = whatAmI.length,
    heading = document.querySelector(".page-header > h2");

  function changeSubTitle() {
    setTimeout(function() {
      j = Math.floor(Math.random() * (n - 1));
      if (j >= i) j += 1;

      heading.classList.add("fade-out");
      i = j;
    }, 1000);
  }
  heading.addEventListener('transitionend', function() {
    if (window.getComputedStyle(heading).opacity == 0) {
      heading.querySelector("span").innerHTML = whatAmI[j];
      heading.classList.remove("fade-out");
    } else
      changeSubTitle();
  });
  changeSubTitle();
});
h2 {
  opacity: 1;
  transition: opacity 700ms;
}
h2.fade-out {
  opacity: 0;
}
<header class="page-header">
  <h1>Bananas</h1>

  <h2><span>A phone</span></h2>

</header>

または(コメントしたように)、要素に存在するクラスも確認して、それに応じて決定することもできます。これは、以前の方法に比べて簡単な方法のようです。

if (heading.classList.contains("fade-out")) {
  heading.querySelector("span").innerHTML = whatAmI[j];
  heading.classList.remove("fade-out");
} else
  changeSubTitle();

document.addEventListener("DOMContentLoaded", function() {
  var whatAmI = ["Fruit", "Not a vegetable", "A phone", "Yummie in tummy"];
  var j, i = 2,
    n = whatAmI.length,
    heading = document.querySelector(".page-header > h2");

  function changeSubTitle() {
    setTimeout(function() {
      j = Math.floor(Math.random() * (n - 1));
      if (j >= i) j += 1;

      heading.classList.add("fade-out");
      i = j;
    }, 1000);
  }
  heading.addEventListener('transitionend', function() {
    if (heading.classList.contains("fade-out")) {
      heading.querySelector("span").innerHTML = whatAmI[j];
      heading.classList.remove("fade-out");
    } else
      changeSubTitle();
  });
  changeSubTitle();
});
h2 {
  opacity: 1;
  transition: opacity 700ms;
}
h2.fade-out {
  opacity: 0;
}
<header class="page-header">
  <h1>Bananas</h1>

  <h2><span>A phone</span></h2>

</header>


上記のスニペットは両方とも、最新バージョンの Firefox、Chrome、Opera、IE11、および IE10 でテストされています (エミュレーションを使用)。Mac の最新バージョンの Safari でも動作するはずです。Windows の場合、Safari バージョンは 5.1.x で停止し、まだwebkitTransitionEndイベントのみを発生させると思います。これらのブラウザーに対応するには、この SO スレッドに記載されている方法を使用できます。

于 2015-09-06T12:41:32.530 に答える