LPで使いがちな、ページスクロールした時に、文字列が順番にアニメーションするライブラリ作ったよ

2021年7月10日

テクノロジー

eyecatch DIY Library Maker の弓削田です。 自分で作るライブラリは、人が作ったものよりも使いやすい(当たり前だろが)を、実感しているので、 やりたいことがある場合、まず仕様を考え始めるボクですが、 最近、LPを作ることにハマっていて、世の中の色々と面白いLPを見て回っています。 面白い効果などがあると、それを自分のコードでライブラリとして蓄積していっているんですが、 比較的利用頻度が高いと思われる、文字列アニメーションのツールを作ったので、ブログで紹介しておきます。

文字列アニメーションツール「text-appear」について

LPの目的は、商品などの広告や、何かしらの告知なので、伝えたいキーワードが明確になっています。 たまに、ゴチャゴチャ小さい文字が書かれているだけのページもありますが、アレ、何の意味もない効果の薄いページだという事に気がついていないのが残念ですね。 でも、効果時に文字を見せるコツとして、比較的目立つ感じの大きめの文字が、スクロールインしてきた時に、フワッと浮き上がってきて、確実に目線がそこにいくようにする、 そんな効果を毎回作っているとしんどいので、class名を書き込むだけ簡単に実装できるライブラリを作ってみました。
これがサンプルです。

ソース

(function(){ let __options = { selector : ".text-appear", target_className : "text-appear-word", appear_speed : 100 // *ms }; function MAIN(){ this.options = __options; this.event(); this.init(); this.scroll(); } MAIN.prototype.event = function(){ window.addEventListener("scroll" , this.scroll.bind(this)); window.addEventListener("resize" , this.scroll.bind(this)); }; MAIN.prototype.init = function(){ let elms = document.querySelectorAll(this.options.selector); for(let elm of elms){ this.set_split_value(elm); } }; MAIN.prototype.set_split_value = function(elm){ if(!elm || !elm.innerHTML){return;} let new_elm = document.createElement("div"); let num = 0; while(elm.innerHTML){ let delay_num = (num * this.options.appear_speed); switch(elm.firstChild.nodeType){ // element case 1: elm.style.setProperty("animation-delay" , delay_num +"ms"); new_elm.appendChild(elm.firstChild); num++; break; // text case 3: let word = elm.firstChild.textContent.slice(0,1); elm.firstChild.textContent = elm.firstChild.textContent.slice(1); // 改行コード if(word === "\n"){ let new_text = document.createTextNode(word); new_elm.appendChild(new_text); } // 文字列 else{ let span = document.createElement("span"); span.className = this.options.target_className; span.style.setProperty("animation-delay" , delay_num +"ms"); span.textContent = word; new_elm.appendChild(span); num++; } if(elm.firstChild.textContent === ""){ elm.removeChild(elm.firstChild); } break; } } elm.innerHTML = new_elm.innerHTML; elm.setAttribute("data-view","1"); }; MAIN.prototype.scroll = function(e){ var h = this.get_pageheight(); // 対象エレメントがページ表示エリアに入った場合にフラグを立てる let elms = document.querySelectorAll(this.options.selector); for(let elm of elms){ let rect = elm.getBoundingClientRect(); if(elm.getAttribute("data-anim") !== "1" // && rect.top > -rect.height +100 && rect.top > -100 && rect.top - h < -100){ elm.setAttribute("data-anim" , "1"); } else if(elm.getAttribute("data-repeat") !== "0" && elm.getAttribute("data-anim") === "1" && rect.top - h > 0){ elm.setAttribute("data-anim" , "0"); } else if(elm.getAttribute("data-repeat") !== "0" && elm.getAttribute("data-anim") === "1" && rect.top < (-rect.height)){ console.log(2); elm.setAttribute("data-anim" , "0"); } } }; MAIN.prototype.get_scroll_y = function(){ return document.scrollingElement.scrollTop; }; MAIN.prototype.get_pageheight = function(){ return window.innerHeight; }; MAIN.prototype.get_pagesize = function(){ return document.scrollingElement.scrollHeight; } switch(document.readyState){ case "complete" : new MAIN();break; default : window.addEventListener("load" , function(){new MAIN()});break; } })() :root{ --size-move-distance:50px; --anim-duration:500ms; } .text-appear{ display:none; } .text-appear[data-view="1"]{ display:block; } .text-appear, .text-appear .text-appear-word{ white-space:pre-wrap; word-break:break-all; font-size:50px; font-weight:bold; } .text-appear .text-appear-word{ display:inline-block; transform:translateY(var(--size-move-distance)); opacity:0; } .text-appear[data-anim="1"]{ border:1px solid red; } .text-appear[data-anim="1"] .text-appear-word{ animation-name : anim-text-appear; animation-duration : var(--anim-duration); animation-timing-function : ease; animation-fill-mode:forwards; } @keyframes anim-text-appear{ 0% { opacity:0; transform:translateY(var(--size-move-distance)); } 70%{ transform:translateY(-5px); } 100% { opacity:1; transform:translateY(0); } } <div class="sample text-appear">これがサンプルです。</div>

使い方

h1タグや、タイトル、ラベルなど、大きめの文字列を表示しているタグに、"text-appear"というクラス名を付与するだけの簡単実装です。 文字サイズや、色、など、サイトによって異なる装飾は、それぞれのcssで記述してもらっても大丈夫です。 ただし、transformは使わないようにしてくださいね。 あと、疑似要素や、アニメーション文字の中にエレメントが含まれていると、うまく動作しない場合があるので、使う際はご注意ください。 他のサイトなどを見ていると、1文字ずつspanタグなどに書き込んで実装しているようですが、 このライブラリを使うと、ただ書かれている文字を、自動的にspanタグに挿入して、効果が表示できます。 そのため、例えばcssで、h1に文字設定を書いている場合は、.h1 span という風に、小階層に継承して貰う必要があるので、実装して見て確認しながらcss設定を行ってください。 また、スクロールインした際に発動するイベントになっていますが、window(htmlタグ)に対して発動するようになっているので、 ページの仕組みで、bodyタグや、任意の要素スクロールでの発動タイミングにしたい場合は、jsの14行目のwindowを対象エレメントに書き換えてご使用ください。 あと、これを参考にしたサイトも、他のサイトも、アニメーションは1度きりのものがほとんどだったんですが、スクロールの上下それぞれで発動するようにして、 スクロールアウトすると、自動的に、文字を消すようにしています。

最後に

LPは見た目のデザインも重要ですが、こうした、プログラミングによる効果も非常に重要な要素という事を理解できました。 そして、実際にブログでサンプル表示をしてみると、色々と開発時に見えていなかった事も見えてきたので、ブログ掲載(実稼働)必須ですね。 他にも面白そうな機能をライブラリにして、LPライブラリ集などというものを自分用に作ろうと目論んでいるユゲタでした。 また、新しいのができたら、ブログで紹介しますね。

人気の投稿

このブログを検索

ごあいさつ

このWebサイトは、独自思考で我が道を行くユゲタの少し尖った思考のTechブログです。 毎日興味がどんどん切り替わるので、テーマはマルチになっています。 もしかしたらアイデアに困っている人の助けになるかもしれません。

ブログ アーカイブ