夕方のレッスン:純粋なJSの要素のサイズ変更

別の無料の夕べがありました。今日は、純粋なJavaScriptのあらゆる要素(div、画像、何でも)のあらゆる方向に完全にサイズ変更できるようにします。



デモページ: Resizable.js



アプローチ番号0



8つの吊り下げ歌姫リサイザーを作成します。そのうちの4つは、要素の側面に沿ったストリップで、さらに4つがコーナーにあります。 サイズを変更するときは、要素のサイズを変更し、diva-resizerをドラッグします。



短所は明らかです:





アプローチ1



要素をマウスで移動するとき、カーソルが要素の端にあるかどうかを確認します。 はいの場合、適切なカーソルスタイルを割り当てます(たとえば、右上の端にカーソルを合わせるとサイズが変更されます)、そうでない場合は、デフォルトのカーソルを割り当てます。



mousedown要素を使用して、同じチェックを行います。 その場合、正しい方向にサイズ変更を開始し、そうでない場合は何も行いません。



補助関数direction()を記述します。これは、カーソルが要素のどのエッジにあるかを決定します。 0から7までの数字(0-上でサイズ変更、1-右など、4-上と右、5-右と下など、時計回り)を返します。 8-カーソルが要素の端にない場合、サイズ変更は開始されません。



function direction( elem, event, pad ) { var res = 8; var pad = pad || 4; var pos = elem.getBoundingClientRect(); var top = pos.top; var left = pos.left; var width = elem.clientWidth; var height = elem.clientHeight; var eTop = event.clientY; var eLeft = event.clientX; // [...]
      
      





引数の名前はそれ自身を表しています:elemはサイズ変更される要素、eventはmousemoveまたはmousedown要素のイベントオブジェクト、padはサイズ変更を開始できるピクセル単位の境界(デフォルトでは4px)からの最大インデントです。 つまり マウスを端に4ピクセルより近づけると、カーソルが変わり、マウスをクリックすると、サイズ変更が開始されます。



要素の寸法と座標、およびイベントの座標に基づいて、カーソルがどのエッジにあるかを確認します。



 var isTop = eTop - top < pad; var isRight = left + width - eLeft < pad; var isBottom = top + height - eTop < pad; var isLeft = eLeft - left < pad; if ( isTop ) res = 0; if ( isRight ) res = 1; if ( isBottom ) res = 2; if ( isLeft ) res = 3;
      
      





それだけではありません-対角のサイズ変更も考慮する必要があります。



 if ( isTop && isRight ) res = 4; if ( isRight && isBottom ) res = 5; if ( isBottom && isLeft ) res = 6; if ( isLeft && isTop ) res = 7; return res; //       , //  res    8
      
      





カーソルスタイルを割り当てる補助変数を導入します。 今後必要になります。



 var cursors = "nwse ne se sw nw".split(" ");
      
      





それでは、 Resizable()コードを直接書き始めましょう。



 function Resizable( elem, options ) { options = options || {}; options.max = options.max || [1E17, 1E17]; options.min = options.min || [10, 10]; options.allow = (options.allow || "11111111").split(""); // [...]
      
      





ここで、 maxminは要素の最大サイズと最小サイズであり、 allowは許可された方向です(たとえば、値「11110000」は斜めのサイズ変更を禁止します)。



端に近づいたときにカーソルを変更します。



 elem.addEventListener( "mousemove", function ( e ) { var dir = direction( this, e ); if ( options.allow[dir] == "0" ) return; this.style.cursor = dir == 8 ? "default" : cursors[ dir ] + "-resize"; //    cursors } );
      
      





要素がmousedownの場合、resizeStart関数を呼び出します。この関数のコードは次のようになります。 サイズ変更時のテキストの選択も禁止されています。



 elem.addEventListener( "mousedown", resizeStart ); document.body.onselectstart = function (e) { return false };
      
      





オプションの値はresizeStartで使用できなくなるため、将来の参照のためにキャッシュします。



 elem.min = options.min; elem.max = options.max; elem.allow = options.allow; elem.pos = elem.getBoundingClientRect();
      
      





作業の半分はすでに完了しています。残っているのは、方向()に基づいて要素のサイズを変更することだけです。 右と下にサイズを変更すると、すべてが簡単になります-高さと幅を変更するだけで済みますが、左と上にサイズを変更する場合は、要素の座標を変更する必要があります。 しかし、まず最初に。



 function resizeStart( ev ) { var dir = direction( this, ev ); //   if ( this.allow[dir] == "0" ) return; //    ,   document.documentElement.style.cursor = this.style.cursor = cursors[ dir ] + "-resize"; var pos = this.getBoundingClientRect(); var elem = this; //    mousemove  var height = this.clientHeight; var width = this.clientWidth; //        //  resize().    . document.addEventListener( "mousemove", resize ); //       //     document.addEventListener( "mouseup", function () { document.removeEventListener( "mousemove", resize ); document.documentElement.style.cursor = elem.style.cursor = "default"; document.body.onselectstart = null; }); };
      
      





最後のフロンティアは内部のresize()関数で、これはすべての作業を行います。



 function resize ( e ) { //            //      //   if-    if ( dir == 0 || dir == 4 || dir == 7 ) { elem.style.top = e.clientY - ev.clientY + pos.top; elem.style.height = height + ev.clientY - e.clientY; } if ( dir == 1 || dir == 4 || dir == 5 ) { elem.style.width = e.clientX - pos.left; } if ( dir == 2 || dir == 5 || dir == 6 ) { elem.style.height = e.clientY - pos.top; } if ( dir == 3 || dir == 6 || dir == 7 ) { elem.style.left = e.clientX - ev.clientX + pos.left; elem.style.width = width + ev.clientX - e.clientX; }
      
      





追加の制限:最小の高さまたは幅に到達したときに、それぞれ上から下または右から左にサイズ変更すると、要素はサイズ変更せずに下または右に移動し始めます。 したがって、次のチェックを行います。



 if ( e.clientY + elem.min[1] > ev.clientY + height ) return; if ( e.clientX + elem.min[0] > ev.clientX + width ) return;
      
      





また、最小サイズまたは最大サイズに達しているかどうかを確認します。



 if ( elem.clientHeight < elem.min[1] ) elem.style.height = elem.min[1]; if ( elem.clientWidth < elem.min[0] ) elem.style.width = elem.min[0]; if ( elem.clientHeight > elem.max[1] ) elem.style.height = elem.max[1]; if ( elem.clientWidth > elem.max[0] ) elem.style.width = elem.max[0]; if ( e.clientY < pos.bottom - elem.max[1] ) elem.style.top = pos.bottom - elem.max[1]; if ( e.clientX < pos.right - elem.max[0] ) elem.style.left = pos.right - elem.max[0];
      
      





これがもっとエレガントにできるかどうかはわかりません...いずれにしても、要素のサイズ、その座標、イベントの座標、そしてこれらすべては方向()の結果に基づいて、さらに最小/最大を考慮に入れる必要があります。 サイズ。



一般的に、プラグインは準備ができています。 jsのソースコードはここにあり、作業の例は最初からいつも通りです。



ボーナス:アニメーションのサイズ変更可能



デモページ: サイズ変更可能2.0



操作の原理は似ています。要素自体のサイズは変更されず、divが作成されます。



 var helper = document.createElement( "DIV" ); document.body.appendChild( helper ); helper.style.cssText = "position: fixed; border: 1px dashed black"; helper.style.width = width; helper.style.height = height; helper.style.top = pos.top; helper.style.left = pos.left;
      
      





に書かれたifsでは、 elemの代わりにヘルパーがいます。



ドキュメントがマウスアップされると、要素をヘルパーのサイズに合わせてアニメーション化し、ヘルパーを削除します。



 document.addEventListener( "mouseup", function () { document.removeEventListener( "mousemove", resize ); document.documentElement.style.cursor = elem.style.cursor = "default"; document.body.onselectstart = null; var newpos = helper.getBoundingClientRect(); var start = new Date().getTime(); setTimeout( animate, 10 ); function animate() { var m = (new Date().getTime() - start) / 300; if (m > 1) m = 1; elem.style.top = pos.top + (newpos.top - pos.top) * m; elem.style.left = pos.left + (newpos.left - pos.left) * m; elem.style.height = height + (helper.clientHeight - height) * m; elem.style.width = width + (helper.clientWidth - width) * m; if (m < 1) setTimeout( animate, 10 ); } setTimeout( function () {document.body.removeChild( helper );}, 310 ); });
      
      





私が言いたかったのはそれだけです。



All Articles