【swellカスタマイズ】javascript/cssだけで変な動きのあるページを作る
SWELL MotionMaster: Scroll Spy & CSS Animator
エラそうな名前のSWELL専用の野良プラグイン作ってみました。
この下の方にある記事内のソースとかCSSをコピペするのがめんどくさい人はプラグインで。
まだjs圧縮とかしてないのでソースみたい人はどうぞ笑
私のBLOGの目次見てていただいた通り、スクロールに追従して見出しが反転して現在どこにいるかわかります。俗にいうスクロール・スパイって奴です。
SWELLの出力可能な目次に全て対応してます。
ついでにこの下の記事にあるCSSアニメーションも一緒に動くようにjavascript作りました。
このプラグインをインストールしていただければスクロールスパイと下で説明しているCSSアニメーションが動きます。
使い方は記事を読んでください。
ちなみにCSSアニメーションの機能ははcocoon他のテーマでも多分動くはずなのでその目的で使っていただいてもOKです。
cocoonで動かしている様子。
インストールの仕方
一般的なプラグインのアップロード方式のインストールで可能です。
プラグインのページにプラグインのアップロードがありますので上でダウンロードしたzipファイルをそのままアップロードするだけです。
ファイルを選択でローカルにダウンロードしてあるswell-motionmaster.zipを選択して今すぐインストールして
プラグインを有効化すれば終わりです。
注意:
外観→カスタマイズ→投稿・固定ページ→目次 の中の設定で どの階層の見出しまで抽出するか を h5にしてください。
スクロールスパイの目次の反転表示の色を変えたい人
設定画面は無いので
プラグイン→プラグインファイルエディターを選択していただいて(警告でますが無視してOK)
右上にある編集するプラグインを選択から
SWELL MotionMaster: Scroll Spy & CSS Animator を選択してからassetsの中にある mlabo.cssの最初の行に反転用のCSSがあるのでそこを直接修正してください。
- color:反転時の文字色(デフォルト黒文字)
- background-color:反転時のバックグラウンドカラー(デフォルト薄いオレンジ)
- font-weight: 文字の太さ(normal,boldなど)(デフォルト太字)
以下の記事は上記プラグインを使わずに自分で直接実装したい人用の記事になりますが
実際のエフェクト効果のサンプルにもなってますので適当に上下スクロールして効果を確認してみてください。
このBLOGは諸々実験する目的で稼働しているのでこのプラグインをインストールしてません笑
以下を参考に直接記述していただいてもこのプラグインをインストールしていただいても直接記述していただいてもどちらも同じ動作するのがわかります。
javascriptとcssだけで動きます jQueryは使いません。
やろうと思えばどの部分にもCSSで手軽に装飾できるのが楽しいSWELL
エフェクトが効く部分はゆっくりとスクロールするとエフェクトが見えませんので
その場合はスクロールバックすると再度エフェクトの確認ができます。
ほぼ全てのブロックと単独行に自在に適用可能
なんでもできるぜ
preタグでコード表示の部分
@font-face {
font-family: 'icomoon';
src:url('/wp-content/themes/swell/assets/fonts/icomoon.ttf?7ojy2d') format('embedded-truetype'),
url('/wp-content/themes/swell/assets/fonts/icomoon.ttf') format('truetype'),
url('/wp-content/themes/swell/assets/fonts/icomoon.woff') format('woff'),
url('/wp-content/themes/swell/assets/fonts/icomoon.svg') format('svg');
font-weight: normal;
font-style: normal;
font-display: swap;
}
画像ギャラリーの一枚一枚にも個別で
つくりは簡単です。
こんな感じ
slideview | 初期化 class定義 (必ず宣言) |
UU-MOVE,tsU | 上から下に |
DD-MOVE,tsD | 下から上に |
LL-MOVE,tsL | 左から右に |
RR-MOVE,tsR | 右から左に |
FF-MOVE | 360度クルリと回転する |
MFADE,ofade | スライドせずにふわっと出現する |
border | ボーダーアニメーション。指定場所の中心から左右に伸びるラインを引く |
borderl | 同上。指定場所の左端から伸びるラインを引く |
INBK | border*のライン幅を文字列と同等にするならこれを一緒に宣言(display: inline-block;) |
FLAT-MOVE | 中心から下に向かって回転 |
FLAT-TOP-MOVE | 中心から上に向かって回転 |
tsU,tsD,tsL,tsR,ofadeについて
これは何かと言いますと具体的にはスクロールに追従せずに即効果を出したいシーンで使います。
私のTOPページをみていただくとわかります。
このページ先頭付近にあるTAB付きのメニュー(New computer blog life)の各TABをクリックしたら意味がわかると思います。 ここではtsD,tsL,tsR,ofadeを各TABの追加cssクラスに宣言しています。
slideview と **-MOVEまたは border* の各classを組み合わせて宣言します。
宣言する順番はどちらが先でも構いません。必ずセットで宣言を。
**-MOVE と border は 併用可能。
**-MOVEは複数記述しても1番最後のみ有効
使用するCSS
外観>テーマファイルエディターでも カスタマイズ>追加CSSでも好きな方にコピペしてください。
/*スクロールスパイで利用*/
a.p-toc__link.active, a.p-toc__link:hover {
color:white;
background-color:black;
font-weight:bold;
}
/* MOVE FADE */
.slideview {
opacity: 0;
}
.slideview.on {
opacity: 1;
}
.LL-MOVE.on {
animation: slideInL forwards 2s;
}
.RR-MOVE.on {
animation: slideInR forwards 2s;
}
.UU-MOVE.on {
animation: slideInU forwards 2s;
}
.DD-MOVE.on {
animation: slideInD forwards 2s;
}
.MFADE.on {
animation: fade forwards 4s;
}
.ofade {
animation: fade forwards 1s;
}
.FLAT-MOVE {
transform-origin: center bottom;
transform: rotateX(-90deg);
}
.FLAT-MOVE.on {
transition: all 1s ease-in-out;
transform: rotateX(0deg);
}
.FLAT-TOP-MOVE {
transform-origin: center top;
transform: rotateX(-90deg);
}
.FLAT-TOP-MOVE.on {
transition: all 3s ease-in-out;
transform: rotateX(0deg);
}
.FF-MOVE.on {
transition: all 1s ease-in-out;
transform: rotate(360deg);
}
@keyframes fade {
0% {
opacity: 0;
}
100% {
opacity: 1;
}
}
.tsL {
animation: slideInL forwards 0.5s;
}
@keyframes slideInL {
0% {
opacity: 0;
transform: translateX(-140px);
}
100% {
opacity: 1;
transform: translateX(0);
}
}
.tsR {
animation: slideInR forwards 0.5s;
}
.tsRR {
animation: slideInR forwards 2s;
}
@keyframes slideInR {
0% {
opacity: 0;
transform: translateX(140px);
}
100% {
opacity: 1;
transform: translateX(0);
}
}
.tsU {
animation: slideInU forwards 0.5s;
}
@keyframes slideInU {
0% {
opacity: 0;
transform: translateY(-140px);
}
100% {
opacity: 1;
transform: translateY(0);
}
}
.tsD {
animation: slideInD forwards 0.5s;
}
@keyframes slideInD {
0% {
opacity: 0;
transform: translateY(140px);
}
100% {
opacity: 1;
transform: translateY(0);
}
}
.INBK {
display: inline-block;
}
.border {
position: relative;
}
.borderl {
position: relative;
}
.borderl.on {
/* 追加のスタイルプロパティ */
}
.borderl.on:before {
content: '';
position: absolute;
left: 0;
bottom: 0;
width: 0;
border-bottom: solid 2px #0f6aaa;
animation: border_anim 2s linear forwards;
}
.border.on:before {
opacity: 1;
content: '';
position: absolute;
left: 50%;
bottom: 0;
width: 0;
border-bottom: solid 2px #0f6aaa;
transform: translateX(-50%);
animation: border_anim 2s linear forwards;
}
@keyframes border_anim {
0% {
width: 0%;
}
100% {
width: 100%;
}
}
CSSアニメーション仕様書
一般的な説明
このCSSコードは、ウェブページ上のさまざまな要素に対する多様なアニメーションと遷移を提供することを目的として設計されています。これらのアニメーションには、異なる方向からのスライドイン(左、右、上、下)、フェードイン、回転、およびボーダーアニメーションが含まれます。
アニメーションの詳細
スライドインアニメーション
- 左からのスライドイン(
.LL-MOVE.on
,.tsL
) - 右からのスライドイン(
.RR-MOVE.on
,.tsR
,.tsRR
) - 上からのスライドイン(
.UU-MOVE.on
,.tsU
) - 下からのスライドイン(
.DD-MOVE.on
,.tsD
)
フェードインアニメーション
- フェードイン(
.MFADE.on
,.ofade
,@keyframes fade
)
回転アニメーション
- 360度回転(
.FF-MOVE.on
)
ボーダーアニメーション
- ボーダーアニメーション(
.border.on:before
,.borderl.on:before
,@keyframes border_anim
)
その他のアニメーション
- 中心から下に向かって回転(
.FLAT-MOVE
,.FLAT-MOVE.on
) - 中心から上に向かって回転(
.FLAT-TOP-MOVE
,.FLAT-TOP-MOVE.on
)
以上がこのCSSコードの主な機能となります。
使用するjavascript
カスタマイズ>高度な設定>bodyタグ終了直前に出力するコード にそのまま貼り付けてください。
SWELLのjavascript記述はページごとに読み込ませる方法と
カスタマイズ>高度な設定で全体的に読み込ませる
方法と2種類あります。
個別にjsファイルを作っておいてそれを読み込ませたい方はこちら↓
カスタマイズ>高度な設定で全体的に読み込ませる場合は
以下のソースをそのままコピペでOKですが
ページ毎に読み込ませる(ページ下部のJS記入する部分)場合の注意
ページごとの記載はデフォルトは 先頭と最下部のscriptタグが自動で付加されますので
それを削ったものをコピペしてください。
めんどくさい方はそのままコピペしても良いのですが
その際は必ずその下部にあるチェックマークをお忘れなく。
このCSSとjavascriptのBLOGへの実装方法の考え方
cssの場合は
外観>テーマファイルエディター | 恒久的に使うならこっちに記載 |
またはカスタマイズ>追加CSS | 恒久的に使うならこっち記載その2 |
個別ページの下部のCSS記載欄 | 一時的にテストもしくはそのページだけしか使わないならこっち |
javascriptの場合は
カスタマイズ>高度な設定 | 恒久的に使うならこっち記載 |
個別ページの下部のJS記載欄 | 一時的にテストもしくはそのページだけしか使わないならこっち |
いずれにコピペしても正常に動作することを確認してます。
現在プラグイン化されたものと同じソースです。座標抽出を共通化してスクロールスパイとエフェクトを同時に制御するようにいたしました。
<script>
//scrool spy and .slideview use
document.addEventListener('DOMContentLoaded', function() {
const sview = document.querySelectorAll('.slideview, .swl-format-1, .swl-format-2');
const sections = Array.from(document.querySelectorAll('h2, h3, h4, h5'));
let adj = window.innerHeight * 0.1;
let rafId = null;
let lastScrollTop = 0;
function getTopPositions(elements) {
return Array.from(elements, el => el.getBoundingClientRect().top + window.pageYOffset);
}
let svTop = getTopPositions(sview);
let sectionsTop = getTopPositions(sections);
function updateAdjAndSvAndSectionsTop() {
adj = window.innerHeight * 0.1;
svTop = getTopPositions(sview);
sectionsTop = getTopPositions(sections);
}
window.addEventListener('resize', updateAdjAndSvAndSectionsTop);
function toggleActiveClass(links, isActive) {
links.forEach(link => {
if (isActive) {
link.classList.add('active');
} else {
link.classList.remove('active');
}
});
}
function handleScroll() {
if (rafId) {
return;
}
rafId = requestAnimationFrame(() => {
const scrollPos = document.documentElement.scrollTop || document.body.scrollTop;
if (Math.abs(scrollPos - lastScrollTop) < 1) {
rafId = null;
return;
}
lastScrollTop = scrollPos;
sections.forEach((section, i) => {
const navLinks = document.querySelectorAll(`a[href="#${section.id}"].p-toc__link`);
const isActive = scrollPos + window.innerHeight - adj >= sectionsTop[i] && (i === sections.length - 1 || scrollPos + window.innerHeight - adj < sectionsTop[i + 1]);
toggleActiveClass(navLinks, isActive);
});
sview.forEach((el, i) => {
if (scrollPos + window.innerHeight - adj > svTop[i]) {
el.classList.add('on');
} else {
el.classList.remove('on');
}
});
rafId = null;
});
}
window.addEventListener('scroll', handleScroll);
updateAdjAndSvAndSectionsTop();
const observer = new MutationObserver((mutationsList) => {
for (let mutation of mutationsList) {
if (mutation.type === 'childList') {
handleScroll();
}
}
});
const tocElements = document.querySelectorAll('.toc');
tocElements.forEach(toc => observer.observe(toc, { childList: true, subtree: true }));
});
</script>
仕様書
概要
このコードは、ウェブページにスクロールスパイとスライドビューの機能を追加します。ユーザーがページをスクロールすると、特定のセクションや要素が表示される際に対応するナビゲーションリンクがアクティブになり、スライドビュー要素が表示されるようにします。
主な機能
- ウィンドウサイズの変更: ウィンドウサイズが変更されると、要素の位置情報を更新します。
- セクションのアクティブ切り替え: ページをスクロールする際に特定のセクションが表示されるようになると、関連するナビゲーションリンクにアクティブクラスを追加・削除します。
- スライドビュー要素の表示: 特定の位置までスクロールすると、スライドビュー要素に
on
クラスを追加して表示します。 - MutationObserverの使用: ページ内の特定の要素(
.toc
)の変化を監視し、変更があるたびにスクロール処理を実行します。
主な変数と関数
- 変数
sview
: スライドビュー要素を格納するコレクションです。sections
: 対象の見出し要素(h2, h3, h4, h5)の配列です。adj
: 要素の表示位置を調整するための値です。rafId
: requestAnimationFrameのIDです。
- 関数
getTopPositions
: 要素の上端の位置を取得します。updateAdjAndSvAndSectionsTop
: ウィンドウサイズの変更時に変数を更新します。toggleActiveClass
: ナビゲーションリンクのアクティブ状態を切り替えます。handleScroll
: スクロールイベントハンドラーで、スクロール位置に基づいて上記の機能を実行します。
使い方
このコードを対象とするHTMLページに追加するだけで、上記の機能が実現できます。必要なクラス名とIDを適切に設定してください。
動作の意味としては目的の領域に画面が達したらadj分オフセットした位置にからエフェクト発動
指定のclassにonまたはactive を追加してそのエフェクト仕込んだclassを発動させる的な動作してます。
教科書に載っているようなclassに名称追加して新しいclassを参照できるようにしようってやつです。
領域から外れると(バックスクロールなど)on/activeを削除するのでまた元classで初期化されて
再度領域に達すると同じように繰り返しエフェクトが可能。
意味わからなくてもコピペして使えると思います。
このjavascriptとcssの定義を応用すればスクロールアクションに対する任意のCSS発火が
色々とできると思います。
SWELLのブロックエディターに応用する方法
SWELLのエディター設定にカスタム書式ってあるの知ってますか?
1番上ででダウンロードした野良プラグインをインストールした状態で
以下の設定をしておくとSWELLブロックエディター上で
文字の一部部分に下線のアニメーションを追加でます。←こんな感じに
この画面からもう少し下までスクロールするとこんな画面で設定できます。
内容は以下のように。
.swl-format-1{
display: inline-block;
font-weight:bold;
}
.swl-format-2{
display: inline-block;
position: relative;
font-weight:bold;
}
.swl-format-2.on:before {
opacity: 1;
content: '';
position: absolute;
left: 50%;
bottom: 0;
width: 0;
border-bottom: solid 2px #0f6aaa;
transform: translateX(-50%);
animation: underline_anim 2s forwards;
}
@keyframes underline_anim {
0% {
width: 0;
}
100% {
width: 100%;
}
}
使い方はブロックエディタのツールバーのSWELLアイコンの中に追加されたコマンドがあるので
アニメーションを適用させたい部分をマウスの左クリックで範囲指定して「下動ライン」を選択するだけです。