designsupply.llc
  • aboutabout
  • servicesservices
  • worksworks
  • mediamedia
  • contactcontact
  • homeサイトトップ
  • about会社概要
  • services業務内容
  • works実績紹介
  • mediaメディア
  • contactお問い合わせ
ja/

media

メディア

  1. サイトトップ
  2. メディア
  3. プログラミングの記事
  4. jQueryでよく使うメソッドをネイティブのJavaScriptに置き換えてみる#5:UI・アニメーション

jQueryでよく使うメソッドをネイティブのJavaScriptに置き換えてみる#5:UI・アニメーション

  • 2020.10.09
  • プログラミング
  • jQuery
Updated: 2020.10.09
jQueryにはDOMの操作だけでなく、UIパーツの実装などに便利なアニメーションなどの動きを表現できるメソッドもたくさん用意されています。第5回目となる今回はそのようなメソッドをネイティブのJavaScriptに置き換えていきたいと思います。実際にこれらのメソッドはネイティブのJavaScriptで実装するとなるとかなり大変でした、、逆にjQueryに依存しがちな処理でもあると言えますね。そのためにも置き換えの方法を知っておいても損はないですね。  
プロパティを指定時間で変更:animate()
特定のCSSのプロパティなどを指定した時間をかけて変更、あるいは設定するメソッドが「animate()」です。これを使うとその名の通り指定したプロパティへアニメーションをつけながら変化させることができます。引数には順に「CSSプロパティ」「変化の時間」「イージングの設定」と指定していきます。 【jQuery】
$("#hoge").animate(
  { 'fontSize': 40 },
  2000,
  'linear'
);
  ネイティブのJavaScriptを使う場合には、簡単な方法として「CSSのtransitionプロパティ」を使う方法があります。これを使うことで短いコードで手軽に、且つより自然に見せることができます。ただし、transitionに対応していないプロパティに関してはアニメーションをつけることができません。そんな場合には「setInterval」を使って一定時間ごとに徐々に変化を与えていく方法が使えます。 【JavaScript】
// CSSのtransitionを使う場合
const element = document.getElementById('hoge');
element.style.cssText = 'font-size: 40px; transition: font-size 2s linear 0s;'

// setIntervalを使う場合
const element = document.getElementById('hoge');
const duration = 2000;
const begin = 16;
const finish = 40;
const startTime = new Date().getTime();
const stopTime = startTime + duration;
const timer = setInterval(() => {
  let currentTime = new Date().getTime();
  let progress = (currentTime - startTime) / duration
  let zoom = (finish - begin) * progress
  element.style.fontSize = `${begin + zoom}px`;
  current = new Date().getTime();
  if(1 < progress) {
    clearInterval(timer);
  }
}, 10);
  setIntervalを使う場合には、設定時間と経過時間の割合を進捗率として算出する必要があります。この進捗率に合わせて、CSSプロパティの値を徐々に変化させていくような設定をします。進捗率の算出方法ですが、「new Date()」を使って開始時刻と現在時刻から経過時間を割り出し、それを設定時間で割ることで算出することができます。そして進捗率が100%を超えた時点で「clearInterval」を使って一定時間の繰り返し処理を終了させます。  
フェードインでの表示・非表示:fadeIn() / fadeOut()
特定要素の透明度を徐々に変化させ、表示・非表示を切り替えるメソッドが「fadeIn()」と「fadeOut()」です。fadeIn()は徐々に表示させ、fadeOut()は徐々に非表示にさせることができます。引数には設定時間を入れることでスピードを調整できます。 【jQuery】
$("#hoge").fadeIn(2000);
$("#hoge").fadeOut(2000);
  ネイティブのJavaScriptを使う場合でも先ほどの、animate()と同じく設定時間と経過時間の割合から進捗率を算出する方法を使います。今回の場合には表示・非表示を切り替えるため、fadeIn()の場合にはデフォルトのスタイルとして、displayプロパティとopacityプロパティを設定して非表示にしておく必要があります。 【JavaScript】
// fadeIn
const element = document.getElementById('hoge');
element.style.cssText = 'display: block; opacity: 0;'
const duration = 2000;
const start = new Date().getTime();
const stop = start + duration;
const timer = setInterval(() => {
  let current = new Date().getTime();
  let progress = (current - start) / duration
  element.style.opacity = 0 + progress;
  current = new Date().getTime();
  if(1 < progress) {
    clearInterval(timer);
  }
}, 10);

// fadeOut
const element = document.getElementById('hoge');
const duration = 2000;
const start = new Date().getTime();
const stop = start + duration;
const timer = setInterval(() => {
  let current = new Date().getTime();
  let progress = (current - start) / duration
  element.style.opacity = 1 - progress;
  current = new Date().getTime();
  if(1 < progress) {
    clearInterval(timer);
    element.style.display = 'none';
  }
}, 10);
  fadeIn()、fadeOut()では、時間経過に合わせてopacityの値が変わり、fadeOut()の場合は設定時間になるとdisplayプロパティが切り替わるという仕組みになっています。この切り替わるタイミングは進捗率が100%を超えた時点になるので、clearIntervalの実行直後に行います。  
スライドしながらの表示・非表示:slideDown() / slideUp()
要素の高さがスライドするように変化するアニメーションを伴って表示・非表示を切り替えるのが「slideDown()」と「slideUp()」メソッドです。これもよく使われるメソッドではないでしょうか。引数には同じく設定時間を入れることでスピードを調整できます。 【jQuery】
$("#hoge").slideDown(2000);
$("#hoge").slideUp(2000);
  このメソッドの置き換えはかなり大変です。実際、jQueryの処理をデベロッパーツールで確認してみると、paddingとmarginとheightの高さが徐々に変化するという複雑なもので、そのためにはまず要素自体の「上下paddingを除いた高さ」「上下paddingの値」「上下marginの値」をそれぞれ取得する必要があります。かなり試行錯誤を繰り返したのですが、こちらのサイト(脱jQuery .fadeIn() .fadeOut() .slideUp() .slideDown())を参考になんとか再現することができました。   まず、slideDown()の場合ですがこれはかなり大変で、要素の高さと上下のpaddingとmarginの値を取得する必要があるのですが、初期状態で非表示となっているのでそのままでは取得できません。そのため「visibility」プロパティを使って非表示にし、高さの値を取れるようにします。その場合には高さの分だけレイアウトスペースが空いてしまうので「position」プロパティを使って表示場所を調整しレイアウトに影響が出ないようにします。 【JavaScript】
// slideDown
const element = document.getElementById('hoge');
const computedStyle = {
  paddingTop: 0,
  paddingBottom: 0,
  marginTop: 0,
  marginBottom: 0,
  height: 0
}
const init = () => {
  element.style.cssText = 'overflow: hidden; display: block; visibility: hidden; position: absolute;';
  computedStyle.paddingTop = parseFloat(window.getComputedStyle(element).getPropertyValue('padding-top'));
  computedStyle.paddingBottom = parseFloat(window.getComputedStyle(element).getPropertyValue('padding-bottom'));
  computedStyle.marginTop = parseFloat(window.getComputedStyle(element).getPropertyValue('margin-top'));
  computedStyle.marginBottom = parseFloat(window.getComputedStyle(element).getPropertyValue('margin-bottom'));
  computedStyle.height = element.clientHeight - parseFloat(window.getComputedStyle(element).getPropertyValue('padding-top')) - parseFloat(window.getComputedStyle(element).getPropertyValue('padding-bottom'));
}
const ready = () => {
  element.style.cssText = 'overflow: hidden; display: block; visibility: visible; position: static; height: 0; margin-top: 0; margin-bottom: 0; padding-top: 0; padding-bottom: 0;';
}
const duration = 2000;
const start = new Date().getTime();
const stop = start + duration;
const run = () => {
  return new Promise((resolve, reject) => {
    init();
    resolve();
  })
  .then(() => {
    return new Promise((resolve, reject) => {
      ready();
      resolve();
    })
  })
  .then(() => {
    return new Promise((resolve, reject) => {
      const timer = setInterval(() => {
        let current = new Date().getTime();
        let progress = (current - start) / duration
        element.style.paddingTop = `${computedStyle.paddingTop * (0 + progress)}px`;
        element.style.paddingBottom = `${computedStyle.paddingBottom * (0 + progress)}px`;
        element.style.marginTop = `${computedStyle.marginTop * (0 + progress)}px`;
        element.style.marginBottom = `${computedStyle.marginBottom * (0 + progress)}px`;
        element.style.height = `${computedStyle.height * (0 + progress)}px`;
        current = new Date().getTime();
        if(1 < progress) {
          clearInterval(timer);
        }
      }, 10);
      resolve();
    })
  })
}
run();

// slideUp
const element = document.getElementById('hoge');
element.style.overflow = 'hidden';
const computedStyle = {
  paddingTop: parseFloat(window.getComputedStyle(element).getPropertyValue('padding-top')),
  paddingBottom: parseFloat(window.getComputedStyle(element).getPropertyValue('padding-bottom')),
  marginTop: parseFloat(window.getComputedStyle(element).getPropertyValue('margin-top')),
  marginBottom: parseFloat(window.getComputedStyle(element).getPropertyValue('margin-bottom')),
}
const elementHeight = element.clientHeight - computedStyle.paddingTop - computedStyle.paddingBottom;
const duration = 2000;
const start = new Date().getTime();
const stop = start + duration;
const timer = setInterval(() => {
  let current = new Date().getTime();
  let progress = (current - start) / duration
  element.style.paddingTop = `${computedStyle.paddingTop * (1 - progress)}px`;
  element.style.paddingBottom = `${computedStyle.paddingBottom * (1 - progress)}px`;
  element.style.marginTop = `${computedStyle.marginTop * (1 - progress)}px`;
  element.style.marginBottom = `${computedStyle.marginBottom * (1 - progress)}px`;
  element.style.height = `${elementHeight * (1 - progress)}px`;
  current = new Date().getTime();
  if(1 < progress) {
    clearInterval(timer);
    element.style.display = 'none';
  }
}, 10);
  あとは先ほどと同じく、設定時間と経過時間の割合から進捗率を算出する方法で徐々に、heightとpadding、marginの値を調整していきますが、まず初めに表示状態の要素の情報を取得し、そのあとに処理を始めないといけないため、最終的にPromiseを使って直列の処理とすることで動くようになりました。   slideUp()の場合はもう少しシンプルで、単純に初期表示状態の情報を取得し、時間経過と合わせて徐々に0に近づけていき、設定時間に到達すると非表示にするという処理を加える形となります。  
  全5回にわたってjQueryでよく使うメソッドをネイティブのJavaScriptに置き換えた場合のコードをまとめてきました。一つ言えることはjQueryはとても便利なライブラリであるということですね! (こちらの記事もどうぞ) ・jQueryでよく使うメソッドをネイティブのJavaScriptに置き換えてみる#1:基本的な操作 ・jQueryでよく使うメソッドをネイティブのJavaScriptに置き換えてみる#2:値の取得・設定 ・jQueryでよく使うメソッドをネイティブのJavaScriptに置き換えてみる#3:要素の走査選択・絞り込み ・jQueryでよく使うメソッドをネイティブのJavaScriptに置き換えてみる#4:要素の移動と挿入・データ通信   ただ、jQueryに依存が高くなってしまうと、別のライブラリやフレームワークに移行する場合に大変な場合もありますので、ネイティブのJavaScriptを使った方法も覚えておくといいのではないでしょうか。また今回実際にjQueryからネイティブのJavaScriptに書き換えたということでjQueyのメソッドについてはもちろんのこと、JavaScriptについてもかなり勉強になったのは良かったですね。jQueryをよく使われる場合には一度試してみてもいいのではないでしょうか。   (参考にさせて頂いたサイト) 脱jQuery .fadeIn() .fadeOut() .slideUp() .slideDown() display: none;のとき要素のサイズが取得できない

この記事を書いた人オガワ シンヤ

合同会社デザインサプライ代表兼CEO / ディレクター・ウェブデザイナー・フロントエンドエンジニアをやっています。「ウェブとデザインでヒト・モノ・サービスを繋げ新しい価値を生み出す」をコンセプトに日々奮闘中!制作中はダイエットコーラとチョコレートが欠かせないアラフォーWebクリエイター。

Sponsored Link

  • Showcase
  • Startify UI
  • Functional Gradation Generator
  • Coloooors

categories

  • WordPress(61)
  • JavaScript(49)
  • Vue.js(48)
  • CSS(46)
  • jQuery(34)
  • Nuxt.js(22)
  • Sass(21)
  • Gulp(17)
  • webpack(16)
  • PHP(14)
  • HTML(14)
  • GSAP(11)
  • React(10)
  • Vite(9)
  • Pug(9)
  • Laravel(8)
  • Cordova(8)
  • Linux(7)
  • Next.js(6)
  • Apache(5)
  • Shopify(4)
  • REST API(4)
  • Node.js(4)
  • Smarty(3)
  • Git(3)
  • JSON(3)
  • その他プログラミング(3)
  • Google Apps API(3)
  • Bootstrap(3)
  • 環境構築・システム(3)
  • TypeScript(2)
  • EJS(2)
  • RMS(2)
  • Docker(2)
  • Instagram API(2)
  • Excel VBA(2)
  • SVG(1)
  • Dart(1)
  • ECカートASP(1)
  • Markdown(1)
  • AMP(1)
  • Nginx(1)
  • XML(1)
  • shellscript(1)
  • Ruby(1)
  • MySQL(1)
  • 次の記事
  • 一覧に戻る
  • 前の記事

まだ依頼内容が決まっていなくても、ご相談ください。

課題の整理や小さな検証、UI/UX・フロントエンドの部分的な支援から始められます。

お問い合わせやご相談はこちらから

Webサイト・プロダクトの企画設計/UI・UXデザイン/フロントエンド開発合同会社デザインサプライ(DesignSupply. LLC)

Office:大阪府大阪市天王寺区清水谷町3-22
Email:info@designsupply-web.com
home
  • サイトトップ
about
  • 3つのポリシー
  • 経営理念
  • 代表・クリエイター紹介
  • 会社概要
services
  • ビジネス・プロダクト支援
  • UI/UX・フロントエンド開発支援
  • プロジェクトの進め方・支援体制
  • エデュケーション事業
works
  • 開発プロジェクト
  • クリエイティブ支援
  • 自社プロダクト
media
  • デザイン
  • プログラミング
  • マーケティング
  • Web開発
  • 写真・動画制作
contact
  • お問い合わせ
news
  • インフォメーション
privacy
  • プライバシーポリシー

WE THINK WITH YOU, DESIGN FOR PEOPLE, AND BUILD WHAT WORKS.

WE THINK WITH YOU, DESIGN FOR PEOPLE, AND BUILD WHAT WORKS.

© 2013 - 2026 DesignSupply.LLC
サイトトップへ
contact