Статьи

Галерея изображений с пользовательскими изображениями (плагин Bonus jQuery)

Как я и обещал в моей предыдущей статье , здесь есть учебник по созданию галереи из изображений нестандартного размера. В качестве бонуса вы узнаете, как создать базовый плагин jQuery, чтобы представить увеличенное изображение миниатюры в более привлекательной форме.

Если вы не читали мою предыдущую статью о нестандартных размерах изображений, прочитайте ее, чтобы было легче понять этот учебник.


В зависимости от макета вашей темы и используемой в ней системы сетки, вы можете выбрать разные размеры изображений для миниатюр. Прежде чем принять решение, подумайте, сколько изображений вы хотите иметь в строке, какова ширина контейнера, в котором будут отображаться эскизы, поля, отступы и т. Д.

В качестве примера я буду использовать ширину 2 колонки 940 пикселей (соотношение 8/4), где содержимое будет 620 пикселей, а боковая панель 300 пикселей с левым полем 20 пикселей. Область содержимого и область боковой панели будут иметь внутренний отступ 20 пикселей. Теперь немного математики: содержимое имеет ширину 620 пикселей с отступом 20 пикселей, оставляя 580 пикселей для миниатюр; и отображение 5 миниатюр в каждой строке, каждая из которых имеет правое поле 10 пикселей, чтобы они не слипались; 5-е изображение в каждой строке не будет иметь правого поля; миниатюры будут 108px по ширине и высоте и обрезаны.

Изображение большего размера будет максимум 660 пикселей в ширину и 660 пикселей в высоту, они будут пропорционально изменены без обрезки.

Вы можете выбрать любой размер, подходящий для вашего макета, если вы решите изменить размеры, их можно легко восстановить (см. Предыдущий пост о том, как это сделать), и они не должны быть квадратной формы.


Отредактируйте файл functions.php так, чтобы он выглядел примерно так:

01
02
03
04
05
06
07
08
09
10
add_action( ‘after_setup_theme’, ‘setup’ );
function setup() {
    // …
 
    add_theme_support( ‘post-thumbnails’ );
    add_image_size( ‘preview’, 108, 108, true );
    add_image_size( ‘zoomed’, 660, 600 );
 
    // …
}

Еще в functions.php добавьте метод generate_thumbnail_list :

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
function generate_thumbnail_list( $post_id = null ) {
    if ( $post_id == null ) return;
    $images = get_posts(
        array(
            ‘numberposts’ => -1,
            ‘post_type’ => ‘attachment’,
            ‘post_mime_type’ => ‘image/jpeg, image/jpg, image/png, image/gif’,
            ‘post_parent’ => $post_id,
            ‘orderby’ => ‘menu_order’,
            ‘order’ => ‘ASC’,
            ‘exclude’ => get_post_thumbnail_id( $post_id )
        )
    );
    if ( count( $images ) > 0 ) {
        echo ‘<ul class=»gallery»>’;
        foreach ( $images as $image ) {
            $src = wp_get_attachment_image_src($image->ID, ‘zoomed’);
            echo ‘<li><a href=»‘ . $src[0] .'»>’ .
        }
        echo ‘</ul>’;
        echo ‘<div class=»clear»></div>’;
    }
}

В content-single.php вызовите метод generate_thumbnail_list , передав идентификатор сообщения в качестве параметра.

1
2
3
<?php the_content();
<h3>Images</h3>
<?php generate_thumbnail_list( get_the_ID() );

Приведенный выше выводит неупорядоченный список, содержащий ссылки на файлы большего размера и миниатюрные изображения.


Очевидно, что эскизы должны быть стилизованы, в противном случае это просто список изображений. Добавьте следующее в существующую таблицу стилей или создайте новую и поставьте ее в очередь :

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
.clear {
    clear: both;
}
.gallery {
    list-style-type: none;
    padding: 0;
    margin: 0;
}
.gallery li {
    float: left;
    margin: 0 10px 10px 0;
}
.gallery li:nth-child(5n) {
    margin-right: 0;
}
.gallery a {
    float: left;
    cursor: pointer;
    text-decoration: none;
}
.gallery img {
    float: left;
    border: 0;
}

Это поместит изображения рядом друг с другом, оставляя пространство вокруг них.

В этот момент клик по миниатюре откроет большое изображение на пустой странице. Это хороший запасной вариант, если JavaScript отключен.


Перед написанием любого JavaScript было бы желательно узнать, как будет отображаться большое изображение. Вот что я имел в виду:

Примечание: все это будет сгенерировано из плагина jQuery. Это просто чтобы показать процесс создания.

Прозрачное наложение поверх всего содержимого с изображением посередине и элементами управления в верхнем правом углу. Во время загрузки изображения будет отображаться счетчик. В корне тела документа будет добавлен div-обертка, который будет содержать ссылки для перехода к следующему и предыдущему, ссылку для закрытия галереи и обертку вокруг изображения, куда будет загружено изображение. Это минимальный HTML-код, который будет использоваться для галереи.

1
2
3
4
5
6
<div id=»zoom»>
    <a href=»#next» class=»next»>Next</a>
    <a href=»#previous» class=»previous»>Previous</a>
    <div class=»close»></div>
    <div class=»content»></div>
</div>

Добавление следующего стиля приведет к стилизации вышеуказанных элементов, как на рисунке выше (комментарии включены для объяснения частей, которые могут быть не сразу очевидны):

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
#zoom {
    z-index: 99990;
    position: fixed;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    /* creates a transparent background, so the content under it will be visible,
    transparency can be adjusted */
    background: rgba(0, 0, 0, 0.8);
}
#zoom .content {
    z-index: 99991;
    position: absolute;
    /* start initial positioning: will be centered horizontally and vertically */
    top: 50%;
    left: 50%;
    width: 200px;
    height: 200px;
    margin: -100px 0 0 -100px;
    /* end positioning */
    /* an animated spinner as background will be visible while the image is loading */
    background: #ffffff url(‘../img/spinner.gif’) no-repeat 50% 50%;
    border: 20px solid #ececec;
    padding: 0;
}
#zoom img {
    display: block;
    max-width: none;
    background: #ececec;
    -moz-box-shadow: 2px 2px 5px rgba(0, 0, 0, 0.3);
    -webkit-box-shadow: 2px 2px 5px rgba(0, 0, 0, 0.3);
    box-shadow: 2px 2px 5px rgba(0, 0, 0, 0.4);
}
#zoom .close {
    z-index: 99993;
    position: absolute;
    top: 0;
    right: 0;
    width: 49px;
    height: 49px;
    cursor: pointer;
    background: transparent url(‘../img/icons/close.png’) no-repeat 50% 50%;
    opacity: 1;
    filter: alpha(opacity=100);
}
#zoom .previous,
#zoom .next {
    z-index: 99992;
    position: absolute;
    top: 0;
    overflow: hidden;
    display: block;
    width: 49px;
    height: 49px;
    text-indent: 100%;
}
#zoom .previous {
    right: 100px;
    background: url(‘../img/icons/arrows.png’) no-repeat 0 0;
}
#zoom .next {
    right: 50px;
    background: url(‘../img/icons/arrows.png’) no-repeat 100% 0;
}
#zoom .close:hover {
    background-color: #da4f49;
}
#zoom .previous:hover,
#zoom .next:hover {
    background-color: #0088cc;
}

Результат вышеизложенного:

Приведенный выше HTML-код не понадобится, он будет создан с помощью JavaScript. События будут прикреплены для открытия, навигации и закрытия галереи. Навигация и закрытие галереи может быть сделано с клавиатуры или с помощью мыши.

JavaScript ниже также прокомментирован, чтобы объяснить, что происходит:

001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
018
019
020
021
022
023
024
025
026
027
028
029
030
031
032
033
034
035
036
037
038
039
040
041
042
043
044
045
046
047
048
049
050
051
052
053
054
055
056
057
058
059
060
061
062
063
064
065
066
067
068
069
070
071
072
073
074
075
076
077
078
079
080
081
082
083
084
085
086
087
088
089
090
091
092
093
094
095
096
097
098
099
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
(function($) {
    $.zoom = function() {
         // append a gallery wrapper to the document body
        $(‘body’).append(‘<div id=»zoom»></div>’);
        var zoomedIn = false, // a flag to know if the gallery is open or not
            zoom = $(‘#zoom’),
            zoomContent = null,
            opened = null;
 
        function setup() {
            zoom.hide();
            // add the inner elements, image wrapper, close and navigation links
            zoom.prepend(‘<div class=»content»></div>’);
            zoom.prepend(‘<div class=»close»></div>’);
            zoom.prepend(‘<a href=»#previous» class=»previous»>Previous</a>’);
            zoom.prepend(‘<a href=»#next» class=»next»>Next</a>’);
             
            zoomContent = $(‘#zoom .content’);
            // attach events to the added elements
            $(‘#zoom .close’).on(‘click’, close);
            $(‘#zoom .previous’).on(‘click’, openPrevious);
            $(‘#zoom .next’).on(‘click’, openNext);
             
            // observe keyboard events for navigation and closing the gallery
            $(document).keydown(function(event) {
                if (!opened) {
                    return;
                }
                if (event.which == 27) {
                    $(‘#zoom .close’).click();
                    return;
                }
                if (event.which == 37) {
                    $(‘#zoom .previous’).click();
                    return;
                }
                if (event.which == 39) {
                    $(‘#zoom .next’).click();
                    return;
                }
                return;
            });
             
            if ($(‘.gallery li a’).length == 1) {
                // add ‘zoom’ class for single image so the navigation links will hide
                $(‘.gallery li a’)[0].addClass(‘zoom’);
            }
            // attach click event observer to open the image
            $(‘.zoom, .gallery li a’).on(‘click’, open);
        }
         
        function open(event) {
            event.preventDefault();
            var link = $(this),
                src = link.attr(‘href’),
                // create an image object with the source from the link
                image = $(new Image()).attr(‘src’, src).hide();
            if (!src) {
                return;
            }
            $(‘#zoom .previous, #zoom .next’).show();
            if (link.hasClass(‘zoom’)) {
                $(‘#zoom .previous, #zoom .next’).hide();
            }
             
            // show the gallery with loading spinner, navigation and close buttons
            if (!zoomedIn) {
                zoomedIn = true;
                zoom.show();
            }
             
            // clean up and add image object for loading
            zoomContent.empty().prepend(image);
            // event observer for image loading, render() will be
            // called while image is loading
            image.load(render);
            opened = link;
        }
         
        function openPrevious(event) {
            event.preventDefault();
            if (opened.hasClass(‘zoom’)) {
                return;
            }
            var prev = opened.parent(‘li’).prev();
            if (prev.length == 0) {
                prev = $(‘.gallery li:last-child’);
            }
            prev.children(‘a’).trigger(‘click’);
        }
         
        function openNext(event) {
            event.preventDefault();
            if (opened.hasClass(‘zoom’)) {
                return;
            }
            var next = opened.parent(‘li’).next();
            if (next.length == 0) {
                next = $(‘.gallery li:first-child’);
            }
            next.children(‘a’).trigger(‘click’);
        }
         
        function render() {
            // if the image is not fully loaded do nothing
            if (!this.complete) {
                return;
            }
            var image = $(this);
            // if image has the same dimensions as the gallery
            // just show the image don’t animate
            if (image.width() == zoomContent.width() &&
                image.height() == zoomContent.height()) {
                show(image);
                return;
            }
            var borderWidth = parseInt(zoomContent.css(‘borderLeftWidth’));
            // resize the gallery to the image dimensions before
            // displaying the image
            zoomContent.animate({
                width: image.width(),
                height: image.height(),
                marginTop: -(image.height() / 2) — borderWidth,
                marginLeft: -(image.width() / 2) — borderWidth
            }, 300, function(){
                show(image);
            });
 
            function show(image) {
                image.fadeIn(‘fast’);
            }
        }
         
        function close(event) {
            event.preventDefault();
            zoomedIn = false;
            zoom.hide();
            zoomContent.empty();
        }
         
        setup();
    };
})(jQuery);

После включения вышеуказанного плагина инициализируйте его, добавив вызов плагина в метод generate_thumbnail_list :

1
2
3
4
5
6
7
function generate_thumbnail_list( $post_id = null ) {
    // …
    if ( count( $images ) > 0 ) {
        // …
        echo ‘<script type=»text/javascript»>jQuery.zoom();</script>’;
    }
}

Реальный пример того, как это работает и как это можно использовать: Zoom jQuery Photo Gallery Plugin demo