ネイティブ js はカスタム スクロール バー コンポーネントを実装します

ネイティブ js はカスタム スクロール バー コンポーネントを実装します

この記事の例では、カスタムスクロールバーコンポーネントを実装するためのjsの具体的なコードを参考までに共有しています。具体的な内容は次のとおりです。

機能要件:

1. データ構造に従ってメニューコンテンツを作成し、ページに表示します。
2. メニューをクリックすると、対応するサブメニューの内容が表示されます。全体の内容がオーバーフローした場合は、スクロールバーが表示されます。
3. コンテンツ全体の高さが変わると、スクロール バーの高さも変わります。
4. マウスでスクロールバーをドラッグすると、コンテンツ全体が上方向にスクロールします。
5. マウスをスクロールすると、スクロールバーと全体のコンテンツもそれに応じてスクロールします。

効果を見てみましょう:

デフォルトの状態:

メニューをクリックすると、コンテンツがオーバーフローした後にスクロール バーが表示されます。

マウスでスクロール バーをドラッグすると、コンテンツ全体が上にスクロールします。

分析:

  • このケースには、アコーディオン メニューとスクロール バーの 2 つのコンポーネントが含まれているため、これらを個別に記述してから統合することができます。
  • 折りたたみメニューでは、多階層メニューの状況を考慮し、再帰を使用してこれを実行する必要があり、データ処理を容易にするためにデータの構造を統一する必要があります。
  • スクロール バーの作成には、2 つの比例方程式があります。1 つは、スクロール バーの高さ / 外側の div の高さ = 外側の div の高さ / コンテンツ全体の高さです。もう 1 つは、スクロール バーの位置 / (外側の div の高さ - スクロール バーの高さ) = コンテンツの scrollTop / (コンテンツ全体の高さ - 外側の div の高さ) です。
  • 折りたたみメニューをクリックすると、それに応じてスクロール バーの高さを設定する必要があります。折りたたみメニューは Menu.js ファイルにあり、スクロール バーの設定は ScrollBar.js ファイルにあります。スクロール バーの設定には、イベントのスローとリッスンが必要です。
  • メニューのマウス スクロール イベントを監視します。マウスがスクロールすると、スクロール ホイールの方向を判別し、スクロール バーとコンテンツの上部の値を設定します。イベントのスローと監視も必要です。

コードは以下に添付されています:

HTML 構造、データのシミュレート、外部コンテナーの作成:

<!DOCTYPE html>
<html lang="ja">
<ヘッド>
 <メタ文字セット="UTF-8">
 <meta name="viewport" content="width=デバイス幅、初期スケール=1.0">
 <title>スクロールバー</title>
</head>
<本文>
 <スクリプトタイプ="モジュール">
 './js/Utils.js' から Utils をインポートします。
 './js/Menu.js' からメニューをインポートします。
 './js/ScrollBar.js' から ScrollBar をインポートします。
 var arr = [
  {名前:"A",カテゴリ:[
  {名前:"アウディ",カテゴリ:[
   {name:"アウディ A3",href:""},
   {名前:"アウディ A4L",カテゴリ:[
   {name:"アウディ A4L-1",href:""}
   ]},
   {name:"アウディ Q3",href:""},
   {name:"アウディ Q5L",href:""},
   {name:"アウディ Q2L",href:""},
   {name:"Audi Q7 (輸入車)",href:""},
   {name:"Audi Q8 (輸入車)",href:""},
   {name:"アウディ Q7 ニューエナジー",href:""},
  ]},
  {名前:"アルファロメオ",カテゴリ:[
   {name:"ステルヴィオ(輸入品)",href:""},
   {name:"Giulia (輸入)",href:""},
  ]}
  ]},
  {名前:"B",カテゴリ:[
  {name:"メルセデス・ベンツ",カテゴリー:[
   {name:"メルセデスベンツ Cクラス",href:""},
   {name:"メルセデスベンツ Eクラス",href:""},
   {name:"メルセデスベンツ GLA クラス",href:""},
   {name:"メルセデスベンツ GLC クラス",href:""},
   {name:"メルセデスベンツ Aクラス",href:""},
   {name:"メルセデスベンツ Eクラス (輸入車)",href:""},
   {name:"メルセデスベンツ Aクラス(輸入車)",href:""},
   {name:"メルセデスベンツ Bクラス(輸入車)",href:""},
   {name:"威霆",href:""},
   {name:"メルセデスベンツ Vクラス",href:""},
  ]},
  {名前:"BMW",カテゴリー:[
   {name:"BMW 5 シリーズ",href:""},
   {name:"BMW 1 シリーズ",href:""},
   {名前:"BMW X1",href:""},
   {name:"BMW X5 (輸入車)",href:""},
   {name:"BMW X6 (輸入車)",href:""},
  ]},
  {名前:"ホンダ",カテゴリー:[
   {name:"ジンルイ",href:""},
   {name:"シビック",href:""},
   {name:"ホンダ CR-V",href:""},
   {name:"ホンダ XR-V",href:""},
   {name:"ホンダ UR-V",href:""},
   {name:"エリシオン",href:""},
   {name:"翔宇",href:""},
   {name:"INSPIRE",href:""},
   {name:"リンパイ",href:""},
   {name:"アコード",href:""},
   {name:"ビンジ",href:""},
  ]},
  {name:"ビュイック",カテゴリー:[
   {name:"カイル",href:""},
   {name:"英朗",href:""},
   {name:"威朗",href:""},
   {name:"YueLang",href:""},
   {name:"リーガル",href:""},
   {name:"ラクロス",href:""},
   {name:"アンコラ",href:""},
   {name:"Envision",href:""},
   {name:"ビュイック GL8",href:""},
   {name:"ビュイック GL6",href:""},
   {name:"VELITE",href:""},
  ]}
  ]}
 ]
 var コンテナ;
 初期化();
 関数init(){
  メニューを作成します(arr);  
  スクロールバーを作成します。
 }
  関数createMenu(arr){
  //メニューを作成します。let menu=new Menu(arr);
  //最も外側のコンテナを作成する container=Utils.createE("div",{
  幅:"235px",
  高さ:"360ピクセル",
  境界線:"1px 実線 #ccc",
  位置:"相対",
  オーバーフロー:"非表示"
  })
  menu.appendTo(コンテナ);
  Utils.appendTo(コンテナ、"本体")
 }
 関数createScrollBar(){
  //スクロールバーを作成します。let scrollBar=new ScrollBar(container);
  scrollBar.appendTo(コンテナ);
 }
 </スクリプト>
</本文>
</html>

Menu.js ファイルは、データに従って折りたたみメニュー コンテンツを作成します。

'./Utils.js' から Utils をインポートします。
デフォルトクラスMenuをエクスポートする{
 静的 SET_BAR_HEIGHT="set_bar_height";
 静的 MOUSE_WHEEL_EVENT="マウスホイールイベント";
 コンストラクタ(_list){
 this.elem = this.createElem(_list);
 }
 要素を作成します(_list){
 if(this.elem) は this.elem を返します。
 //最も外側のulコンテナを作成する let ul=Utils.createE("ul",{
  リストスタイル:"なし",
  パディング:"0px",
  マージン:"0px",
  幅:"235px",
  高さ:"360ピクセル",
  色:"#333",
  フォントサイズ:"14px",
  ユーザー選択: "なし",
  位置:"絶対"
 });
 // li リストを作成します this.createMenu(_list,ul);
 //ul はクリック イベントをリッスンします ul.addEventListener("click",e=>this.clickHandler(e));
 //ul はスクロールホイールイベントをリッスンします。Firefox は DOMMouseScroll を使用し、他のブラウザは mousewheel を使用します。
 ul.addEventListener("マウスホイール",e=>this.mouseWheelHandler(e));
 ul.addEventListener("DOMMouseScroll",e=>this.mouseWheelHandler(e));
 ul を返します。
 }
 親に追加{
 Utils.appendTo(this.elem,parent);
 }
 //第一レベルのメニューを作成する createMenu(_list,parent){
 for(let i=0;i<_list.length;i++){
  li = Utils.createE("li",{
  背景:"#f5f5f5",
  borderTop:"1px 実線 #ddd",
  行の高さ:"32px",
  },{
  data:1, //クリックして最初のレベルのメニューが折りたたまれるのを制御します})
  span = Utils.createE("span",{
  左余白:"14px",
  フォントサイズ:"18px"
  },{
  テキストコンテンツ:_list[i].name
  })
  Utils.appendTo(span,li);
  Utils.appendTo(li,親);
  //サブメニューを作成します。3 番目のパラメータはサブメニューを表示するかどうかを制御します。this.createSubMenu(_list[i].category,li,0);
 }
 }
 //サブメニューを作成する createSubMenu(_subList,_parent,_index){
 //サブメニューがない場合はジャンプします if(_subList.length===0) return;
 subUl=Utils.createE("ul",{
  リストスタイル:"なし",
  背景:"#fff",
  パディング:"0px",
  マージン:"0px",
  フォントサイズ:"14px",
  display:_index===0? "ブロック" : "なし"
 })
 for(let i=0;i<_subList.length;i++){
  subLi=Utils.createE("li",{
  パディング左:"40px",
  位置:"相対",
  カーソル:"ポインタ"
  })
  if(!_subList[i].category){
  //現在のメニューにサブメニューがない場合は、ジャンプするタグを作成します。let subA=Utils.createE("a",{
   色:"#333",
   テキストデコレーション:"なし",
   幅:"100%",
   表示:"インラインブロック"
  },{
   テキストコンテンツ:_subList[i].name、
   href:_subList[i].href || "javascript:void(0)",
   ターゲット:_subList[i].href ? "_blank" : "_self"
  })
  Utils.appendTo(subA、subLi);
  }それ以外{
  //現在のメニューにサブメニューがある場合は、span タグを作成します。let subSpan=Utils.createE("span",{
   位置:"絶対",
   左:"20px",
   上:"8px",
   境界線: "1px 実線 #ccc",
   表示: "インラインブロック",
   幅: "10px",
   高さ: "10px",
   行の高さ:"8px"
  },{
   textContent:_subList[i].category.length>0? "+" : "-"
  })
  subLi.textContent=_subList[i].name;
  Utils.appendTo(subSpan、subLi);
  }
  Utils.appendTo(subLi,subUl);
  //現在のメニューにサブメニューがない場合は、次の実行をスキップします。if(!_subList[i].category) continue;
  //現在のメニューのサブメニューをパラメータとして使用し、再帰を実行します。this.createSubMenu(_subList[i].category,subLi,1);
 }
 Utils.appendTo(subUl、_parent);
 }
 クリックハンドラ(e){
 //現在のクリックが li タグまたは span でない場合は、直接ジャンプします if(e.target.nodeName!=="LI" && e.target.nodeName!=="SPAN") return;
 ターゲットにします。
 e.target.nodeName==="SPAN" の場合、 targ=e.target.parentElement;
 そうでない場合、targ=e.target;
 //現在のクリック Li の下にサブメニューがない場合、直接ジャンプします if(targ.children.length<=1) return;
 //現在のクリックが第 1 レベルのメニューの場合は、直接ジャンプします if(targ.data===1) return;
 //現在クリックされている Li の下の ul の表示と非表示を制御します if(!targ.bool) targ.lastElementChild.style.display="block";
 それ以外の場合は、targ.lastElementChild.style.display="none";
 targ.bool = !targ.bool;
 //span タグの内容を変更します this.changeSpan(targ);
 //スクロール バーの高さを変更するイベントをスローします。var evt = new Event (Menu.SET_BAR_HEIGHT);
 ドキュメント.dispatchEvent(evt)
 }
 changeSpan(要素){
 if(elem.lastElementChild.style.display==="block"){
  要素.firstElementChild.textContent="-";
 }それ以外{
  要素.firstElementChild.textContent="+";
 }
 }
 マウスホイールハンドラ(e){
 //イベントのバブリングを停止します e.stopPropagation();
 //Firefox は e.detail をチェックします。e.detail<0 の場合、ホイールが下がっていてページが上がっていることを意味します。let tag=e.detail,wheelDir;
 //他のブラウザは e.deltaY を判断します。e.deltaY<0 の場合、スクロールホイールが下がっていてページが上がっていることを意味します。if(tag===0) tag=e.deltaY;

 if(タグ>0){
  //ホイールが下にスクロールし、ページが上に移動します wheelDir="down";
 }それ以外{
  wheelDir="上";
 }
 //イベントをスローし、スクロールホイールの方向を渡します。let evt = new Event(Menu.MOUSE_WHEEL_EVENT);
 evt.wheelDirection=ホイール方向;
 this.elem.dispatchEvent(evt);
 }
}

ScrollBar.js ファイルを使用して、スクロール バーを作成し、スクロール バーを操作します。

'./Utils.js' から Utils をインポートします。
'./Menu.js' からメニューをインポートします。
デフォルトクラスScrollBarをエクスポートします。
 バー;
 コンハイト;
 メニューの高さ;
 ホイールスピード=6;
 バートップ=0;
 静的 SET_BAR_HEIGHT="set_bar_height";
 コンストラクタ(親) {
 this.container = 親;
 this.menuUl = this.container.firstElementChild;
 this.elem = this.createElem();
 //メニューのクリック イベントをリッスンし、スクロール バーの高さを動的に変更します。document.addEventListener(ScrollBar.SET_BAR_HEIGHT,()=>this.setBarHeight());
 //ul メニューはホイール イベントをリッスンします this.menuUl.addEventListener(Menu.MOUSE_WHEEL_EVENT,e=>this.mouseWheelHandler(e));
 }
 要素を作成します(){
 if (this.elem) は this.elem を返します。
 //スクロールバーの外側のコンテナを作成する let div = Utils.createE("div", {
  幅: "8px",
  高さ: "100%",
  位置: "絶対"、
  右: "0px",
  上: "0px",
 })
 div を作成します。
 div を返します。
 }
 追加先(親) {
 Utils.appendTo(this.elem,parent);
 }
 作成バー(_parent) {
 if(this.bar) は this.bar を返します。
 //スクロールバーを作成する this.bar = Utils.createE("div", {
  幅: "100%",
  位置: "絶対"、
  左: "0px",
  上: "0px",
  境界半径: "10px",
  背景色: "rgba(255,0,0,.5)"
 })
 //スクロールバーのホバー状態のスタイルを設定します。this.bar.addEventListener("mouseenter",e=>this.setMouseStateHandler(e));
 this.bar.addEventListener("mouseleave",e=>this.setMouseStateHandler(e));
 //スクロールバーの高さを設定します this.setBarHeight();
 //マウスのドラッグイベントをリッスンします this.mouseHand = e => this.mouseHandler(e);
 this.bar.addEventListener("mousedown", this.mouseHand);
 Utils.appendTo(this.bar、_parent);
 }
 setBarHeight() {
 //外側の親コンテナの高さ this.conHeight = this.container.clientHeight;
 //実際のコンテンツの高さ this.menuHeight = this.container.firstElementChild.scrollHeight;
 // 実際のコンテンツの高さが親コンテナーの高さより小さい場合、スクロール バーは非表示になります if (this.conHeight >= this.menuHeight) this.bar.style.display = "none";
 それ以外の場合は this.bar.style.display = "block";
 //スクロールバーの高さを計算します。let h = Math.floor(this.conHeight / this.menuHeight * this.conHeight);
 this.bar.style.height = h + "px";
 }
 マウスステートハンドラーを設定する(e){
 //スクロールバーのホバー状態のスタイルを設定します if (e.type == = "mouseenter") {
  背景色は rgba(255,0,0,1) です。
 }それ以外{
  this.bar.style.backgroundColor="rgba(255,0,0,.5)";
 }
 }
 マウスハンドラ(e) {
 スイッチ (e.type) {
  ケース「マウスダウン」:
  e.preventDefault();
  オフセットYは、
  document.addEventListener("mousemove", this.mouseHand);
  document.addEventListener("mouseup", this.mouseHand);
  壊す;
  ケース「マウス移動」:
  //注: getBoundingClientRect() によって返される結果では、幅と高さの両方に境界線が含まれます。var rect = this.container.getBoundingClientRect();
  this.barTop = e.clientY - rect.y - this.y;
  //スクロールバーの移動 this.barMove();
  壊す;
  ケース「マウスアップ」:
  document.removeEventListener("mousemove"、this.mouseHand);
  document.removeEventListener("mouseup", this.mouseHand);
  壊す;
 }
 }
 マウスホイールハンドラ(e){
 //ローラーイベント if(e.wheelDirection==="down"){
  //下にスクロールすると、メニュー コンテンツが上に移動します。this.barTop+=this.wheelSpeed;
 }それ以外{
  this.barTop-=this.wheelSpeed;
 }
 //スクロールバーの移動 this.barMove();
 }
 バー移動(){
 this.barTop が 0 の場合、 this.barTop は 0 になります。
 this.barTop > this.conHeight - this.bar.offsetHeight の場合、 this.barTop = this.conHeight - this.bar.offsetHeight;
 this.bar.style.top = this.barTop + "px";
 //メニューコンテンツのスクロール this.menuMove();
 }
 メニュー移動(){
 //コンテンツのスクロール高さを計算します。let menuTop=this.barTop/(this.conHeight-this.bar.offsetHeight)*(this.menuHeight-this.conHeight);
 this.menuUl.style.top=-menuTop+"px";
 }
}

Utils.js ファイルはツールキットです:

デフォルトクラス Utils をエクスポートする{
 静的createE(要素、スタイル、準備){
 要素 = document.createElement(要素);
 if(style) for(let prop in style) elem.style[prop]=style[prop];
 if(prep) for(let prop in prep) elem[prop]=prep[prop];
 要素を返します。
 }
 静的appendTo(要素、親){
 parent.constructor === String の場合、parent = document.querySelector(parent);
 親要素に子要素を追加します。
 }
 静的ランダム数(最小値,最大値){
 Math.floor(Math.random*(max-min)+min) を返します。
 }
 静的ランダムカラー(アルファ){
 アルファ=アルファ||Math.random().toFixed(1);
 isNaN(alpha)の場合、alpha=1;
 アルファ>1の場合、アルファ=1;
 アルファ<0の場合、アルファ=0;
 col="rgba("; とします。
 (i=0;i<3;i++) の場合{
  col+=Utils.randomNum(0,256)+",";
 }
 col+=alpha+")";
 列を返します。
 }
 静的挿入Css(選択、スタイル){
 document.styleSheets.length===0の場合{
  styleS = Utils.createE("style"); とします。
  Utils.appendTo(styleS,document.head);
 }
 styleSheet を document.styleSheets[document.styleSheets.length-1] とします。
 str=select+"{"とします。
 for(var prop in スタイル){
  str+=prop.replace(/[AZ]/g,function(item){
  "-"+item.toLocaleLowerCase() を返します。
  })+":"+styles[prop]+";";
 }
 str+="}"
 styleSheet.insertRule(str、styleSheet.cssRules.length);
 }
 静的 getIdElem(要素,obj){
 if(elem.id) obj[elem.id]=elem;
 if(elem.children.length===0) の場合、obj を返します。
 for(let i=0;i<elem.children.length;i++){
  Utils.getIdElem(elem.children[i],obj);
 }
 }
}

以上がこの記事の全内容です。皆様の勉強のお役に立てれば幸いです。また、123WORDPRESS.COM を応援していただければ幸いです。

以下もご興味があるかもしれません:
  • ネイティブ js でカスタム スクロール バーを実装する
  • jsはスクロールバーの自動スクロールを実現します
  • Vue.js デスクトップ カスタム スクロール バー コンポーネント 美化 スクロール バー VScroll
  • JS カスタムスクロールバー効果
  • JavaScript でシンプルなチャット ダイアログ ボックス (スクロール バー付き) を実装します。
  • js ホイール イベントを使用した js カスタム スクロール バーの実装
  • JS はスクロールバーを底まで押してさらに読み込むように実装します
  • js を使用してシンプルなスクロールバーのプロセス分析を実装する
  • スクロールバーを非表示にするlayer.jsオープン例
  • Vue pure jsはスクロールバーを一番下まで監視します
  • JavaScriptはスクロールバーの位置を取得し、ページをアンカーポイントまでスライドします。

<<:  Linuxの同時実行は簡単です。このようにするだけです

>>:  Ubuntu 15.04 は MySQL リモート ポート 3306 を開きます

推薦する

HTMLボタンを中央に配置する方法

HTML ボタン自体を中央に配置するにはどうすればよいでしょうか? このアイデアは簡単に見つかります...

JSはプログレスバーをドラッグして要素の透明度を変更することを実装しています

今日ご紹介したいのは、ネイティブ JS を使用してプログレス バーをドラッグし、要素の透明度を変更す...

ElementUI の el-dropdown に複数のパラメータを実装する方法

最近、業務上のボタンの増加により、ページレイアウトにボタンが多すぎて、ページが美しくなく、ユーザーエ...

MySQL ストレージエンジンの簡単な紹介

1. MySQL アーキテクチャストレージ エンジンを紹介する前に、まずは MySQL アーキテクチ...

Reactの基本のまとめ

目次序文始めるReactライフサイクルリアクトファイバーリアクトセットステートReactイベントメカ...

CentOS7 環境での DHCP 設定チュートリアル

目次CentOS7環境での設定コマンド手順1. DHCP設定ファイルを設定する2. グローバル構成を...

mysql maxとwhere間の実行問題の概要

mysql maxとwhereの間の実行の問題SQLを実行します: テーブル「grades」を作成し...

JavaScript es6 における var、let、const の違いの詳細な説明

まず、よくある質問は、ECMAScript と JavaScript の関係は何ですか? ECMAS...

MySQLに必要な共通知識のまとめ

目次主キー制約一意の主キー非 Null 制約デフォルトの制約外部キー制約1NF 2NF 3NFデータ...

初心者向けのMySQLデータベースとテーブルDDLの作成と操作の学習

目次1. データベースを操作する1.1 データベースを作成する1.2 データベースをクエリする1.3...

KTLツールはMySQLからMySQLへのデータの同期方法を実現します

ktl ツールを使用して、mysql から mysql にデータを同期します。 1. 新しいジョブス...

pagodaを使用してionCube拡張機能をインストールする方法

1. まずパゴダを設置するインストール要件: Python バージョン: 2.6/2.7 (Pago...

HTML 順序なしリスト 箇条書き 画像を使用した CSS の記述

少なくとも 5 冊のベストセラー書籍の順序なしリストを含む HTML ページを作成します。各書籍の前...

MySQL パフォーマンス最適化のための魔法のツール、Explain の基本的な使用分析

導入MySQL には、SELECT ステートメントを分析し、開発者が最適化できるように SELECT...

Docker コンテナのネットワーク設定によく使われるコマンドの詳しい説明

基本的なネットワーク構成Docker はイメージに基づいて複数のコンテナを「開く」ことができ、各コン...