PhotoSwipeがとても良いからwordpressで実装

少し前に、何かでブログを徘徊してたらとても良い感じのモーダルウィンドウがあったので調べてみたので。
そしたらフリーで公開されていたので、実装してみました。

広告

モバイルフレンドリーなPhotoSwipeをwordpressで実装する

このPhotoSwipeというライブラリは、スマホのスワイプに対応していて、動きもGOOD。
PCので表示では全画面や、拡大ボタンも付く。
(このブログでは全画面表示は切ってます)

動作は下の画像をクリックでどんぞ。

CB750

CB750-2

BMWの画像

BMWの画像-2

実装編

さて実装ですが、wordpress用のプラグインもあったのですが、過去の記事だと動かなかった。
エラーが起こってた様子も無かったからそーゆー設定だと思うのですが、どうせならイージーに過去の記事まで対応させたいと思うのが人のサガ。

なので、実装用のコードは自分で書きます。

    if ( is_singular() ){
        wp_enqueue_style( 'photoswipe-style', get_stylesheet_directory_uri() . '/library/photo-swipe/photoswipe.min.css', array(), '1.0.0' );
        wp_enqueue_style( 'psdefault-style', get_stylesheet_directory_uri() . '/library/photo-swipe/default-skin/default-skin.min.css', array(), '1.0.0' );
    }

    if ( is_singular() ){
        wp_enqueue_script( 'photoswipe-js', get_stylesheet_directory_uri() . '/library/photo-swipe/photoswipe.min.js', array(), '1.0.0', true );
        wp_enqueue_script( 'photoswipeui-js', get_stylesheet_directory_uri() . '/library/photo-swipe/photoswipe-ui-default.min.js', array(), '1.0.0', true );        
    }

まずはライブラリの読み込み。
上はシングルページのみでの読み込みです。

jsとcssを分けてますが、一緒でも当然大丈夫。

この時点で意味が分からなければ、プラグインで良いと思う。

上ではテーマフォルダにlibrarディレクトリを作って、そこに入れてます。

そんで次は、発火用のデータを記事に差し込みます。

function PhotoSwipe_fanc( $content ) {
    
    $pattern = "/(<a[^>]*?href=['\"][^'\"]+?\.(?:bmp|gif|jpg|jpeg|png)(\?\S{0,}){0,1}['\"][^\>]*)>/i";
    $replacement = '$1 class="photo-swipe">';
    $content = preg_replace($pattern, $replacement, $content);
    
    if ( ! preg_match_all( '/<img [^>]+>/', $content, $matches ) ) {
        return $content;
    }
 
    $selected_images = $attachment_ids = array();
 
    foreach( $matches[0] as $image ) {
        if ( preg_match( '/wp-image-([0-9]+)/i', $image, $class_id ) &&
            ( $attachment_id = absint( $class_id[1] ) ) ) {
            $selected_images[ $image ] = $attachment_id;
            $attachment_ids[ $attachment_id ] = true;
        }
    }
 
    if ( count( $attachment_ids ) > 1 ) {
        update_meta_cache( 'post', array_keys( $attachment_ids ) );
    }
 
    foreach ( $selected_images as $image => $attachment_id ) {
        $content = str_replace( $image, PhotoSwipe_fanc_set( $image, $attachment_id ), $content );
    }
 
    return $content;
}
add_filter('the_content', 'PhotoSwipe_fanc');

function PhotoSwipe_fanc_set( $image, $attachment_id ){
    $image_src_full = wp_get_attachment_image_src( $attachment_id,'full' );
    if($image_src_full){
        $attr = 'data-size="'.$image_src_full[1].'x'.$image_src_full[2].'"';
        $image = preg_replace( '/<img ([^>]+?)[\/ ]*>/', '<img $1' . $attr . ' />', $image );
    }
    return $image;   
}

function.phpでthe_contentにフック。
上ではsrcsetを吐き出すコードを真似てdata属性にfullサイズ画像の大きさを渡します。

あと、発火用のclassも。
別にclassはなくても出来るんだけど、あったほうが何かと使えるかな?・・・と思って挿入。

次はjquery。

if( $('a.photo-swipe')[0] ){
        
    $('<div class="pswp" tabindex="-1" role="dialog" aria-hidden="true"><div class="pswp__bg"></div><div class="pswp__scroll-wrap"><div class="pswp__container"><div class="pswp__item"></div><div class="pswp__item"></div><div class="pswp__item"></div></div><div class="pswp__ui pswp__ui--hidden"><div class="pswp__top-bar"><div class="pswp__counter"></div><button class="pswp__button pswp__button--close" title="Close (Esc)"></button><button class="pswp__button pswp__button--share" title="Share"></button><button class="pswp__button pswp__button--fs" title="Toggle fullscreen"></button><button class="pswp__button pswp__button--zoom" title="Zoom in/out"></button><div class="pswp__preloader"><div class="pswp__preloader__icn"><div class="pswp__preloader__cut"><div class="pswp__preloader__donut"></div></div></div></div></div><div class="pswp__share-modal pswp__share-modal--hidden pswp__single-tap"><div class="pswp__share-tooltip"></div></div><button class="pswp__button pswp__button--arrow--left" title="Previous (arrow left)"></button><button class="pswp__button pswp__button--arrow--right" title="Next (arrow right)"></button><div class="pswp__caption"><div class="pswp__caption__center"></div></div></div></div></div>').appendTo('body');
    
    $('a.photo-swipe img:not("[data-size]")').each(function(){
            var eleme = $(this);
            var img = new Image();
            img.src = eleme.parent().attr('href');
            img.onload = function() {
                var imgw = img.width;
                var imgh = img.height;
                eleme.attr('data-size',imgw + 'x' +imgh );
            }
            
    });

	var PhotoSwipe = window.PhotoSwipe,
		PhotoSwipeUI_Default = window.PhotoSwipeUI_Default;

	$('body').on('click', 'a.photo-swipe:has("[data-size]")', function(e) {
		if( !PhotoSwipe || !PhotoSwipeUI_Default ) {
			return;
		}

		e.preventDefault();
		openPhotoSwipe( this );
	});

	var parseThumbnailElements = function(gallery, el) {
		var elements = $(gallery).find('a.photo-swipe:has("[data-size]")').has('img'),
			galleryItems = [],
			index;

		elements.each(function(i) {
			var $el = $(this),
				size = $('img',$el).data('size').split('x'),
				caption;

			if( $el.next().is('.wp-caption-text') ) {
				// image with caption
				caption = $el.next().text();
			} else if( $el.parent().next().is('.wp-caption-text') ) {
				// gallery icon with caption
				caption = $el.parent().next().text();
			} else {
				caption = $el.find('img').attr('alt');
			}

			galleryItems.push({
				src: $el.attr('href'),
				w: parseInt(size[0], 10),
				h: parseInt(size[1], 10),
				title: caption,
				msrc: $el.find('img').attr('src'),
				el: $el
			});
			if( el === $el.get(0) ) {
				index = i;
			}
		});

		return [galleryItems, parseInt(index, 10)];
	};

	var openPhotoSwipe = function( element, disableAnimation ) {
		var pswpElement = $('.pswp').get(0),
			galleryElement = $(element).parents('.gallery, .hentry, .main, body').first(),
			gallery,
			options,
			items, index;

		items = parseThumbnailElements(galleryElement, element);
		index = items[1];
		items = items[0];

		options = {
			index: index,
            fullscreenEl: false,
			getThumbBoundsFn: function(index) {
				var image = items[index].el.find('img'),
					offset = image.offset();

				return {x:offset.left, y:offset.top, w:image.width()};
			},
		};

		if(disableAnimation) {
			options.showAnimationDuration = 0;
		}
		gallery = new PhotoSwipe( pswpElement, PhotoSwipeUI_Default, items, options);
		gallery.init();
	};

これはプラグインで公開されていたコードを使って、少し仕様を変えています。

まずphoto-swipeのclassが無ければ何も起きない。

attachment_idで画像のサイズが読み取れない場合、ブラウザにロードさせてリンク画像の大きさを取得してしまいます。

強制的にロードさせちゃうから、巨大な画像があると重くなるかも知れない。
普通にWP使ってればあまりない事だと思うんだけど...。

attachment_idで画像サイズが取れないケースは、XMLとかで引っ越しして、現在のWP上に画像ファイルが無い とか、データベースに入ってない状態とか。

あと、外部URLの場合はattachment_idが無いからブラウザにロードさせるしか無い。
phpでやる方法もあるけど、jqueryで良いかな? と思ってやってみました。

まとめ

今までは自分で作ったモーダルウィンドウを使ってましたが、PhotoSwipeの完成度が高いので変えてみたワケです。

いずれ自分でスワイプ対応版を作ろうと思っていたのですが、サラリー化で時間の余裕が無くなったので丁度良いタイミングでした。
動きもスムーズだし、ピンチも問題無し。
PCではズームボタンもあるから、僕のやりたかった条件は満たされてしまいました。

たまに徘徊してみると良いライブラリと出会えるもんですね。
作者様には感謝です。

本家サイトはコチラ>> PhotoSwipe

色々チェックして問題が無さそうだったら、メインサイトもこのライブラリを使おうと思います。

ではでは

広告

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です