まだプログラマーですが何か?

プログラマーネタとアスリートネタ中心。たまに作成したウェブサービス関連の話も http://twitter.com/dotnsf

タグ:animate

jQuery を使って HTML の iframe の内側コンテンツを、iframe の外側の JavaScript からスクロールさせる方法を紹介します。

今回は2つの HTML ファイル(main.html と sub.html)を使います。main.html が iframe の外側(というか、iframe を記述する側)のファイルで、main.html の中の iframe に sub.html が指定されて埋め込まれて表示される、という関係だと想定します。sub.html はどんな内容でも構いませんが、強制スクロールさせて表示することを想定しているので、それなりに縦長の、普通に見ても縦スクロールさせないと全体が見えないくらいの大きさのページを使ってください:
2017113001

一方、iframe の外側である main.html が今回の主役で、main.html 内の JavaScript で sub.html をスクロールさせて表示させることが今回の目的です。実現するためには以下のような内容で記述します:
<html>
<head>
<script src="https://code.jquery.com/jquery-2.0.3.min.js"></script>
<script>
$(function(){
  $('#sub').load( function(){
    iframe_scroll( 100 );
  });
});

function iframe_scroll( top ){
  //. 「0.8 秒で 100 ピクセルスクロールし、0.2 秒待つ」を繰り返す
  $('body,html', $('#sub').contents() ).animate( {scrollTop: top}, 800, 'swing' );
  setTimetout( iframe_scroll, 1000, top + 100 );
}
</script>
<title>main</title>
</head>
<body>
<h1>main</h1>
<hr/>
<iframe id="sub" src="./sub.html" width="90%" height="50%"></iframe>
</body>
</html>

jQuery を使って、まず sub.html がロードされた直後に( $('#sub').load() 関数内で)iframe_scroll 関数を実行しています。この関数では iframe 要素のコンテンツを取り出し、animate 関数を使ってスクロールさせています。この例では 0.8 秒かけて 100 ピクセル下にスクロールし、0.2 秒(1000 ミリ秒 - 800 ミリ秒)止まって繰り返す、という例を実装しています。

なお、sub.html をローカルで用意する代わりに外部コンテンツ(http://www.xxx.com/xxxxx.html など)を指定した場合、iframe 内に表示はされますが、クロスドメイン制約にかかって iframe 内の要素にアクセスすることができず、スクロールは行われません。ご注意ください。


HTML 内のオブジェクトを移動させるには jQuery の animate メソッド を使うのが一般的(というか簡単)ですが、CSS3 の transition を使ってもできます。

プログラマー/デベロッパーの立場だと jQuery を使うことは珍しくないんですが、CSS はちと遠い存在で、基本は理解しているつもりでしたが、あまり接することがありませんでした。いい機会なので勉強がてら使ってみました。


さて、目的は似てるけどアプローチの異なる2つの手法、その違いはどこにあるのでしょう?

簡単に言えば animate は CPU 処理、transition は GPU 併用の処理になります。PC だと見た目にもあまり差はないかもしれませんが、比較的 CPU 性能の劣るスマホ(それもちと古めの)だと、この差がバッチリでそう。グラフィックチップを併用することで非力なCPU環境でもスムーズなアニメーション処理が実現できます。また見た目に差がなくてもCPUの負荷を軽減することにもなります。


実際に2種類のメソッドで同じアニメーションを実装したのが以下の例です。上の "Animate" をクリックすると jQuery.animate で、下の "Transition" をクリックすると CSS3.transition で、それぞれ重ねあわせスライドスクロール処理が行われます。PC ブラウザだとあまり差を感じないかもしれませんが、非力な環境ほど下の方がスムーズな動きになるはず。



Animate









Transition










ソースコード全文はこのページのソースを参照していただきたいのですが、大まかにはこんな感じになります:

共通の CSS クラス:
<style type="text/css">
.c1{
	position: absolute;
	z-index: 1;
	left: 100px;
	opacity: 1;
	width: 100px;
	height: 100px;
	background: yellow;
}
.c2{
	position: absolute;
	z-index: 0;
	left: 100px;
	opacity: 1;
	width: 100px;
	height: 100px;
	background: red;
}
</style>


jQuery.animate を使った場合の HTML & JavaScript コード:
<a  href="javascript:void(0);" id="aa">Animate</a>
<div  class="c1"></div>
<div  id="c2a" class="c2"></div>
<script type="text/javascript">
var ba = true;
$('#aa').on('click', function(){
	ba = !ba;
	var l = 200;
	if( ba ){ l = 100; }
	$('#c2a').animate(
		{ left: l + 'px' },
		{ duration: '700', easing: "linear" }
	);
});
</script>


CSS3.transition を使った場合の HTML & JavaScript コード:
<a  href="javascript:void(0);" id="at">Animate</a>
<div  class="c1"></div>
<div  id="c2t" class="c2"></div>
<script type="text/javascript">

var bt = true;
$('#at').on('click', function(){
	bt = !bt;
	var l = 200;
	if( bt ){ l = 100; }
	$('#c2t').css({
		left: l + 'px',
		WebkitTransition: 'left 0.7s linear',
		MozTransition: 'left 0.7s linear',
		MsTransition: 'left 0.7s linear',
		OTransition: 'left 0.7s linear',
		transition: 'left 0.7s linear'
	});
});
</script>

どちらのケースもクリック時にトグルのような動きをするのでそのための余分なコードがありますが、jQuery.animate では左座標(left)を指定して 700 ミリ秒でリニアにアニメートを、CSS3.transition でも左座標と効果(transition)を指定して 0.7 秒間で遷移するように css を変えています。違いはこの2箇所です。

もちろん全てのケースで有用というわけではないと思います。またこの例はかなりシンプルな内容なので違いが少なく見えていますが、現実的にはそう簡単にはいかないことはあると思います。ただ後者が使える環境であれば後者にすべきなのかな。



 

このページのトップヘ