日記ブログ、または雑多なメモ
2014年1月3日

埋め込みwebギャラリー改造 javascript/jqueryとの闘い






 やばいやばいといいつつ……、結局ちょぼちょぼ原稿描きつつ、埋め込みギャラリーの改造を続けた結果……、一応望み通りの動きになった。

 構造としては、

jquery.swipeshow.js ”PCでもスマホでもスワイプできるどっちかというと小型設置向け、オートスライドショーギャラリー。 ただしポップアップ機能なし”
jquery.fancybox.js ”背景暗転ポップアップできるプラグイン。 動作がデフォルトで小気味よい”

 を合体させてみた。



 最初、swipeshowの画像表示部分である<img>タグを<a>タグで囲み、fancyboxを通常通りの手順でフックさせて、あっという間に完成~~♪♪
……とか思ったらスワイプ/ドラッグと同時にクリックが発生。 どうも<a>タグ経由、もしくはonClick経由ではどうしてもそうなってしまうらしい。
で、結局<a>タグを使わない方法でクリック/スワイプ検知部分を自分で組むしかなくなり(いや別に組まなくてもいいんだが)、今に至る。


 以下、悩んだ部分。 全部悩んだといえば悩んだんだが、特に悩んだ部分。

*クリックじゃないの!!ドラッグなの!!!!!
>条件をクリック側に入れるのではなく、ドラッグ処理側に入れたらすんなりいった。 まあ、比較的

*よし。 <div>でフックだ。 しかし「id」でやるとHTMLの実装が大変そうなので、「class」でスマートにやりたい。 でもそうなるとjavascript側のソースがなんかすげえ大変そう
>地味に検索しまくりなるべく新しい正確そうなコードをコピペしまくり、改造しまくって動くものを取捨選択合体

*「class」で動くようになったが、引数の渡しは「title」とかでなく独自のタグが使いたい
>javascript側でthis.getAttribute("独自タグ");とかやると拾える

*mousedown mouseupなどを使って組んだらスマホで反応しなくなった
>touchstart touchendなどのタッチデバイス用の処理が必要

*fancyboxが最初のクリック時には起動せず、2回目以降で起動する
>クリック処理のところだけではなく、functionの始めに一度fancyboxをイニシャライズの意味で起動させておく必要がある

*どう見てもタッチデバイス用に組めているはずなのに、まともに動かない
>座標はclientX(Y)とかではなくpageX(Y)で取得(たぶん)

*なぜか…というかうっすらわかるような気もするが、最終的にどうがんばってもタップでは直接fancyboxをcallしても発火しない
>無理やりclick発行で発火


まあ……もう全部わけわからんかったんだが…とりあえず、デバグにchrome最高であった。
特にデベロッパーツールのtouch device emurationはすごい。 助かりましたよ。
その他、各jsライブラリのバージョンが微妙にちょっと違ったりしても起動しなかったりするのでその辺も注意みたいである。


以下、関連ヘッダ
    <link href="css/swipeshow/jquery.swipeshow.css" rel="stylesheet" />
    <link href="css/swipeshow/style.css" rel="stylesheet" />
    <link href="css/swipeshow/slideshow-theme.css" rel="stylesheet" />
    <link rel="stylesheet" type="text/css" href="css/jquery.fancybox.css">
    <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.1/jquery.min.js"></script>
    <script src="js/swipeshow-master/jquery.swipeshow.min.js"></script>
    <script src="js/jquery.fancybox.js"></script>


以下、javascriptソース
<script type="text/javascript">
jQuery(function ($) {
  'use strict';
  var chkTouch = ('ontouchstart' in window); // タッチデバイスかどうか?
  var mypopup = document.getElementsByClassName('mypopup'), // classから要素取得
  mypopupCount = mypopup.length, // cache the length
  i;
  function startDrag(evt) { // ドラッグorクリックスタート
        var diffX = evt.pageX - this.offsetLeft,
        diffY = evt.pageY - this.offsetTop,
        that = this;
        var diff ;
        $(that).fancybox({'href':that.getAttribute("rel")}); // fancybox事前発行
        document.addEventListener('touchend', stopDrag);
        document.addEventListener('touchmove', moveAlong);
        document.addEventListener('mouseup', stopDrag);
        document.addEventListener('mousemove', moveAlong);
        function stopDrag(evt) { // ボタンアップ
            $(that).trigger("click"); // 強制クリック発行(fancyboxのタップ起動不能対策)
            document.removeEventListener('mouseup', stopDrag);
            document.removeEventListener('touchend', stopDrag);
            document.removeEventListener('touchmove', moveAlong);
            document.removeEventListener('mousemove', moveAlong);
        }
        function moveAlong(evt) { //ドラッグ中
            diff = Math.abs(evt.pageX - diffX);
            if ( diff > 1 ) { // 位置がずれてたらドラッグしている
              evt.preventDefault(); // スクロール抑制
              $(that).off('click.fb-start'); // fancybox起動抑制
              $(that).unbind('click'); // クリック発行取り消し
            }
        }
        function display(evt) { // fancybox起動 relタグの中身(画像URL)をhrefに渡す
            $(that).fancybox({'href':that.getAttribute("rel")});
        }
    }
    for (i = 0; i < mypopupCount; i += 1) { // 複数ゲットしたclassをforで順番に処理
     if ( chkTouch == false ) {
       mypopup[i].addEventListener('mousedown', startDrag); // PC
     } else {
       mypopup[i].addEventListener('touchstart', startDrag); // タッチデバイス
     }
    }
});
</script>
汚いソースだなぁ。
試行錯誤、あの手この手のトライの変遷で、処理的に重複してる部分があるかもではある。
※なぜかサンプルページではiPhone上でスワイプ時にスクロールが発生したので「moveAlong()」に「evt.preventDefault();」追加



以下、HTML。 classが"mypopup"だと発動。 "rel"に表示させたい画像のURL
 <div class="slideshow swipeshow">
    <ul class="slides">
      <li class="slide">
        <div class="mypopup" rel="ugallery_cvt/1-big.jpg"><img src="ugallery_cvt/1.jpg" alt="" /></div>
      </li>
      <li class="slide">
        <div class="mypopup" rel="ugallery_cvt/2-big.jpg"><img src="ugallery_cvt/2.jpg" alt="" /></div>
      </li>
      <li class="slide">
        <div class="mypopup" rel="ugallery_cvt/3-big.jpg"><img src="ugallery_cvt/3.jpg" alt="" /></div>
      </li>
      <li class="slide">
        <div class="mypopup" rel="ugallery_cvt/4-big.jpg"><img src="ugallery_cvt/4.jpg" alt="" /></div>
      </li>
      <li class="slide">
        <div class="mypopup" rel="ugallery_cvt/5-big.jpg"><img src="ugallery_cvt/5.jpg" alt="" /></div>
      </li>
      <li class="slide">
        <div class="mypopup" rel="ugallery_cvt/6-big.jpg"><img src="ugallery_cvt/6.jpg" alt="" /></div>
      </li>
      <li class="slide">
        <div class="mypopup" rel="ugallery_cvt/7-big.jpg"><img src="ugallery_cvt/7.jpg" alt="" /></div>
      </li>
    </ul>
    <!--<button class='previous'></button>
    <button class='next'></button>-->
    <div class='dots'></div>
  </div>
  <script>
    (function($) {
      $(".version").text($.swipeshow.version);
      $(".slideshow").swipeshow({ mouse: true, interval: 6000 });
    })(jQuery);
  </script>


 以上。


 サンプルページはこちら (deleted)。

  chrome(31.0.1650.63 m)
chrome touch device emuration
IE10
seamonkey 2.23
firefox 26.0
iPhone5 iOS7 safari
で動作確認。


 ところで、なんでここまでしたかといえば。
swipeshow側に小さい画像、fancyboxで巨大版画像を表示できれば、管理的に「ほら、ここに立派なギャラリーがあるじゃん!!」と言えて、のちのち楽になるはず。 と思ったからである。 画像の用意はphpで自動変換マシンを作ったので、やることはフォルダに新しい絵を放り込むだけ!あとは最新7枚を自動ftpアップロードしてくれるのだ!!むふふ……ふぅ…


 小さい方の画像で平均25KBほどなので、7つで180KBになる。 でかい絵をそのまま置いてた時は1MBくらいあったんだな……おそろしい。 14個くらい置きたい気もするがトップページが400KBは重いよなぁ……やっぱり。 一気読みせずに、非同期で画像をロードしてくれるスワイプ可能ギャラリーが欲しいーーー


 そういえばjavascript、javascriptと言ってるが、jQueryで起動してるので、これはjqueryで組んだというべきなのか。
今に至ってもよくわかっていないが動いてるので良いとする。

 しかし、なんでこの界隈では「発火」とか「fire」とかいうんだろう。

使っちゃうよな。


原稿描こう。




コメント欄
(投稿なし)

コメントなどありましたらこちらからどうぞ
名前
内容
 ※名前、内容ともに入力必須です
- C'sGallery Blogっぽく見えるシステム3.2 -
小武 (管理人) eta2@tim.hi-ho.ne.jp