Pull to refresh

Comments 39

Как вариант:
Узнаем jsом ppi и если у пользователя retina дописываем в href всех img «2х» перед расширением.
Если речь об обработке загруженной страницы, то пользователь накажет себя на загрузку неоптимизированных и оптимизированных изображений (т.е. оба комплекта).
Будет эдакий progressive loading.
Сначала отображается упрощенная версия, потом подгружается более красивая, в которой в 4 раза больше пикселей.
Если имеем gprs с ограниченной скоростью и неограниченным трафиком то это самое оно.
Ох, нагородите сейчас, лучше начните использовать css4 image-set, с префиксом оно уже поддерживается в Safari 6 and Chrome 21, для остальных же high dpi устройств и избранных изображений используйте вдвое больше пикселей втиснутых в нужных объём и более агрессивное сжатие, всё

blog.cloudfour.com/safari-6-and-chrome-21-add-image-set-to-support-retina-images/
А как быть с пользовательским контентом?
А это должно быть на стороне CMS при формировании страницы. У вас же кука есть.
И раз вы можете заставить CMS делать две версии картинки, заставьте её отдавать разные линки в /img/.
А если усложним задачу кэшированием?
А так сложно закешировать две версии? =)
Я вообще не знаю, я только на Django пишу, и не вижу никаких препятствий.
В других местах могут быть.
Подумал, в принципе выполнимо. Динамический контент перед кэшированием обработать по выставленной куке и сформировать два кэша не проблема. Но ведь есть еще и статические шаблоны. Как быть с ними? Тоже два комплекта? ИМХО оно получится слишком трудно-управляемым со временем.
В Django я б написал шаблонный тег IMG и везде применял бы его.
А для передачи куки в шаблон сделал бы Context Processor, так что тег бы всегда знал что в куке.
Хм, но <img> это только часть проблемы. Во-первых есть CSS. Во-вторых, есть различные ajax загрузчики контента на сервер, появляется необходимость обработки статических шаблонов и т.д. и т.п. Другими словами, мы либо не покрываем всех картинок либо способ становится неуправляемо интегрируемым со скриптами CMS (что также не очень хорошо, так как лишает гибкости).
В моем случае, при необходимости, в течение пары минут статика перетаскивается на nginx без перекройки всего кода. Если бы удалось уйти от серверного php скрипта только с помощью обработчика в nginx способ стал бы реально универсальным. Есть спецы? Ау?
Я сделал вот таким образом:

if ($cookie_retina = 1) {
    rewrite ^/images/(.*?)\.(jpg|png|gif) /images/$1@2x.$2;
}
location ~ /images/(.*?)@2x\.(jpg|png|gif) {
    try_files $uri /images/$1.$2 =404;
}

Если запрашивается картинка @2x и ее нет на сервере, то отдается обычная картинка.
Вместо =404 можно написать свой обработчик (например, переслать в php-fpm и тд)

Название куки, которую нужно установить «retina». Соответственно, 1 — ретина, что-то другое — не ретина.

При таком подходе для всех картинок на сайте обязательно указывать width и height. Для через аттрибуты или через css-свойства, а для фоновых картинок нужно указывать background-size: width height.
Странно, что никто не «отметил» это решение. В разы оптимальней по нагрузке, чем описанное автором топика (для Арача).
Со вчерашнего вечера «отметили» это решение и обсуждали, внес правки в пост.
A на Android планшетах с ретиной это сработает?
Не пробовал, нужно лишь выполнить JS и посмотреть что вернет. Думаю да.
JS то ни куда не денется.
Я про css4 image-set.
Технический приём, связанный с употреблением CSS4 image-set, не может работать почти ни на одной из современных версий системы Android, раз уж о его появлении нам сообщили в августе 2012 года.

Есть ли хоть одна версия Android, появившаяся после августа?

Только одна — 4.1.2, за октябрь 2012 года. (Предыдущая версия, 4.1.1, появилась 9 июля.)

Много ли у кого версия 4.1.2 установлена? (Вопрос риторический, с подразумеваемым отрицательным ответом.)

Сопровождался ли её выход изменениями в коде Android Browser, или производители решили «работает — не трогай!»? (Вопрос не риторический, ответа я не знаю.)
Логично, спасибо.
Там еще Chrome есть, теоретически там может сработать.
if (file_exists($_GET['img']) && isImg ($_GET['img']))
        die (file_get_contents($_GET['img']));

Оригинальный способ отдачи контента. Лучше использовать функцию readfile(), которая не читает в память весь файл перед выводом. А еще лучше сказать веб-серверу, какой файл нужно отдать с помошью специального заголовка. Но такой фокус я знаю только для nginx, не знаю, есть ли в apache что-то подобное.
Тут согласен. Но, readfile() не везде доступна.
А вот по поводу заголовка для nginx можно по-подробнее?
> Разумеется, это изменение увеличило нагрузку на сервер

Разумеется.
Если я вас правильно понял, то убрать весь этот олдскульный огород с прогоном каждой картинки через php+apache вам помогут три строчки на nginx.
Ставите nginx. Всем изображениям в коде сайта добавляете префикс "/2x", если человек с ретины.
Скажем, было /images/pic.jpg, стало /2x/images/pic.jpg
Далее пишете в конфиге:

location ~ ^/2x/(.+)$ {
    try_files       $uri /$1 =404;
}


Оптимизированные изображения, соответственно, заливаете в папку /2x соответственно текущей структуре.
Перечитал еще раз задачу. Решение для кук:

1. Аналогично ставите куку перед загрузкой страницы: если ретина, кука retina = 1, если нет, то куки retina нет.
2. Пути к изображениям остаются неизменными, никаких префиксов /2x и т.д.
3. Кладете оптимизированные изображения в папку /2x/… и далее согласно текущей структуре файлов на сайте.
4. Конфиг nginx:

                if ($http_cookie ~ "retina" ) {
                        set     $retina 1;
                }
                location ~ ^/2x/(.+)$ {
                        try_files       $uri /$1 =404;
                }
                location ~* ^.+.(jpg|jpeg|gif|png)$ {
                        if ($retina = 1) {
                                rewrite (.+)    /2x$1;
                        }
                }


Суть в том, что сервер проверяет наличие куки «retina». Если она есть, перенаправляет файлы на префикс /2x. Далее смотрит: если файл есть в 2x — отдает ретина-версию, если нет — отдает файл по старому пути.
docomo, спасибо, так действительно можно создать универсальный метод. Я так понимаю, описать в конфиге nginx правило работы с постфиксом в имени файла невозможно?
Ну почему же, возможно. Вот для постфикса @2x:

                if ($http_cookie ~ "retina" ) {
                        set     $retina 1;
                }
                location ~* ^(.+)@2x.(jpg|jpeg|gif|png)$ {
                        try_files       $uri $1.$2 =404;
                }
                location ~* ^.+.(jpg|jpeg|gif|png)$ {
                        if ($retina = 1) {
                                rewrite ^(.+).(jpg|jpeg|gif|png)$ $1@2x.$2;
                        }
                }


В этом случае файлы остаются там же, где и были, просто pic.jpg становится pic@2x.jpg (описанный в вашем посте вариант). По-прежнему проверяем на куку «retina», если есть — отдаем @2x изображения. Пути к картинкам править, опять же, нигде не надо.
Великолепно! Вечером попробую, если все получится, внесу правку в статью для глупого решения с apache и отличного варианта с nginx. Спасибо. Плюсанул бы, но кармы не хватает :)
Apache в принципе-то не виноват. Просто в вашем варианте картинки гоняются через php-скрипт, а это большая нагрузка. mod_rewrite апача я уже не помню за давностью, но уверен, что на нем тоже можно реализовать подобную схему проверки существования файла.
Ну под глупым решением с Apache я и имел ввиду php-скрипт. Но и статику лучше конечно-же отдавать nginx, поэтому ваш способ сейчас в явном выигрыше.
Странно, в конфиге nginx этот код приводит к тому, что картинки вообще не отображаются. Куку не выставлял, опробовал без нее.
Проверьте параметр root в конфиге хоста.
Чтобы тут не разводить треды, кинул вам в личку полный конфиг хоста, например.
Собственно выше это решение было предложено и оно (вместе с вашим) наиболее оптимальное для данной задачи.
лучшим способом адаптации на сегодняшний день является способ c background-image в CSS. Но он не применим к обычным изображениям в теге <img>
Вообще-то он вполне применим.

В вики Stylish излагается вот какой действенный рецепт подмены изображения при помощи CSS:

IMG#идентификаторКартинки {
   /* обнуляем размеры имеющейся картинки: */
   height: 0 !important;
   width: 0 !important;
   /* задаём размеры новой картинки: */
   padding-left: 125px !important;
   padding-top: 25px !important;
   /* задаём адрес новой картинки: */
   background: url(http://example.com/адрес/иллюстрации) no-repeat !important;
}

Достаточно засунуть этот код внутрь Вашей обёртки @media only screen and (-webkit-min-device-pixel-ratio: 1.5), only screen and (min-resolution: 144dpi)») — и дело сделано.
Mithgolда, действительно, это вариант, но:
1. В большом проекте мы будем вынуждены картинки background дизайна в css обрабатывать вручную;
2. Способ не подойдет при большом количестве «внедрений» картинок (во всех шаблонах надо указывать id картинки, а если есть генерация лайтбоксов на js — опять же придется перерыть весь код и в части мест внести изменения не удастся, т.к. id тега может быть занятым;
3. Самое главное. Для каждой страницы @media css придется генерировать скриптами. А если на страницу аяксом подгрузится еще картинка — всплывут проблемы.

За способ спасибо, для статики он применим на ура!
А что, сейчас все экраны с высокой плотностью Ретиной называют?
только макаводы ;) ведройды называют hdpi и xhdpi
С одной стороны, куки для того и придуманы, чтобы влиять на генерацию контента, но с другой, содержимое «статического» файла будет определяться не только урлом, но и кукой — костыльно выглядит, как минимум всякое кеширование ломается сходу, и далеко не все cdn для статики смогут такие запросы правильно обработать.

Хорошее решение должно оперировать только урлами. Это сложно, не спорю, надо лезть в движок сайта, одними шаблонами с добавленным JS кодом не обойдешься уже… ((
Only those users with full accounts are able to leave comments. Log in, please.