Cross Browser のための DHTML


・DHTML版 Marquee

IE 特有のタグに MARQUEE がありますが、このタグと同様な動作を JavaScript で 記述することができます。

こんちは
こんばんわ
Hello
Good-bye

上の「開始」ボタンを操作すると4種類のメッセージが色々な方向から様々なスピードで流れます。 「停止」ボタンを操作するとメッセージが停止します。

#> IE の MARQUEE は動作をカスタマイズするための様々な属性がありますが、 全ての動作を実装するのは面倒なので単純化しています。 f(^^; 別名、手抜き...

以下は Marquee のコードです。

<script language="JavaScript1.2"><!--
// クリップ領域管理オブジェクト
//   MqPane(left,top,width,height);
//     left,top     : クリップ領域の位置( 左上コーナ )
//     width,height : クリップ領域の幅と高さ
function MqPane(left,top,width,height){
  this.left   = left;       this.top    = top;
  this.width  = width;      this.height = height;
  this.bottom = top+height; this.right  = left+width;
}
// クリップメソッド
//   clip(mqc);
//     mqc : MqControl オブジェクト
MqPane.prototype.clip = function(mqc){
  var left   = mqc.x<this.left?(this.left-mqc.x):0;
  var right  =(mqc.x+mqc.width )>this.right?
                (this.right -mqc.x):mqc.width;
  var top    = mqc.y<this.top ?(this.top -mqc.y):0;
  var bottom =(mqc.y+mqc.height)>this.bottom?
                (this.bottom-mqc.y):mqc.height;
  setDivClip(mqc.div,top,right,bottom,left);
}
// 可視領域判定メソッド
//   bool = isVisible(mqc);
//     mqc    : MqControl オブジェクト
//     戻り値 : true = 見える部分がある, false = 全く見えない
MqPane.prototype.isVisible = function(mqc){
  if(   this.left>=(mqc.x+mqc.width )||this.right <=mqc.x
     || this.top >=(mqc.y+mqc.height)||this.bottom<=mqc.y)
  {
    if(mqc.visible){
      setDivVisibility(mqc.div,false); mqc.visible = false;
    }
    return false;
  } else {
    if(!mqc.visible){
      setDivVisibility(mqc.div,true ); mqc.visible = true;
    }
    return true;
  }
}
// メッセージ用レイア管理オブジェクト
//   MqControl(div,pane,dir,d);
//     div  : 移動するレイアオブジェクト
//     pane : MqPane オブジェクト
//     dir  : 移動方向
              MqControl.UP    = 1; // 下から上
              MqControl.DOWN  = 2; // 上から下
              MqControl.LEFT  = 3; // 右から左
              MqControl.RIGHT = 4; // 左から右
//     d    : 1回あたりの移動量( pixel )
function MqControl(div,pane,dir,d){
  this.pane   = pane;
  this.div    = div;
  this.width  = getDivWidth (div);
  this.height = getDivHeight(div);
  switch(dir){
  case 1: // UP
    this.dx = 0; this.dy = -d;
    this.x  = (pane.width-this.width)/2+pane.left;
    this.y  = pane.top+pane.height;
    this.doAction = this.doUpDown;
    break;
  case 2: // DOWN
    this.dx = 0; this.dy = d;
    this.x  = (pane.width-this.width)/2+pane.left;
    this.y  = pane.top-this.height;
    this.doAction = this.doUpDown;
    break;
  case 3: // LEFT
    this.dx = -d; this.dy = 0;
    this.x  = pane.left+pane.width;
    this.y  = (pane.height-this.height)/2+pane.top;
    this.doAction = this.doLeftRight;
    break;
  case 4: // RIGHT
    this.dx = d;  this.dy = 0;
    this.x  = pane.left-this.width;
    this.y  = (pane.height-this.height)/2+pane.top;
    this.doAction = this.doLeftRight;
    break;
  }
  this.visible = false;
  this.pane.clip(this);
  moveDivTo(this.div,this.x,this.y);
}
// メッセージ移動メソッド( 上下 )
//   bool = doUpDown();
//     戻り値 : true = 1サイクル終了, false = 移動中
MqControl.prototype.doUpDown = function(){
  this.y+=this.dy;
  if(!this.pane.isVisible(this)){
    this.y = this.dy>0?
               (this.pane.top-this.height):this.pane.bottom;
    this.pane.clip(this);
    moveDivTo(this.div,this.x,this.y);
    return true;
  }
  this.pane.clip(this);
  moveDivTo(this.div,this.x,this.y);
  return false;
}
// メッセージ移動メソッド( 上下 )
//   bool = doLeftRight();
//     戻り値 : true = 1サイクル終了, false = 移動中
MqControl.prototype.doLeftRight = function(){
  this.x+=this.dx;
  if(!this.pane.isVisible(this)){
    this.x = this.dx>0?
               (this.pane.left-this.width):this.pane.right;
    this.pane.clip(this);
    moveDivTo(this.div,this.x,this.y);
    return true;
  }
  this.pane.clip(this);
  moveDivTo(this.div,this.x,this.y);
  return false;
}
// --></script>

この文字の部分は「ライブラリ集」で紹介している関数です。 上のスクリプトでは記述されていませんが、実際には「ライブラリ集」を参照して追加してください。

各オブジェクトのメソッドとプロパティを以下に示します。

クリップ領域管理オブジェクト

コンストラクタ
  - メッセージが見える矩形領域を定義します
  MqPane(left,top,width,height);
    left,top     : クリップ領域の位置( 左上コーナ )
    width,height : クリップ領域の幅と高さ

クリップメソッド
  - メッセージをクリップします
  clip(mqc);
    mqc : MqControl オブジェクト

可視領域判定メソッド
  - メッセージの可視状態を判定し、visibilityの設定も行います
  bool = isVisible(mqc);
    mqc    : MqControl オブジェクト
    戻り値 : true = 見える部分がある, false = 全く見えない

メッセージ用レイア管理オブジェクト

コンストラクタ
  - 表示するメッセージを管理します
  MqControl(div,pane,dir,d);
    div  : 移動するレイアオブジェクト
    pane : MqPane オブジェクト
    dir  : 移動方向
           MqControl.UP    = 下から上
           MqControl.DOWN  = 上から下
           MqControl.LEFT  = 右から左
           MqControl.RIGHT = 左から右
    d    : 1回あたりの移動量( pixel )

メッセージ移動メソッド
  - メッセージを移動します
  bool = doAction();
    戻り値 : true = 1サイクル終了, false = 移動中

使い方

位置(20,100)の位置にあるサイズ(300,50)の矩形領域に、 "Hello World" を横( 右から左 )に移動する例を以下に示します

<style type="text/css"><!--
/* クリップ領域のスタイルの設定 */
.cliparea{ position:absolute; }
#c {
  left:20; top:100;
  width:300; height:50; clip:rect(0 300 50 0);
  background-color:#333399; layer-background-color:#333399;
}
/* メッセージのスタイルの設定 */
.marquee    { position:absolute; visibility:hidden; }
.marquee TD { font-size:18pt; font-weight:600; }
#m1 TD{ color:#99cc99; font-style:italic; }
--></style>
<script language="JavaScript"><!--
// 旧バージョン用のダミー関数
function init(){}
function closure(){}
// --></script>
<script language="JavaScript1.2"><!--
// ブラウザ固有の問題対応
if(document.all){
  var s='';
  if(document.getElementById){
    if(navigator.userAgent.indexOf('Mac')!=-1){
      // Mac版 IE5 は座標計算に問題があるので
      // マージン幅を 0 にしてバグ回避する
      s+='BODY{ margin:0px; }\n';
    }
  } else {
    // IE4 はレイアの幅を定義しないとページの端まで
    // 拡張されるので最小限の幅に調整するように
    // width:1; を指定しておく
    s+='.marquee  { width:1px; }\n';
  }
  if(s!=''){
    document.write(
      '<style type="text/css">\n'+s+'<\/style>\n'
      );
  }
}
// 各種変数
mqc        = null; // MqControl オブジェクト( メッセージ )
mqTid      = null; // タイマ識別子
mqInterval = 50;   // インターバル時間( msec )

// 初期化( 共通 )
function init(){
  // Marquee オブジェクトの作成
  mqc = new MqControl(
              initDivSize(getDivFromName('m1')),
              new MqPane(20,100,300,50),
              MqControl.LEFT, 5);

  // 移動開始
  doMq();
}
// 終了処理
function closure(){
  if(mqTid){ clearTimeout(mqTid); mqTid = null; }
}
// 実行
function doMq(){
  if(mqc){
    mqc.doAction();
    mqTid = setTimeout('doMq();',mqInterval);
  }
}
// --></script>
<body ... onLoad="init();" onUnload="closure();">
    :
<div class="cliparea" id="c"></div>
<div class="marquee" id="m1">
<table border=0 cellspacing=0 cellpadding=0><tr><td nowrap>
Hello World
</td></tr></table>
</div>
    :

例によって、この文字の部分は「ライブラリ集」で紹介している関数です。

また、この文字の部分はこのサンプル特有の部分です。

他の領域と区別させるために Marquee のクリップ領域にレイア( id="c" の DIVタグ ) を使用していますが、なくても良いです。

表示するメッセージは visibility が hidden なレイア( id="m1" の DIVタグ )で、 文字の内容や形状は適当に調整します。

#> もし、旧バージョンのブラウザとも同居できるようにしたければ onLoad イベント以降にレイアを生成した方が良いかもしれません。

メッセージの移動スピードは mqInterval変数で調整します。

このサンプルでは onLoad イベント時から動作するようにしていますが、 もし、何らかのトリガーで開始するようにするなら、init 関数内に記述している doMq 関数の呼出を外して開始したいタイミングで呼出し、 停止したいタイミングで closure 関数を呼び出します。

また、このサンプルでは単一のメッセージの動作ですが、 複数のメッセージを同時に表示したい場合は、 このファイルのスクリプトを参考にして下さい。


応用例 - Stuff Roll

表示するメッセージを複数行にして下から上に移動させると、 Stuff Roll になったりします(笑)。

スクリプトは殆ど前述のサンプルと同じなので省略します。 f(^^;

title
"JavaScript Tips Collection"

Author
"hagi3"

Produced by
"hagi3"

Page designed by
"hagi3"

Copyright
(c) 2001 ShinSoft. All rights reserved.


注意事項


Copyright(c) 1998 - 2001 hagiwara. All rights reserved.