素のJavaScriptでjQueryのトグルメソッドを再現します。
アニメーションはCSSで行うので処理も軽いかも…?
サンプル
const toggleBtn1 = document.querySelector('.toggle-btn1');
const targetEl1 = document.querySelector('.target1');
toggleBtn1.addEventListener('click', () => {
slideToggle(targetEl1);
});
const toggelBtn2 = document.querySelector('.toggle-btn2');
const targetEl2 = document.querySelector('.target2');
toggelBtn2.addEventListener('click', () => {
slideToggle(targetEl2, 2000);
});
使い方
slideToggleのターゲットにする要素全てに「slide-toggle」クラスを付与します。
後は、関数「slideToggle(ターゲット, 時間)」でメソッドの様に利用できます。
CSS
.slide-toggle {
position: absolute;
visibility: hidden;
overflow: hidden;
}
.slide-toggle.st-open {
position: relative;
visibility: visible;
}
JavaScript
const slideSpeed = '400';
const slideToggleElement = document.querySelectorAll('.slide-toggle');
slideToggleElement.forEach(el => {
el.addEventListener('transitionend', function () {
this.style.height = 'auto';
this.classList.remove('st-moving');
if (this.classList.contains('st-close')) {
this.style.transition = '0s';
this.classList.remove('st-close');
this.classList.remove('st-open');
}
});
});
function slideToggle(target, speed) {
if (!speed) {
speed = slideSpeed;
}
target.style.transition = speed + 'ms';
if (target.classList.contains('st-moving') === false) {
target.classList.add('st-moving');
height = target.clientHeight;
if (target.classList.contains('st-open')) {
target.classList.add('st-close');
target.style.height = height + 'px';
setTimeout(function () {
target.style.height = 0;
});
} else {
target.style.height = 0;
target.classList.add('st-open');
setTimeout(function () {
target.style.height = height + 'px';
});
}
}
}
簡単な解説
const slideSpeed = '400';
const slideToggleElement = document.querySelectorAll('.slide-toggle');
- 基本スピードと要素を取得
function slideToggle(target, speed) {
if (target.classList.contains('st-moving') === false) {
if (!speed) {
speed = slideSpeed;
}
target.style.transition = speed + 'ms';
target.classList.add('st-moving');
height = target.clientHeight;
if (target.classList.contains('st-open')) {
target.classList.add('st-close');
target.style.height = height + 'px';
setTimeout(function () {
target.style.height = 0;
});
} else {
target.style.height = 0;
target.classList.add('st-open');
setTimeout(function () {
target.style.height = height + 'px';
});
}
}
}
- 「st-moving」が付いている場合は何もしない。
動作開始で付与、動作完了で取るクラス。
アニメーション中に動作しないようにするため。 - 速度が設定されているかどうかを確認しtransitionに設定
- 現在の高さを変数に入れてから開閉で条件分岐
- 開く時はheightを0にし「st-open」を付与
その後変数に保存した高さを設定することでCSSでアニメーション
(高さ取得のタイミングでは要素はabsoluteのため取得できる) - 閉じるときは「st-close」を付与し変数heightを付与
その後高さ0を指定することでCSSでアニメーション
slideToggleElement.forEach(el => {
el.addEventListener('transitionend', function () {
this.style.height = 'auto';
this.classList.remove('st-moving');
if (this.classList.contains('st-close')) {
this.style.transition = '0s';
this.classList.remove('st-close');
this.classList.remove('st-open');
}
});
});
各要素にトランジションが終わった時に以下の処理
- heightをautoに(レスポンシブ時に固定されないよう)
- 「st-moving」を外す
さらに「st-close」がある場合(閉じる時のクラス)
- transitionを0に(0にしないと次回アニメーションしてしまう)
- 「st-close」「st-open」を外す
完成!
以上で完成です。
次回以降でこれを応用したQ&Aを作ります。