Генерация превью для адаптивного сайта

Имею сайт, каталог изделий, который сверстан на Bootstrap 3. Генерирую превьюшки через phpThumbOn (знаю что не оптимально, но все же). Для больших экранов мне достаточно превьюшки по ширине 250px, они идут в 3 колонки, все нормально, размер превьюшек небольшой, грузятся быстро. Но для смартфонов, где превьюшки выстраиваются в одну колонку уже надо превью под 800px шириной. Сейчас генерирую превью 800px по ширине для всех девайсов, на всех экранах это выглядит хорошо но размер превью уже под 250 килобайт каждого и грузятся не айс. А эсли этих превью 10 штук странице, получается только картинок на 2,5 метра. Надо бы делать генерацию превью в зависимости от экрана динамически. Хотелось бы узнать как это сделать оптимальнее. Есть ли у кого какие решения?
Сергей Росоловский
16 июня 2016, 09:30
modx.pro
5
2 836
0

Комментарии: 26

Юрий
16 июня 2016, 12:55
+1
Лучше не пожалейте денег и купите ms2gallery, настройте медиаисточник, на генерацию необходимых размеров изображений.
А для «адаптивности» рекомендую использовать js плагин lazysizes. Он позволит делать «ленивую» загрузку изображений по мере прокрутки страницы, также может работать с различными размерами фото, в зависимости от размера экрана
    Сергей Росоловский
    16 июня 2016, 13:07
    0
    Ну ms2Gallery у меня есть, (еще с тех времен когда она свободно лежала на гитхабе), но сайт еще до того уже был наполнен ресурсами где к кажому ресурсу были tv поля с картинками. Да ms2Gallery пользоваться удобно, думаю перейду на нее, но правда не знаю как это поможет в плане скорости загрузки картинок и траффика.
    И с lazysizes, я просидел целый вечер но так и не смог заставить работать. А вот простой lazy load прикрутил, но это просто отложенная загрузка, траффик тот же.
    P.S.
    Хорошо картинки сделаны на vrmedia.tv, но там проще, сайт не адаптивный.
      Юрий
      16 июня 2016, 15:50
      +1
      C lazysizes очень просто:
      Подключаете скрипт, лучше использовать minifix
      Посмотрите еще есть куча плагинов для Lazysizes.
      <script src="ls.respimg.js"></script>
      <script src="lazysizes.min.js" async=""></script>
      Для адаптивных изображений используйте плагин respimg

      Сделайте столько размеров картинки сколько Вам нужно на вашу верстку.
      Еще для уменьшения размера картинки, в параметрах phpThumbOn уменьшите сжатие jpg
    Сергей
    16 июня 2016, 13:18
    +1
    Может есть смысл посмотреть в сторону mobiledetect? Для мобильного разрешения отдельно картинки выводить.
      Сергей Росоловский
      16 июня 2016, 13:46
      0
      Кажется mobiletetect не всегда правильно определяет, но надо поюзать.
      Иван Бочкарев
      17 июня 2016, 07:08
      +1
        Сергей Росоловский
        17 июня 2016, 22:17
        +1
        Пока что сделал так используя phpThumbOn, можно и на ms2Gallery переделать

        <picture>
              <source media="(min-width: 1200px)" srcset="[[+tv.ProductImage:phpthumbon=`w=234&h=175&zc=1`]]">
              <source media="(min-width: 992px)" srcset="[[+tv.ProductImage:phpthumbon=`w=184&h=138&zc=1`]]">
              <source media="(min-width: 768px)" srcset="[[+tv.ProductImage:phpthumbon=`w=311&h=233&zc=1`]]">
              <img class="img-responsive" src="[[+tv.ProductImage:phpthumbon=`w=670&h=503&zc=1`]]">
         </picture>
          Владимир
          18 июня 2016, 17:08
          0
          Интересно, тест гугловский что говорит после добавления вариантов превьюшек?
            Сергей Росоловский
            18 июня 2016, 17:15
            0
            Да, гугловский тест видит только наибольшую из перечисленных превью и пишет что надо бы оптимизировать изображения :) Хотя если правой клавишей мыши сохранять изображение из сайта то сохраняется нужный размер.
              Владимир
              18 июня 2016, 17:49
              0
              Только эту
              <img class="img-responsive" src="[[+tv.ProductImage:phpthumbon=`w=670&h=503&zc=1`]]">
              видит?
                Сергей Росоловский
                18 июня 2016, 17:53
                +1
                Да гугл видит только эту, да и при тестировании в gtmetrix тоже эту видит. Но по факту в браузере ресайзит правильно, в зависимости от размера экрана. Иногда даже видно подгрузку превью когда проходишь точку излома.
                  Владимир
                  18 июня 2016, 18:08
                  0
                  Гад он (Google) тогда :)) Тогда его speed-тест не соответствует стандартам.
                  Сам что только не делал, и ленивую подгрузку и сжимал картинки, пока увы, тест не пройден.
                  Кстати pthumb мне как больше нравится, чем phpthumbon. Например, phpthumbon выставляет размеры картинки в теге img? Все таки часто надо их (размеры) проставить.
                  С феномом pthumb дружит прекрасно:
                  {$_modx->runSnippet('!pthumb', [
                        'input' => $_pls['tv.title_image'],
                        'options' => 'w=400&h=240q=75&zc=C',
                        'toPlaceholder' => 'thumb'
                        ])}
                                                       
                        <img class="img-responsive" src="{$_modx->getPlaceholder('thumb')}" width="{$_modx->getPlaceholder('thumb.width')}" height="{$_modx->getPlaceholder('thumb.height')}"/>
                  По моему это всяко лучше модификаторов.
                    Владимир
                    18 июня 2016, 18:12
                    +1
                    Кстати, а если в основной тег картинку указать меньше 670 пикселей по ширине? Т.е. такую, какую гугл тест сочтет за «ОК»? А живым людям показывать в соответствии с source media?
                      Сергей Росоловский
                      18 июня 2016, 18:27
                      +1
                      Но вот если так сделать, (тут у меня ms2Gallery, но это неважно) + еще lazyload прикручен, то гугловский тест проходит!!!
                      Я так понял в data-original надо изначально прописывать наименьший размер превью, в моем случае [[+184x138]], а там уж бутстрап сам разберется что показывать.
                      <picture>
                            <source media="(min-width: 1200px)" srcset="[[+234x175]]" width="234" height="175">
                            <source media="(min-width: 992px)" srcset="[[+184x138]]" width="184" height="138">
                            <source media="(min-width: 768px)" srcset="[[+311x233]]" width="311" height="233">
                            <source media="(max-width: 767px)" srcset="[[+670x503]]" width="670" height="503">
                            <img
                                  class="lazy img-responsive" width="100%" height="100%"
                                  src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw=="
                                  data-original="[[+184x138]]">
                      </picture>
                        Владимир
                        18 июня 2016, 18:53
                        0
                        Ясно, но так же ясно что source media тест не учитывает. Спасибо, попробую тоже скормить гуглу наименьшую картинку.
                          Сергей Росоловский
                          18 июня 2016, 22:17
                          0
                          Похоже эти фокусы с изображениями не все мобильные браузеры поддерживают. Например Хром на Андроиде 4.4, все хорошо, а вот UC Browser уже как-то не совсем хорошо.
            Волков Николай
            19 июня 2016, 05:45
            0
            Данный вариант во-первых не всеми браузерами поддерживается. Тот же Гугл тест видит самую большую, т.к. не знаком с новым тэгом
            <picture>
            и игнорирует его и загружает
            <img>
            Во-вторых, помимо адаптивности ключевую роль играет еще и плотность пикселей экрана. На тех же Ретина экранах все будет размыто смотреться. Поэтом для дисплеев с повышенной плотностью пикселей, указавают дополнительные имена файлов в атрибуте srcset.

            <picture>
                <source srcset="smaller.jpg, smaller_retina.jpg 2x" media="(max-width: 768px)">
                <source srcset="default.jpg, default_retina.jpg 2x">
                <img srcset="default.jpg, default_retina.jpg 2x" alt="My default image">
            </picture>
            Ну и последнее JS для браузеров без поддержки http://scottjehl.github.io/picturefill/
              Волков Николай
              19 июня 2016, 05:50
              0
              Плюс еще есть одна маленькая хитрость: на смартах вы написали, что должны быть самые широкие превью. И это в первую очередь из-за того, что у их экранов значительно более высокая плотность пикселей. Поэтому чаще всего при генерации превью для них занижают сильно качество у превьюшки, т.к. дефекты на ней будет не разглядеть, но главное это то, что их размер будет значительно меньше.
                Сергей Росоловский
                19 июня 2016, 08:21
                0
                Да уж, в этой адаптивности камней подводных много. В принципе это контейнер, можно и без него обойтись одним img вместе с srcset и sizes. А кто имеет iPhone или iPad, протестируйте https://novabrama.com.ua/catalog/bramy/, тут на украинском, но все же интересно как смотрется на ретина дисплеях будет.
                  Волков Николай
                  19 июня 2016, 10:20
                  0
                  На iphone5s нормально, единственное шапка кривая немного, т.к. часть логотипа позиционировалась над блоком меню + картинки флагов не очень чёткие
                    Сергей Росоловский
                    19 июня 2016, 10:32
                    0
                    Если это то что я думаю, то логотип так задуман. Спасибо за тест.
                      Владимир
                      19 июня 2016, 11:29
                      0
                      Кстати, перешел по вашей ссылке, не работает меню, жму на «гамбургер» — меню не раскрывается (Chrome, на андроиде 4.4.2) Картинки выглядят хорошо, на мой взгляд.
            Константин Обухов
            20 июня 2016, 13:48
            +1
            // Работаем только на фронтенде
            if ($modx->event->name != 'OnHandleRequest' || $modx->context->key == 'mgr') {return;}
            
            // Определяем запрашиваемый хост
            $host = $_SERVER['HTTP_HOST'];
            // Выбираем контекст с настройкой base_url
            $q = $modx->newQuery('modContextSetting', array('key' => 'http_host', 'value' => $host));
            $q->select('context_key');
            $tstart = microtime(true);
            
            if ($q->prepare() && $q->stmt->execute()) {
             // Учитываем наш запрос в БД
             $modx->queryTime += microtime(true) - $tstart;
             $modx->executedQueries++;
             // Получаем ключ контекста
             if ($context = $q->stmt->fetch(PDO::FETCH_COLUMN)) {
              // Web инициализируется в index.php - на него переключаться не нужно
            //   if ($context != 'web') {
               $modx->switchContext($context);
            //   }
             }
             else {
                    $modx->sendErrorPage();
             }
            }
            $useragent = $_SERVER['HTTP_USER_AGENT'];
            if(preg_match('/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino/i',$useragent)||preg_match('/1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i',substr($useragent,0,4))) {
                $modx->setPlaceholder('mob','1');
            }
            else{ $modx->setPlaceholder('mob','0');}

            Вешаем плагин и имеем 100% placeholder
            [[!+mob]]
            на странице — вызов некешируемый.
            Верхнюю часть где переключение контекстов(made Василий) и 404 для случая когда домены для сайта указаны как *.site.ru в админке хостинга, можно удалить работает 100%.

            И дальше уже идет адаптивность плюс разделение контента на мобила и не мобила, что-то вроде такого
            [[!+mob:is=`1`:then=`<img src="full.jpg">`:else=`<img src="mobile.jpg">`]]
            или так
            <img src="[[!+mob:is=`1`:then=`[[*mobile_img]]`:else=`[[*desc_img]]`]]">
            В условия можешь свой phptmb вставить.
              Сергей Росоловский
              20 июня 2016, 20:25
              0
              Спасибо, обойдемся как нибудь и без этих манускриптов, так сказать малой кровью :)
                Константин Обухов
                20 июня 2016, 21:26
                0
                Ну это как пример, чтобы не выглядело так страшно (копировал с сайта лень стало удалять лишнее) нужно что-то типа такого сделать:

                // Работаем только на фронтенде
                if ($modx->event->name != 'OnHandleRequest' || $modx->context->key == 'mgr') {return;}
                $useragent = $_SERVER['HTTP_USER_AGENT'];
                if(preg_match('/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino/i',$useragent)||preg_match('/1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i',substr($useragent,0,4))) {
                    $modx->setPlaceholder('mob','1');
                }
                else{ $modx->setPlaceholder('mob','0');}

                Сама регулярка взята с сайта http://detectmobilebrowsers.com/

                Как по мне это удобно в плане того что не только картинки можно так обрабатывать по сути часть контента скрывать без css, а значит страница будет легче на мобиле.
              Авторизуйтесь или зарегистрируйтесь, чтобы оставлять комментарии.
              26