• ベストアンサー

画像とテキストの移動

画像とテキストを1セットにして(画像の下にテキストがある想定)、ある範囲の左から右に常に動かせつつ、マウスオーバーするとストップするようにさせたいのですが、JavaScriptでの実現方法を教えてください。 要件 ・上記の1セットはHTMLで設置 ・1セットのHTMLに対してのidの割り振りはしない ・10セットあるとして、流れていく過程で3セットずつ程度同時に見える想定 ・IE、FF、safari、Chrome、Operaで対応 ・移動はループさせる

質問者が選んだベストアンサー

  • ベストアンサー
  • fujillin
  • ベストアンサー率61% (1594/2576)
回答No.5

#3、#4です。 大変失礼しました!! >左から右に常に動かせつつ~~ になっていませんでしたね。(←今頃気がつきました。すんません。) ついでといっては何ですが、方向も個別に指定できるものにしてみました。 class="slider" または class="slider directionR" は左から右へ、 class="slider directionL" は右から左へ移動します。 おまけで、一番下の「revers」ボタンを押すたびに、下のdivの動く方向が逆転します。 <html> <head> <style type="text/css"> * { padding:0; margin:0; } div.slider {width:600px; height:140px; border:1px solid gray;} div.slider li { width:160px; float:left; list-style:none; } div.slider li img { width:160px; height:100px; } div.slider li span { display:block; text-align:center; } </style> <script type="text/javascript"> window.onload = function(){ $slider.initialize(); } var $slider = { initialize : function() { this.p = { elm:[], start:[], pos:[], dir:[], flag:[] }; var i=0, j, ul, li, divW, liW, cls, n, t; var div = document.getElementsByTagName('DIV'); while (e = div[i++]) { cls = e.className; if (cls=='slider' || cls.match(/^slider /)) { if (!divW) divW = wide(e); if(ul = e.getElementsByTagName('UL')[0]) { li = ul.getElementsByTagName('LI'); if (!n) liW = wide(li[0]), n = Math.floor(divW/liW) + 1; e.style.overflow = 'hidden'; e.style.psotion = 'relative'; ul.style.width = (divW + n*liW) + 'px'; ul.style.position = 'relative'; t = this.p, j = t.pos.length, t.elm[j] = ul; t.dir[j] = cls.match(/directionL/)?-1:1; t.start[j] = -liW*li.length, t.pos[j] = t.start[j]; t.flag[j] = true, ul.left = t.pos[j]; ul.onmouseover = (function(k) { return function(){$slider.stop(k);};})(j); ul.onmouseout = (function(k) { return function(){$slider.start(k);};})(j); for (j=0; j<n; j++) ul.appendChild(li[j % li.length].cloneNode(true)); } } } this.Tid = setInterval(this.timer, 30); function wide(e) { var w =e.currentStyle?e.currentStyle['width']:document.defaultView.getComputedStyle(e, null).getPropertyValue('width'); return w.replace('px',''); } }, timer : function() { var i = -1, p = $slider.p, t, step = 3; while (p.elm[++i]) { if (p.flag[i]) { t = p.pos[i] + p.dir[i]*step; if (p.dir[i] < 0 && t < p.start[i]) t = 0; if (p.dir[i] > 0 && t > 0) t = p.start[i]; p.elm[i].style.left = t, p.pos[i] = t; } } }, start : function(n) { this.p.flag[n] = true; }, stop : function(n) { this.p.flag[n] = false; } } </script> </head> <body> <div class="slider directionR"> <ul> <li><img src="image1.gif"><span>text1</span></li> <li><img src="image2.gif"><span>text2</span></li> <li><img src="image3.gif"><span>text3</span></li> <li><img src="image4.gif"><span>text4</span></li> </ul> </div> <br> <div class="slider directionL"> <ul> <li><img src="A.jpg"><span>説明1</span></li> <li><img src="B.jpg"><span>説明2</span></li> <li><img src="c.jpg"><span>説明3</span></li> </ul> </div> <button type="button" onclick="$slider.p.dir[1] *= -1">reverse</button> </body> </html>

big7980
質問者

お礼

すばらしいです。汎用性もあり、リバースまで追加していただけるなんて。 これで思ったものが実現できました。 度々のコーディングありがとうございました。

その他の回答 (4)

  • fujillin
  • ベストアンサー率61% (1594/2576)
回答No.4

#3です。こんにちは。 ご質問に『左から右に常に動かせつつ』とあったので、逆回転までは考慮していませんでした。 >逆回転バージョンは、「step = 3」を「-3」にするとなりますが、ループが >効かなくなります。 ご推察の通り、1回の進むピクセル数がstepですので、-3などとすれば逆方向に進むことになります。 仕組みとしては、表示に必要な長さ分の画像を先に並べておいて、それを動かしていき、端まで行ったら(一気に)巻き戻しています。見た目にはエンドレスで循環して見えますがそう見えるだけ。 進む方向を変えただけでは、その辺の制御がうまくいかなくなってしまいます。 実際には、現在表示している部分の位置(p.pos)が、常にp.start~0の間にあるようにしておかないと、端部に画像が無いところが表示されてしまうことになります。(p.startは必ず負数です) とりあえず、逆回転限定でよければ、 step = -3などとしておいて、その4行下の if (t > 0) t = p.start[i]; を if (t < p.start[i]) t = 0; に入替えてあげれば動作します。 順回転、逆回転が自由にできるようにするには、全体的に少し手を入れてあげないとならないですね。

  • fujillin
  • ベストアンサー率61% (1594/2576)
回答No.3

ご質問とは少し違うかも知れませんが… <div class="slider"> <ul> <li><img><span>text</span></li> <li><img><span>text</span></li>  ・・・・・・・・・ </ul> </div> の構成のソースを作成しておけば、これに対して実行されます。 *複数あっても可ですが、あまり多く設置すると負荷がかかるかも。 *表示できるリストの数を計算する都合上、divとliには必ずwidthを指定しておいてください。 (あまりよいサンプルではない気もしますが、まぁ、作ってみたので…) <html> <head> <style type="text/css"> * { padding:0; margin:0; } div.slider {width:600px; height:140px; border:1px solid gray;} div.slider li { width:160px; float:left; list-style:none; } div.slider li img { width:160px; height:100px; } div.slider li span { display:block; text-align:center; } </style> <script type="text/javascript"> window.onload = function(){ $slider.initialize(); } var $slider = { initialize : function() { this.p = { elm:[], start:[], pos:[], flag:[] }; var i=0, j, ul, li, divW, liW, n, t; var div = document.getElementsByTagName('DIV'); while (e = div[i++]) { if (e.className=='slider') { if (!divW) divW = wide(e); if(ul = e.getElementsByTagName('UL')[0]) { li = ul.getElementsByTagName('LI'); if (!n) liW = wide(li[0]), n = Math.floor(divW/liW) + 1; e.style.overflow = 'hidden', e.style.psotion = 'relative'; ul.style.width = (divW + n*liW) + 'px'; ul.style.position = 'relative'; t = this.p, j = t.pos.length, t.elm[j] = ul; t.start[j] = -liW*li.length, t.pos[j] = t.start[j]; t.flag[j] = true, ul.left = t.pos[j]; ul.onmouseover = (function(k) { return function(){$slider.stop(k);};})(j); ul.onmouseout = (function(k) { return function(){$slider.start(k);};})(j); for (j=0; j<n; j++) ul.appendChild(li[j % li.length].cloneNode(true)); } } } this.Tid = setInterval(this.timer, 30); function wide(e) { var w =e.currentStyle?e.currentStyle['width']:document.defaultView.getComputedStyle(e, null).getPropertyValue('width'); return w.replace('px',''); } }, timer : function() { var i = -1, p = $slider.p, t, step = 3; while (p.elm[++i]) { if (p.flag[i]) { t = p.pos[i] + step; if (t > 0) t = p.start[i]; p.elm[i].style.left = t, p.pos[i] = t; } } }, start : function(n) { this.p.flag[n] = true; }, stop : function(n) { this.p.flag[n] = false; } } </script> </head> <body> <div class="slider"> <ul> <li><img src="image1.gif"><span>text1</span></li> <li><img src="image2.gif"><span>text2</span></li> <li><img src="image3.gif"><span>text3</span></li> <li><img src="image4.gif"><span>text4</span></li> </ul> </div> 途中の文章とか <div class="slider"> <ul> <li><img src="A.jpg"><span>説明1</span></li> <li><img src="B.jpg"><span>説明2</span></li> <li><img src="c.jpg"><span>説明3</span></li> </ul> </div> </body> </html>

big7980
質問者

お礼

ありがとうございます。かなり求めるものと近いです。 逆回転バージョンは、「step = 3」を「-3」にするとなりますが、ループが効かなくなります。これは作りも変えないとだめでしょうか。(素人質問で申し訳ありません)

回答No.2

ふたたびごめん。べんりなきのうがつまったやつをつかえば かんたんかもしれないけど、けっきょくそれさえもつかいこなせないなら、 いらいしたほうがよいとおもう。 こじんてきには、そういうのはつかいたくないし、 つかわなくたって、うごかせるようになると、それはそれで、 おもしろいよ。 さいしょにあげたこーどをつかったら、ながくなっちゃった うごかしたり、とめたりのとりがーは、ぐちゃぐちゃ。 だめだなこれ。(ぜんかくくうはくははんかくに) <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"> <html lang="ja"> <head>  <meta http-equiv="Content-Script-Type" content="application/javascript">  <meta http-equiv="Content-Type" content="text/html; charset=utf-8">  <title>TEST</title>  <style type="text/css">  #MLIST {   width : 600px;   height: 230px;   border: 1px #800 solid;   list-style : none;   margin : 0;   padding : 0;   overflow : auto;  }  .part {   width : 200px;   height: 240px;   margin : 0;   padding : 0;   float: left;  }  .part ol {   list-style : none;  }  .photo {   width : 200px;   height : 200px;  }  .photo img {   width : 200px;   height : 200px;  }  .comment {   width : 200px;   height : 40px;   text-align: center;   font-size: 12px;   padding-top:10px;  }  </style> </head> <body>  <ul id="MLIST" onMouseover="MLIST.stop()" onMouseout="MLIST.start(MLIST.move)">   <li class="part">    <ol>     <li class="photo"><img src="./img/0.gif" alt="photo0" ></li>     <li class="comment">せつめい1</li>    </ol>   </li>  </ul> <script type="text/javascript"><!-- function Locator (x) {  this.left = x + 'px'; } function Starter (callbackfn) {  this.timerID = (function (o) {   return setInterval(function () { return callbackfn.call(o); }, o.interval);  })(this); } function Stopper () {  clearInterval(this.timerID); } function Timer ( n ) {  this.timerID = null;  this.interval = n; } Timer.prototype.start = function (listener) {  return Starter.call(this, listener); }; Timer.prototype.stop = function () {  return Stopper.call(this); }; var Hoge = function ( ) {  this.init.apply( this, arguments ); }; Hoge.prototype = new Timer; Hoge.prototype.constructor = Hoge; Hoge.prototype.init = function ( tid, step, interval ) {  var e = document.getElementById( tid );  if(! e) return;  e.style.overflow = 'hidden';  e.style.position = 'relative';  this.e = e;  this.s = step;  this.interval = interval;  this.reset(); }; Hoge.prototype.addPart = (function ( tag ) {  return function ( ary ) {   var cnt = 0, o, p, i;   while( o = ary[ cnt++ ] ) {    i = tag( 'img' ), i.src = o[0], i.alt = o[1];    this.e.appendChild(     tag( 'li', 'part',      tag( 'ol', '',       tag( 'li', 'photo', i),       tag( 'li', 'comment', o[2] )      )     )    );   }   this.reset();  }; })(   function ( tag, cs, c1, c2 ) {    var d = document;    var e = d.createElement( tag );    cs && (e.className = cs);    c1 && e.appendChild( 'string' == typeof c1 ? d.createTextNode( c1 ): c1 );    c2 && e.appendChild( 'string' == typeof c2 ? d.createTextNode( c2 ): c2 );    return e;   }  ); Hoge.prototype.reset = (function ( get ) {  return function ( ) {   this.min = this.max = this.e.offsetWidth;   var cnt = 0, o;   this.ch = get( this.e );      while( o = this.ch[ cnt++ ] ) {    o.style.position = 'absolute';    Locator.call( o.style, this.min -= o.offsetWidth);   }  }; })(   function ( e ) {    var cnt = 0, ch = [ ], o;    while( o = e.childNodes[ cnt++ ] ) o.nodeType == 1 && ch.push( o );    return ch;   }  ); Hoge.prototype.move = function ( ) {  var cnt = 0, o, x;  while( o = this.ch[ cnt++ ] ) {   if( (x = o.offsetLeft + this.s) >= this.max ) x = this.min;   Locator.call( o.style, x);  } } var ary = [  [ './img/1.gif', '*', 'せつめい1' ],  [ './img/2.gif', '*', 'せつめい2' ],  [ './img/3.gif', '*', 'せつめい3' ],  [ './img/4.gif', '*', 'せつめい4' ],  [ './img/5.gif', '*', 'せつめい5' ],  [ './img/6.gif', '*', 'せつめい6' ] ];  var MLIST = new Hoge( 'MLIST', 4, 50 ); MLIST.addPart( ary ); MLIST.start( MLIST.move ); //--> </script> </body> </html>

big7980
質問者

お礼

たびたびのご回答ありがとうございます。 なるほど、誰かにJSのプロトタイプは業務上はあまり使わないほうがいいと言われたのですが、それに似ている理由なのかも知れませんね。 いただいたタグでも大分ヒントになりました。 これをもとに少しいじってみます。

回答No.1

ごめんなさい。おそらくものすごくなが~~~いぷろぐらむに なりそうなので、HTMLぶぶんだけでも、かいてみました。 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"> <html lang="ja"> <head>  <meta http-equiv="Content-Script-Type" content="application/javascript">  <meta http-equiv="Content-Type" content="text/html; charset=utf-8">  <title>TEST</title>  <style type="text/css">  </style> </head> <body>  <ul>   <li>    <ol>     <li><img src="./img/0.gif" width="200" height="200"></li>     <li>せつめい</li>    </ol>   </li>  </ul> <script type="text/javascript"><!-- //ここにかいてもらう。(ぜんかくくうはくははんかくにしてね) //--> </script> </body> </html> ちなみに、ぷろのひとは、どれぐらいでかきあげるのでしょうか? 1じかん?2じかん?しろうとは、その10ばい、ひつようだとして う~~~~~ん、やっぱり、ぼらんてぃあで、かけそうにありません。 どこぞの、ぎょうしゃに、いらいされてはどうでしょう。 ぶぶんてきに、おぶじぇくとしこう てきなかんがえで、 みんなにかきあげてもらうとか・・。でもじかんがものすごくかかりそう! かこに、そんけいするひとが、かいていたこーどの、こぴぺです。 たいまーに、あたるぶぶんです。こうやって、ぶひんをだしあえば なんとかなるかもしれなくもいかもしれない。 function Starter (callbackfn) {  this.timerID = (function (o) {   return setInterval(function () { return callbackfn.call(o); }, o.interval);  })(this); } function Stopper () {  clearInterval(this.timerID); } function Timer ( n ) {  this.timerID = null;  this.interval = n; } Timer.prototype.start = function (listener) {  return Starter.call(this, listener); }; Timer.prototype.stop = function () {  return Stopper.call(this); };

big7980
質問者

お礼

ありがとうございます。 左右に動くスクリプトは簡単そうでしたので、少しのカスタマイズで済むかと考えていましたが、大変なんですね。 他にも良い案がでましたら、ご教示いただけますと助かります。

big7980
質問者

補足

たびたび申し訳ありません。 こんな記述を見つけたのですが、カスタマイズで実現できませんでしょうか? http://nettuts.s3.amazonaws.com/413_newsTicker/demo/simpleTicker.html <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script> <script type="text/javascript"> $(function() { //cache the ticker var ticker = $("#ticker"); //wrap dt:dd pairs in divs ticker.children().filter("dt").each(function() { var dt = $(this), container = $("<div>"); dt.next().appendTo(container); dt.prependTo(container); container.appendTo(ticker); }); //hide the scrollbar ticker.css("overflow", "hidden"); //animator function function animator(currentItem) { //work out new anim duration var distance = currentItem.height(); duration = (distance + parseInt(currentItem.css("marginTop"))) / 0.025; //animate the first child of the ticker currentItem.animate({ marginTop: -distance }, duration, "linear", function() { //move current item to the bottom currentItem.appendTo(currentItem.parent()).css("marginTop", 0); //recurse animator(currentItem.parent().children(":first")); }); }; //start the ticker animator(ticker.children(":first")); //set mouseenter ticker.mouseenter(function() { //stop current animation ticker.children().stop(); }); //set mouseleave ticker.mouseleave(function() { //resume animation animator(ticker.children(":first")); }); }); </script>

関連するQ&A

専門家に質問してみよう