06 | 2010/07 |  08

  1. 無料サーバー

User forum-FC2BLOG-Info-Edit Template-Post-Edit-Upload-LogOut

CSSやJavascript自習の苦闘史を綴っていきたい。恐縮ですがJavascriptを有効にしてご覧ください。
2005年12月から社会問題も掲載!


スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

jQuery を使って画像も動画も Popup する

popup メソッドは2年半前に一度作成していた

2007年12月。PopupTips と題して、jquery.js を最小限度使用してポップアップを作りました。お陰様で 6 件の拍手を戴きましたが、パソコンの高速化がますます定着し、加速されている今、jquery.js をフル活用したコードでも、描画に大きな支障は出ない程度にまでパソコン性能が向上しました。
だから、というわけでもありませんが、今回改めて jquery.js をフル活用して popup メソッドを作り直しました。

それは上の「関連エントリイ」に掲載した jQuery()活用(2) Popup Tips を自作する──jQuery解読(22) に詳述したので、関心のある方はそちらをご覧戴ければ幸いです。

jquery.js をフル活用して作成した popup メソッドの概要

ここでは自作の setPopup プラグインメソッドの概要を紹介させて戴きます。なお、以下のアンダーライン部に popup を仕込みましたので、どんな具合に作動するのか、このエントリイで確認して戴くことが出来ます。

  1. 改めて作成した popup は それを引き起こすタグ要素の title 属性値をそのコンテンツとするように設計しました。つまり、何らかの class 指定を行わなくても、jQuery('*[title]').setPopup(args) で popup 励起要素が指定出来るようにしました。
  2. 勿論、特定の要素に class 指定を施して、それらの要素に対してだけ popup を表示させることも可能です。つまり、popup 励起要素はいかようにも自由に指定できるようにしました。
  3. popup 励起要素内で mouseenter/mouseleave イベントが発生すると、popup 要素が表示/隠蔽されることは勿論ですが、更に mousemove イベントが起きると、popup 要素はマウスカーソルに追随して移動するように設計しました。なお、その際には popup 要素が画面からはみ出さないようにもしました。
  4. popup する内容はテキスト文字列だけではなく、任意の HTML タグ要素を指定出来るようにしました。つまり、title 属性値に記述した HTML 文が HTML 文として解釈され、popup 要素内に描画されるようにしました。例えば、番号付き箇条書きや画像を popup させることも可能です。(ここではパノラマ写真を popup します)
  5. 次に動画を popup させてみます。なお動画表示の場合には HTML 文に若干の工夫が必要です。popup 要素内にはマウスカーソルを移動出来ないので、自動再生を指定しておく必要がある、ということです。
    なお、youtube 動画の自動再生指定方法は、 youtubeの動画を自動再生する方法 に大変分かりやすく記されていました。

▲ToTop

どのエントリイでも、どのブログでも使えるように plug-in 化

作成した Javascript コードの全容は こちら に掲載しておきましたが、このコードをプラグイン化したことを強調しておこうと思います。

プラグイン化により、このブログのどのエントリイでも、否、このブログだけではなく、また Fc2 ブログでなくても、任意のブログで使える仕様になっているはずです。

jquery.js をフル活用しつつ、汎用的に利用できる───今後作成するjquery.js を利用したコードは、可能な限りこのような仕様にするつもりです。それこそが jquery.js を真の意味で活用することになるはずですし、そうなればこその「やり甲斐」でもあります。

スポンサーサイト

jQueryを使ってブログエントリイの目次を自動作成する。

この上の目次は以下に述べるスクリプトにより自動作成されたものである。

このエントリイの後に、別のもっとクールな目次自動作成プラグインを作った。このため、このエントリでのみ 2 通りの目次が作成され、表示されるようにした。この他のエントリイでは新しい目次作成プラグインを使用するようにしたため、このエントリイでのみ旧バージョンとなってしまった目次作成プラグインを表示している。

なお、新しい目次自動作成プラグインについては、こちらで 触れている。

エントリイ目次の作成意義

私のブログエントリイは、各エントリイの文章が長くなる傾向にある。

そして長いエントリイの場合には、全体を概観する必要が生じるので目次があった方が良い。

しかも、その目次は或るルールに基づいて作成することにすれば、エントリイ毎に作らなくてもスクリプトで自動作成させることが可能だ。

そこで、jQuery を活用する簡単な例として作ってみた。

エントリイ目次のスクリプトによる作成方法

目次項目はヘッダー要素のコンテンツをピックアップすれば良く、それに頁内リンクを貼った上で箇条書き整形してから、エントリイ内に挿入すればよい。

なお、頁内リンクを貼るということは、リンク先となるヘッダー要素のコンテンツを a タグで包含しなければならず、その行為もスクリプトで自動的に行うべきだろう。

目次自動作成:makeContents メソッドコード

以下に makeContents コードとその各行説明を掲載したが、コードの要点を列挙しておきたい。

  1. makeContents メソッドは汎用性が高いプラグイン形式とした。
  2. このメソッドに 2 つの引数を用意した。これは、初期状態で目次を表示するか否かを指定し、また目次の背景色を自在に変更可能にするためだ。なお、2 つの引数の記述順は指定せず、いずれが先でもインタープリタが「正しく理解」できるよう工夫した。
  3. 初期状態で目次が表示されているか否かに応じて、目次表示/隠蔽ボタンの機能は変化するが、それを 1 つの toggle イベントハンドラーで扱うにあたり、ボタン背景色と slideDown/Up を交互に入れ替えるために配列の reverse メソッドを活用した。
  4. blur メソッドを使ってボタン要素にフォーカスが残らないようにした。
  5. 自作コードで初めて wrapInner メソッドを利用した。これは或るタグ要素内のコンテンツを、新たな子要素で囲む場合に重宝するメソッドだ。或る要素Aの子要素Bを新たな子要素Cを挿入してCの子要素(つまりAの孫要素)にする便利なメソッドである。
  6. $btn オブジェクトに見られるように jQuery インスタンスメソッドチェーンを多用した。メソッドチェーンは余りの便利さに快感すら覚える。これもまた jquery.js の醍醐味と言えよう。
    因みにここでチェーンしたメソッドは、順に .css、.prependTo、.toggle だ。しかもjQuery インスタンスメソッドの返値が jQuery インスタンス自身となることを利用して、チェーンメソッドが適用されている jQuery インスタンスを右辺に配置して、これを左辺の変数に代入することまで一つの式で実現した。
  7. 上で述べた jQuery インスタンスメソッドの返値を利用した式は、他の箇所でも多用している。変数 $contents や $h4 への代入式もまた、 jQuery インスタンスメソッド返値が jQuery インスタンスであることを利用している。
// makeContents メソッドをプラグインとして登録する。
(function ($){$.fn.makeContents = function(display,color){
  // 個別エントリイ表示モード以外の場合何もしない。
  if (!/.+blog-entry.+html$/.test(location.href)) (function(){return;})();
  else { // 個別エントリイ表示モードならば実行する
    $(function(){ // DOM ready イベントに登録する。
    // もし #contents 要素が存在すればそれを削除する。
    if ($("#contents").size()) $("#contents").remove();
    // ローカル変数定義
    var $entry, $contents, $h4, $btn, o = [], bgColor=
      // 目次ブロックの背景色を設定する。
      (typeof display==="boolean" && typeof color==="string" && color) 
      || (typeof color==="boolean" && typeof display==="string" && display)
      || "darkslategray";
    // エントリイ本体部分へのショートカット作成
    $entry = $("div.entry_body");
    // 目次を表示する ol 要素をスタイルシート付きでエントリイ
    // 最上部に挿入する。但し、コード進行が終了間際迄は非表示としておく。
    $contents = $("<ol id='contents' />").css({
      margin:"1em 2em",padding:"0.5em 2em",border:"1px dotted white",
      lineHeight:"1.1em",background:bgColor
    }).prependTo($entry).hide();
    // H4 ヘッダーコンテンツに id を付け、H4 ヘッダーコンテンツを
    // 頁内リンク付きの LI 要素として目次の OL 要素内に挿入する
    $h4 = $("h4",$entry).each(function(i){
      $(this).wrapInner("<a id='contents"+i +"'></a>");
      $contents.append(
        "<li><a href='#contents"+i+"'>"+$(this).text() +"</a></li>"
      );
    });
    // ボタン背景色と slide メソッドを配列に登録
    o[0]={btncolor:"pink",fn:function(){$contents.slideDown()}};
    o[1]={btncolor:"palegreen",fn:function(){$contents.slideUp()}};
    // 目次を最初に表示しない指定の場合、
    // 色と slide メソッドのセットを入れ替える。
    if (!display) o.reverse();

    // 目次の表示/隠蔽を操作するボタンをエントリイ本体上部に配置し、
    $btn = $("<button>目次の表示/隠蔽</button>").css({
      display:"block",background:o[0].btncolor,
      fontWeight:"bold",width:"150px",margin:"0 auto"
    }).prependTo($entry).toggle(function(){ // toggle イベントを登録する。
      // slide メソッドの実行。
      o[1].fn();
      // ボタンの背景色を変更する。
      $(this).css({background:o[1].btncolor}).blur();
    },function(){
      o[0].fn();
      $(this).css({background:o[0].btncolor}).blur();
    });
    // 目次表示モードが指定されている場合には、slideDown メソッドを実行する。
    if (display===true || color===true) $contents.slideDown();
  });}
}})(jQuery);
// makeContents メソッドを目次表示モード( true 指定 )で起動する。
$().makeContents(true);
//$().makeContents(); //エントリイ表示時に目次を非表示にする場合の指定
//$().makeContents(true, "navy"); //エントリイ表示時に目次を表示しその背景色をnavyにする場合の指定

複数エントリイにまたがるコンテンツの総合目次をスクリプトで挿入する

はじめに

複数のエントリイにまたがって或る長いコンテンツがあるとする。この場合、全体に共通する総合目次が存在すると閲覧しやすい。

そしてその総合目次は、どのコンテンツが今見ているエントリイに存在し、また別のエントリイにどんな項目が存在しているかを指し示すべきであり、別ページの項目にはリンクが貼られていることが望ましい。

以上の総合目次をスクリプトで挿入する方法を考えてみた。

この総合目次を実際に適用したエントリイは、上の関連エントリイリストで示した No.749~753 の 5 つだ。

それらのいずれかを開けば、実際にスクリプトによって挿入された総合目次をエントリイ最上部に見ることが出来る。

何故 Ajax を使わなかったか?

まず Ajax 通信を使おうと考えたが直ぐに止めた。答えは単純だ。使えないからである。

Fc2 ブログの場合、エントリイHTMLファイルが存在するサーバーと、アップロードしたファイルが存在するサーバーが異なっている。このため同一サーバー上のファイルにしか適用できない Ajax 通信はアップロードしたファイルを対象として使用できないのである。

もし、Ajax 通信が同じ Fc2 ドメイン内の異なるサーバー間でも使用できるならば、総合目次をアップロードしておいて、それを jQuery(要素).load(url) で当該要素内に読み込めば済む。しかし、駄目元で試したみたがやはり「期待通り」駄目だった。エントリイサーバーと異なるサーバーを対象として、エントリイ頁から Ajax 通信は出来なかった。

総合目次の HTML 文をスクリプト内に取込み、script をインクルードすれば良い

では、諦めて各エントリイに同一の総合目次 HTML 文を挿入するしかないのか?!─── Ajax 通信が不成功に終わった直後はそう考えた。

しかし、それでは余りに芸がない。何とかならないものかと思案していたら、ふと script タグによるインクルードならば、Ajax 通信と異なり、同一サーバー制限がないことを思い出した。

そうだ。HTML 文を Javascript 文で書いてしまって、全てをスクリプトで挿入すればよいのだ!

どっちみち HTML 文だけでは目的は達成できずJavascript コードを必要とするのだから、全てをスクリプト化してしまえば良いのだ!

こうして完成した総合目次は、エントリイ No.749~753 に掲載した。

▲ToTop

目次の HTML 文を取込みインクルード対象とした script について

極めて簡単なスクリプトであり、目次部分を変更すればいくらでも汎用的に使えるので、script を掲載し説明することとしたい。

■ Entry No.749~753 の総合目次の Javascript 文
// 目次を挿入する div 要素を取得し、ショートカットを作る。
// この要素もスクリプトで挿入しても良いが、可読性を高めるために敢えてエントリイ HTML 文
// 内に別途挿入することとした。なお、HTML文に挿入した div 要素はあらかじめ display:none
// としておく必要がある。
var $contents = $("div.posSizeContents");
// 個別エントリイ表示モードではない時には、必要なコメント文を挿入する。
if (/blog-entry.+html$/.exec(location.href)===null){
  $contents.html('<p class="ta_c">個別エントリイ表示モードの時のみ、ここに目次を表示します</p>').show();

} else { // 以降は個別エントリイモードの時にのみ適用されるブロック
// 変数 contents に総合目次のHTML文を登録する。
var contents ='<ol class="ml_0 pl_2 mt_0 mb_0">'+
'<li><a href="http://hkom.blog1.fc2.com/blog-entry-749.html" target="_blank">要素位置の測定と適正な配置──はじめに</a></li>'+
'<li><a href="http://hkom.blog1.fc2.com/blog-entry-750.html" target="_blank">コード解説(1) jQuery.offset</a></li>'+
'<li><a href="http://hkom.blog1.fc2.com/blog-entry-750.html" target="_blank">コード解説(1) jQuery().offset</a></li>'+
'<li><a href="http://hkom.blog1.fc2.com/blog-entry-751.html" target="_blank">コード解説(2) jQuery().position</a></li>'+
'<li><a href="http://hkom.blog1.fc2.com/blog-entry-751.html" target="_blank">コード解説(2) jQuery().offsetParent</a></li>'+
'<li><a href="http://hkom.blog1.fc2.com/blog-entry-752.html" target="_blank">コード解説(3) jQuery().scrollLeft</a></li>'+
'<li><a href="http://hkom.blog1.fc2.com/blog-entry-752.html" target="_blank">コード解説(3) jQuery().scrollTop</a></li>'+
'<li><a href="http://hkom.blog1.fc2.com/blog-entry-753.html" target="_blank">コード解説(4) jQuery().innerHeight</a></li>'+
'<li><a href="http://hkom.blog1.fc2.com/blog-entry-753.html" target="_blank">コード解説(4) jQuery().innerWidth</a></li>'+
'<li><a href="http://hkom.blog1.fc2.com/blog-entry-753.html" target="_blank">コード解説(4) jQuery().outerHeight</a></li>'+
'<li><a href="http://hkom.blog1.fc2.com/blog-entry-753.html" target="_blank">コード解説(4) jQuery().outerWidth</a></li>'+
'<li><a href="http://hkom.blog1.fc2.com/blog-entry-753.html" target="_blank">コード解説(4) jQuery().height</a></li>'+
'<li><a href="http://hkom.blog1.fc2.com/blog-entry-753.html" target="_blank">コード解説(4) jQuery().width</a></li></ol>';

// 正規表現作成
var  regExpr = /(http:.+entry-)([0-9]+)/,
// アドレス情報から今見ているエントリイの番号を取得
  thisEntryNo = Number(regExpr.exec(location.href)[2]);
// 用意した div 要素内に総合目次 HTML 文を挿入してから、a 要素を見つけ、
// 全ての a 要素を対象としてイテレート処理を施す。
$contents.html(contents).find("a").each(function(){
  // href属性値から エントリイ番号を取得して変数 No に代入する
  var No = Number(regExpr.exec($(this).attr("href"))[2]);
  // 取得した No が今見ているエントリイの番号と一致すれば、
  if (No===thisEntryNo){
    // 当該 a 要素の内容テキスト(つまりエントリイタイトル)を変数 txt に代入
    var txt = $(this).text();
    // a 要素の親要素に遡り、その中を空にしてから(つまり a 要素を削除してから)
    // 当該エントリイタイトル名称に「 ……このエントリイで解読します」を結合した
    // テキスト分を挿入する。
    $(this).parent().empty().html("<span class='pink'>"+txt + " ……このエントリイで解読します</span>");
  } else { // No !== thisEntryNo の時には
    // a 要素の後に「 ……別のエントリイ No."+ No +" で解読します」なるテキスト文を付加する。
    $(this).after("<span> ……別のエントリイ No."+ No +" で解読します</span>");
  }
}).end().show(); //総合目次を挿入した div 要素を非常時から表示に変更する
}

Ajax 通信に拘って総合目次を読み込む方法

上で示した方法よりも時間を要することになるが、Ajax 通信で同一のことを行う方法がないわけではない。

総合目次はエントリイタイトルとエントリイアドレスから構成されているのだから、これらの情報は目次を挿入したいエントリイと同一のサーバーにある。つまり、Ajax 通信の適用対象となる。

よって、総合目次のエントリイ情報を Ajax 通信で取得すればよいことになる。

実は、Ajax 通信によるエントリイ情報取得は、ナビゲータブロックで既に実施済みであり、このコードを一部手直しするだけで、ここで作成したエントリイNo. 749 ~ 753 の総合目次を作成することが可能ではある。

しかし、この方法の場合、エントリイタイトルをそのまま利用することになるので、目次項目を自由に加工した総合目次とするわけには行かない。

だから、ここでは敢えて HTML文を組み込んだ script をインクルードする道を選択したのである。

jQuery の各種メソッドを活用して、マウスカーソルの現在位置や要素の位置とサイズなどを取得する

はじめに───ここで行ったこと

このエントリイでは、jQuery の各種メソッドを活用して、まず、マウスカーソルの現在位置の頁座標を取得/表示し、また要素の頁座標と offsetParent 座標値並びに大きさを取得/表示させます。

次に、要素をアニメーションさせた直後に、当該要素の絶対/相対座標値や要素の各サイズ値を取得/表示させます。その際には、値が変わった箇所を一目で分かるように工夫しました。

このアニメーションは要素が往復運動するもので、1の往復運動毎にその動く方向・距離・内容幅・内容高さを乱数を発生させて変動させています。何度か繰り返しアニメーションさせてみると乱数の効果を良く確認出来るでしょう。box2 と box3 に別々の乱数を割り振ったので、「往路」の方向も移動距離も幅と高さの変化率もお互いに異なりますが、復路は必ず最初の位置とサイズに戻るようにプログラミングしました。

また、往路復路の別を分かりやすくするために、往路が終わると要素が半透明になるようにしました。この状態は復路が終わると当初の不透明に戻ります。

testArea...pos:rel
tester1
pos:stat
box1
pos:rel
tester2
pos:rel
box2
pos:abs
tester3
pos:rel
box3
pos:abs
tester4
pos:abs
tester's position
itemAreatester1tester2tester3tester4
Left
Top
posLeft
posTop
width
innerW
outerW
marginW
height
innerH
outerH
marginH
box's position
box1box2box3

※ ピンクの背景色セルは、その値が直前値から変化したことを示す。

▲ToTop

1. マウスカーソルの現在座標値をリアルタイムで取得し表示する

マウスカーソルの現在座標値は、jQuery のイベントに係るメソッドを利用すれば、極めて簡単に取得できます。ブラウザ毎の計測方法の差異は jquery.js が処理してくれるので、後述するように、座標値取得のための javascript コードは極めて簡潔になります。

次に、取得したマウスカーソル座標値の表示については、上の背景色ロイヤルブルーのボックス内にマウスカーソルが入った時にのみ、マウスカーソルの右下にマウスカーソルの頁座標値を表示するようにしました。更に、当該ボックス内でマウスカーソルが移動した場合には、マウスカーソルに追随して座標表示ボックスを移動させ、かつ、刻々と変化する座標値を瞬時に表示するようにしました。

つまり、マウスカーソルの移動に合わせてリアルタイムでその座標値を取得し、座標値の表示場所はマウスカーソルに追随して移動するようにしました。

2. 要素の頁座標値とoffsetParentからの座標値、並びに大きさを取得し表示する

要素の位置と大きさを取得するために利用する jQuery メソッドは次の 10 個です。

offset、position、width、height、
innerWidth/Height、outerWidth/Height、outerWidth(true)/Height(true)

これらの jQuery インスタンスメソッドを使用すれば、極めて容易に要素の位置とサイズが取得出来ます。

jQuery(要素).offset インスタンスメソッドは、対象要素が含まれる表示領域の左辺または上辺から、対象要素のボーダー辺までの横又は縦方向の距離(頁内絶対座標とでも呼ぶべきか?)を計測し、jQuery(要素).position は、対象要素の offsetParent 要素のパディング辺からの、対象要素のマージン辺の横又は縦方向の距離を計測するメソッドです。このことの詳細は、「 jquery.js (1.4) による要素位置の測定と適正な配置 (2) コード解読(1) 」 に詳述しました。

また、width/height、innerWidth/Height、outerWidth/Height及びouterWidth(true)/Height(true)は、順に対峙する内容辺間距離、パッディング辺間距離、ボーダー辺間距離、マージン辺間距離を計測するメソッドです。詳細は拙エントリイ:「 jquery.js (1.4) による要素位置の測定と適正な配置 (5) コード解読 (4) 」を参照してください。画像付きで説明しています。

取得した値は、このエントリイ上部に配置した tester's position 表と box's position 表に表示させました。ここに、Left と Top は頁座標値で offset メソッドを使って、また posLeft と posTop はoffsetParent からの座標値で、position メソッドを使って、それぞれ取得しています。

また、offsettParent の定義から、各 tester ボックスの offsettParent は testAreaとなり、各 box の offsetParent は各 tester ボックスとなります。( 因みに testArea の offsetParent は div#container であり、更に div#container の offsetParent は body となります。body 以外の offsetParent とする要素は、全て CSS スタイル設定で position:relative を指定し、明示的にoffsetParent となるようにしました。)

▲ToTop

3. 要素を移動させるアニメーションと移動後の座標値の取得/表示について

ここで作成したアニメーションは 2 つの div 要素を、ほぼ同時に上 or 下かつ左 or 右に移動させながら、同時に幅と高さを変化させるものです。目的はアニメーションそのものよりも、移動前後の座標値の取得/表示を主眼としましたが、アニメーションそのものにも、少しは興味を引くであろう様々な工夫を凝らしました。(アニメーションの起動はエントリイ上部に配置した animate ボタンをクリックして行います。)

工夫は、単純な移動やサイズ変更の繰り返しでは詰まらないので、乱数 Math.random() メソッドを使って、移動の度に方向・距離・内容サイズが変わるようにしました。easing 関数も乱数によって 11 種類からその都度任意に選択されるようにセットしたので、クリックする度に異なる方向、異なる距離、,異なるサイズ、異なる easing を使ってアニメが展開されます。

また、ここで作成した移動と大きさ変更アニメーションは、往復運動で 1 サイクルになるようにしたので、往路の移動とサイズ変更が終わると要素が半透明になるようにして、往路であることが分かるようにしました。当然ですが復路が終わると位置と大きさは元に戻り、不透明度も 100 %に戻るようにしました。

4. このエントリイのためのスタイルシート

■スタイルシート
#testArea {
  position:relative;background:royalblue;width:520px;padding:1em;/*height:360px;*/
}
.tester {margin:0.5em;width:100px;height:150px;}
#tester1 {border:solid white 2px;} /*position:static*/
#tester2 {position:relative;background:darkred;border:solid yellow 2px;}
#tester3 {position:relative;background:teal;border:solid white 2px;}
#tester4 {position:absolute;top:10px;left:370px;border:solid lime 2px;}
.box {
  position:absolute;top:50px;left:20px;background:indigo;border:solid lime 2px;
  width:66px;height:80px;
}
#box1 {position:relative;}
#result {margin:1em 0;border:1px lightgray dotted;padding:2px;background:dimgray;}
table#table1 input,table#table2 input {width:65px;text-align:right;background:white}
table#table1 caption,table#table2 caption {color:lime}
table#table1 th,table#table2 th {line-height:0.5em;text-align:center}
table#table1 tr,table#table2 tr {line-height:1em;}
button#animBtn {display:block;position:absolute;top:180px;left:400px;z-index:10;}
div#testArea div#log {position:relative;z-index:9;padding-top:4em;line-height:1.1em;}

▲ToTop

5. jQuery の各種メソッドを活用したこのエントリイのための Javascript コードの解説

■javascript code
  // マウスカーソルの座標値を表示するためのdiv要素を作成する。
  $("<div id='testBalloon' />").css({
      position:"absolute",padding:"0.5em",border:"1px solid green",
      display:"none",background:"navy",zIndex:11
  }).appendTo("body");
  var o ={ // 各種 jQuery インスタンスへのショートカットなどを登録するオブジェクト
    $cont: $("#container"),
    $tArea: $("#testArea"),
    $t1: $("#tester1"),  $t2: $("#tester2"),
    $t3: $("#tester3"),  $t4: $("#tester4"),
    $tbl1: $("#table1"), $tbl2: $("#table2"),
    $input: $("input","#result"),  $log: $("#log"),
    $tBalloon: $("#testBalloon"), rnd:{}, // 乱数を格納するオブジェクト
    easing:["swing","easeInOutQuad","easeInOutCubic","easeInOutQuart","easeInOutQuint",
    "easeInOutSine","easeInOutExpo","easeInOutCirc","easeInOutElastic","easeInOutBack",
    "easeInOutBounce"], //easing 関数を登録
    cnt: 0, //カウンター
    flag: true //奇数偶数区別用
  };
  // 各 box へのショートカットを登録する
  o.$b1= $(o.$t1).children(":eq(1)");
  o.$b2= $(o.$t2).children(":eq(1)").css("zIndex","2");
  o.$b3= $(o.$t3).children(":eq(1)").css("zIndex","3");
  // document 内でマウスカーソルが動いた時に、その座標値を o オブジェクトのプロパティに登録する。
  // たったこれだけのコードで目的を達成することが出来る。
  $(document).bind('mousemove',function(e){ 
    o.x = e.pageX;
    o.y = e.pageY;
  });
  // エリア内にマウスカーソルがある時と外れた時の、
  // マウスカーソル座標値を表示するボックスの表示/非表示を制御する。
  o.$tArea.hover(
    function(){o.$tBalloon.fadeIn()},
    function(){o.$tBalloon.fadeOut()}
  ).mousemove(function(){
    // エリア内でマウスカーソルが動いた時に座標値を表示する。
    // 座標値の表示ボックスは、マウスカーソルの右下に 16 pxずれた箇所に表示する。
    o.$tBalloon.html("<div>top: "+ o.y+ "px<br />left: "+o.x+"px</div>")
      .css({top:parseInt(o.y)+16+"px",left:parseInt(o.x)+16+"px"})
  });

  // 要素の位置と大きさを計測する関数を再呼び出し出来るように定義する。
  var doCalc = function(){
    $.each([o.$cont,o.$tArea,o.$t1,o.$t2,o.$t3,o.$t4,o.$b1,o.$b2,o.$b3],function(){
      this.oSet = $(this).offset(); // jQuery.offset メソッド
      this.pos = $(this).position(); // jQuery.position メソッド
      this.left = this.oSet.left; // jQuery.offset().left 値取得
      this.top = this.oSet.top; // jQuery.offset().top 値取得
      this.posLeft = this.pos.left; // jQuery.position().left 値取得
      this.posTop = this.pos.top; // jQuery.position().top 値取得
      this.width = $(this).width(); // 内容辺間の幅取得
      this.innerW = $(this).innerWidth(); // padding 辺間の幅取得
      this.outerW = $(this).outerWidth(); // border 辺間の幅取得
      this.marginW = $(this).outerWidth(true); // margin 辺間の幅取得
      this.height = $(this).height(); // 内容辺間の高さ取得
      this.innerH = $(this).innerHeight(); // padding 辺間の高さ取得
      this.outerH = $(this).outerHeight(); // border 辺間の高さ取得
      this.marginH = $(this).outerHeight(true); // margin 辺間の高さ取得
    });
  }
  doCalc(); //関数実行
  // アニメーションで使用するために、4 つのプロパティの初期値を
  // アニメ対象オブジェクトの2 つのプロパティの初期値を org プロパティに記憶させる
  $.each([o.$b2,o.$b3],function(i,n){
    n.org={};
    $.each(["posLeft","posTop","width","height"],function(){
      n.org[this] = n[this];
    });
  });

  // 位置やサイズ値をエントリイ内の表内に挿入する関数
  var insertValue = function(ary,obj){ // ary は計測対象要素、obj は挿入対象 table。
    $.each(ary,function(i,n){
      $.each(["left","top","posLeft","posTop","width","innerW","outerW","marginW","height","innerH","outerH","marginH"],
        function(j){
          o.tmp=$(obj).find("input:eq("+(i+j*ary.length)+")");
          o.tmp.before=o.tmp.attr("value") || 0; // 直前の値
          // 各要素の各属性値を取得する。
          o.tmp.attr("value",parseInt(n[this],10)); // n は各要素、this は属性
          o.tmp.after=o.tmp.attr("value");
          // 前後の属性値が異なれば背景色を変化させる。
          o.tmp.before !== o.tmp.after ? o.tmp.css("background","pink")
          : o.tmp.css("background","white");
      });
    });
  };
  insertValue([o.$tArea,o.$t1,o.$t2,o.$t3,o.$t4],o.$tbl1);
  insertValue([o.$b1,o.$b2,o.$b3],o.$tbl2);
  o.$input.css("background","white"); // (初期値として)背景色をホワイトに設定する。
  // 移動アニメーション関数の定義
  var trans = function(){
    o.$input.css("background","white"); // 背景色の初期化
    // box2 の移動アニメーション。trans 関数は call メソッドを使ってo.rndオブジェクト
    // から呼び出すため、this は o.rnd オブジェクトを参照することになる。
    // this の各プロパティは $("#animBtn").click メソッドを参照のこと。
    o.$b2.animate({
      // アニメ終了値は全て相対移動量で設定する
      left: this[1]+"="+this[5][0]+"px",
      top: this[2]+"="+parseInt(this[5][0]/2)+"px",
      width: this[1]+"="+ Math.round(o.$b2.org.width*this[6][0])+"px",
      height: this[2]+"="+ Math.round(o.$b2.org.height*this[6][1])+"px",
      opacity: o.flag ? 0.5 : 1
      // 奇数回目には半透明に、偶数回目には不透明に。
      opacity: o.flag ? 0.5 : 1
    },1000,o.easing[parseInt(o.rnd[0][0]*11)]);
    o.$b3.animate({
      left: this[3]+"="+ this[5][1] +"px",
      top: this[4]+"="+ parseInt(this[5][1]/2) +"px",
      width: this[3]+"="+ Math.round(o.$b3.org.width*this[6][1]) +"px",
      height: this[4]+"="+ Math.round(o.$b3.org.height*this[6][0]) +"px",
      opacity: o.flag ? 0.5 : 1
    },1000,o.easing[parseInt(o.rnd[0][1]*11)],function(){ //アニメーションが終わってから、移動後の座標値を挿入する。
      doCalc(); insertValue([o.$b1,o.$b2,o.$b3],o.$tbl2);
    });
  }
  // アニメの動作ログを作る。
  var insertLog = function(){
    var ary = []; // 偶数回目の移動方向を反転表示とするため
    $.each([this[1],this[2],this[3],this[4]],function(i,n){
      ary[i] = o.flag ? n : (n==="+" ? "-" : "+");
    });
    o.$log.html(
      "<div>box2 の移動方向と距離のための乱数:"+ this[0][0] + "</div>"+
      "<div>box3 の移動方向と距離のための乱数:"+ this[0][1] + "</div>"+
      "<div>box2 の横移動距離:"+ary[0] +"=" + this[5][0]+"px, "+
      "box2 の縦移動距離:"+ary[1] +"=" + parseInt(this[5][0]/2)+"px</div>"+
      "<div>box3 の横移動距離:"+ary[2] +"=" + this[5][1]+"px, "+
      "box3 の縦移動距離:"+ary[3] +"=" + parseInt(this[5][1]/2)+"px</div>"+
      "<div>サイズ増減のための 2 つの乱数:<br />  "+this[6][0]+","+this[6][1]+"</div>"+
      "<div>box2 の横方向サイズ増減倍率、又は box3 の縦方向サイズ増減倍率:<br />  "+this[6][0] +"</div>"+
      "<div>box3 の横方向サイズ増減倍率、又は box2 の方向サイズ増減倍率:<br />  "+this[6][1] +"</div>"+
      "<div>box2 の移動に適用されたeasing:"+o.easing[parseInt(o.rnd[0][0]*11)]+"</div>"+
      "<div>box3 の移動に適用されたeasing:"+o.easing[parseInt(o.rnd[0][1]*11)] +"</div>"
    );
  };
  // animate ボタンがクリックされたら実行する。
  $("#animBtn").click(function(){
    var i=1;
    o.flag = ++o.cnt % 2; // 奇数回目(true) か、偶数回目(false )か?
    if (o.flag){ // 奇数回目ならば
      // 移動方向、移動距離、サイズ変更等に使用する乱数を発生させる。
      // o.rnd は乱数を使った各種プロパティを格納するオブジェクトである。
      o.rnd[0]=[Math.random(),Math.random()];
      // 乱数値の小数点第 1 ~ 4 位迄の各桁の数値が偶数ならば+を、
      // 奇数ならば-を o.rnd[i] に順に代入する。これにより 2 つのボックス
      // それぞれの横及び縦方向の移動方向をランダムに設定する。
      for (;i<5;i++)
          o.rnd[i] = parseInt(o.rnd[0][0] * Math.pow(10,i)) % 2 === 0 ? "+" : "-";
      // box2 と box3 の移動距離を設定 (0 ~ 199)
      o.rnd[5] =[parseInt(o.rnd[0][0]*200),parseInt(o.rnd[0][1]*200)];
      // box2 と box3 のサイズ変動倍率を設定 (-0.5 ~ +0.49999)
      o.rnd[6] =[o.rnd[0][0]-0.5,o.rnd[0][1]-0.5];
    } else {
        // 偶数回目では正負記号を反転させる
        for (; i<5; i++) o.rnd[i] = o.rnd[i]==="+" ? "-" : "+";
    }
    trans.call(o.rnd); // アニメーション開始
    insertLog.call(o.rnd); // アニメーションに係るログを表示する。
    $(this).blur(); // ボタンからフォーカスを外す。
  });

▲ToTop

6. javascript コード作成上留意したこと

HTML、CSS、Javascriptの役割分担

一部に style 属性を設けましたが、出来るだけ文書構造(HTML)、表示(CSS)及び動作(Javascript)は区別しました。

出来るだけ変数の数を減らしました

無名関数で括る必要はなかったのでトップレベルの変数はグローバルになります。そこで可読性をたかめるためにも、トップレベルの変数は 1 つにまとめました。具体的には基礎的な変数を var o オブジェクトプロパティにまとめて、関数以外のトップレベルの変数は var o だけとしました。

jQuery インスタンスの表記上の扱い

jQuery インスタンスを複数回使用する場合には、そのショートカットを作成し、かつ jQuery インスタンスと一目で分かるような独自の名称にしました。具体的には、変数名の 1 文字目に $ 記号を付けました。

ランダムなアニメーションとするために、乱数をさまざまに加工しました

移動する方向、移動距離、サイズの変動率、アニメに適用する easing 関数の選択などを、ランダムに設定しましたが、その各々に乱数を発生させるのではなく、発生させた 1 つの乱数を加工して使い回しました。

アニメ終了後に実行させる行為の扱い

jQuery(要素).animate メソッドでは当該アニメーション終了後に行わせる行為は、所定の方法で記述しなければなりません。或る行為を単にこのメソッド以降の行に既述すると、アニメーション実行中もコード進行は進みますから、アニメーション終了を待たずに当該行為が実行されてしまうからです。

久々に animate メソッドを使用したため、そのことに気がつくのに時間を要してしまい、アニメーション終了後の処置を相応しいタイミングでブラウザに反映させることがなかなか出来ず、徒労を重ねてしまいました。

ボタンクリックによる往復アニメの工夫

アニメーションを起動するボタンは簡潔に 1 つだけとしましたが、ここで作ったアニメーションには往路と復路があり、2 回のアニメーションが 1 セットになっています。そこで最初の段階では、click メソッドではなく toggle メソッドで往復アニメーションを実現させていました。

そして移動方向/距離もサイズ変更も、before と afterで、符号を変えて往復アニメを実現していました。

しかし、効率的なコード記述にすべきだと考え、click 数に応じた flag を用意して click メソッドを採用することにしました。

また、アニメの終点値には、"+=" 等の相対変動値を採用しましたが、これには大きな意味があります。絶対変動値指定を採用すると、コードは長大になるばかりで美しくないのです。相対変動値の採用は往復アニメーションにおける重要なポイントでしょう。

▲ToTop

 90%近いシェアを握っているインターネットエクスプローラの描画エンジンを利用したタブbrowser。沢山のタブbrowserがあるが、多機能、カスタマイズフリー、スクリプト利用等で一日の長がある。Gekkoエンジンへの対応も行われ、IEからの自立独立の方向に向かっている。2005年7月にはIE7が登場する見通しの中で、今後の発展が望まれる。

 多様なCSS作成支援機能を備えた、タグ入力式 HTML&CSS作成支援エディタ。スキンデザインもすっきりしている。テキストエディター上で作成するよりも確実で安全にタグ打ちが出来る。
文字コードを選べないのが欠点。

 StyleNote同様のタグ入力式 HTML&CSS 作成支援エディタ。長年使用してきたが現在StyleNoteに乗り換えつつある。

 クリップボード履歴情報を活用する為のソフト。画像まで履歴を取ってくれるのが嬉しい。このソフトを使わない日は絶対ない程に重宝し、愛用している。

 起動中のウィンドウの「コピーできない」説明文などの文字列を取得し、コピー可能な文字データにするツール。何かと便利。

 ストリーミングデータを保存することが出来るソフト。動画利用には不可欠なソフトだ。

 無料ながらレイヤー機能を有し、スクリプトによる拡張も可能な、sleipnir作者が提供している優れもの画像編集ソフト。

 画面キャプチャソフトと言えばこれに勝るものなし、ではないだろうか? 様々な取得方法を有しており、ブログ作成にもHomepage作成に不可欠だ。Jtrimと並んでWoodyBellsの作品。

 複数ファイルの同時編集は出来ないが、透過pngも作れる画像編集ソフト。
(以下当該サイトから抜粋)初心者にも簡単に操作が出来るフォトレタッチソフトです。多くの加工機能で画像に様々な効果を与えることができます。非常に軽快に動作するため、ストレスなく操作できます。

 Animation Gifファイルを作れる無料ソフト。

 キャプチャソフト。画面内にサイト全体が表示しきれない場合でも、これを使えば全体をキャプチャすることが出来る。

 画像処理。画像のフォーマット変換のみならず、色数やサイズ、圧縮率の変更まで一括処理できてしまう『BatchGOO!』は、大量の画像をまとめて処理したいときに大変便利なソフト。BMP, TIFF, JPEG, PCX, PNG の相互変換をはじめ、色数・サイズ・解像度の統一、JPEG圧縮率の調節など、ホームページ用の画像や携帯電話用の壁紙を揃えるのに抜群の相性を見せる。(Vectorの当該ソフト紹介頁より抜粋引用)

 名前から直ぐに想像が付くように画像のサイズを測るためのソフトだ。Homepage作成には欠かせない。2カラム、3カラムのレイアウトを行う場合に大変重宝する。

 ランチャーソフトは沢山あるが、中でもこれが一押しだ。2年以上使ってきたがその操作性には毎日満足している。これを使い始めてからデスクトップには一切のアイコンを表示することをやめてしまった。

 AdobeReader7によって、起動時間が長すぎるという長年のユーザーの不満はある程度解消した。そのためこの高速化ソフトは存在価値が低下してしまったかもしれない。AdobeReader6迄はこのソフトによる起動高速化で恩恵を受けてきた。

 IE専用が難点だが、様々なサイト内でIDやパスワードを入力するのに重宝するソフト。コンテキストメニューから簡単に起動できるのがGood! sleipnir等のIEの描画エンジンを利用しているブラウザでも使える。

 利用しているパソコンの諸元値を取得するには、このソフトがベストだ。インストール済みソフトの一覧が取得できるのも嬉しい。

 WMPは機能が豊富なだけ重い。RealPlayerも同様だ。そこでMedia Player Classicを使いたい。動作が軽快なだけではなく、対応しているファイル形式もすこぶる多く、これひとつで、wmvもrmも表示できてしまうのだから凄い! 数多あるMedia Playerの王様と言えるだろう。

 自宅でPCを起動しているときには必ず起動しているメディアプレーヤー。何かと過剰なWinampよりも、起動も速くスキンはシンプルだ。

 DivX, Xvid, Mov, Vob, Mpeg, Mpeg4, avi, wmv, dv, などの動画をDVD-Video形式に変換できるフリーソフト。クリックするとDVD関連ソフト紹介サイト=「DVDなToolたち」なるHomepageが開きます。

上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。