Задача возникла, когда делал клиенту сайт с электронным магазином. Картинки товаров на страницах должны выводиться единообразно; сам же клиент имеет картинки всех возможных размеров и пропорций. Чтобы освободить его от редактирования изображений, было решено вписывать их в контейнер - блок <div> фиксированного размера, обрамленный рамкой. Вытянутые по горизонтали имиджи вписываться будут по ширине, вытянутые по вертикали - соответственно, по высоте. Сами изображения должны быть кликабельны.

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

Назовем нашу функцию out_adjusted_link_image. Ее определение будет иметь такой вид:

function out_adjusted_link_image($img_file, $img_alt, $img_title,
                                 $a_href, $div_wd, $div_ht,
                                 $div_more_style = '', $a_more = '')

Параметры:

Имя
Тип
Описание
$img_file
string
путь и имя файла изображения
$img_alt, $img_title
string
атрибуты alt и title тега имиджа
$a_href
string
URL, открываемый по клику на картинке
$div_wd, $div_ht
int
ширина и высота контейнера
$div_more_style
string
дополнительные атрибуты CSS-стиля контейнера (опционально)
$a_more
string
дополнительные атрибуты тега анкора (опционально)

Возвращаемое функцией значение - строка, содержащая HTML-скрипт нашей конструкции контейнер - линк - имидж.

Строим тело функции. Пошагово:

1. Определяем константы, задающие оба измерения, по которым будем вписывать:

define('ALIGN_BY_WD', 0);
define('ALIGN_BY_HT', 1);

2. Выясняем размеры имиджа. Для этого воспользуемся функцией getimagesize(). В качестве параметра эта функция требует имя файла образа, включая путь к нему. Возвращает она массив из 7 элементов, из которых нас интересуют первые 2 (т. е. с индексами 0 и 1), содержащие соответственно ширину и высоту имиджа.

$size = getimagesize($img_file);
$img_wd = $size[0];
$img_ht = $size[1];

3. Определяем, по какому измерению вписывать. Если контейнер более "сплющен" по вертикали, чем имидж, то после подгонки по размеру имидж впишется по высоте, в обратном случае - по ширине. Данная логика реализуется следующим фрагментом кода PHP:

if ($div_wd / $div_ht > $img_wd / $img_ht)
  $align = ALIGN_BY_HT;
else
  $align = ALIGN_BY_WD;

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

4. Вписываем нашу картинку в контейнер. Для этого вычисляем ширину и высоту вписанного имиджа - $new_img_wd и $new_img_ht. Для последующего центрирования определяем также переменные $rel_edge и $abs_edge - края для относительного и абсолютного позиционирования по соответствующим измерениям, и $new_img_dim - размер, который будем использовать для установки отступа. Присваиваем им значения в соответствии с направлениями выравнивания.

if ($align == ALIGN_BY_HT) {
  $new_img_ht = $div_ht;
  $new_img_wd = $new_img_ht * $img_wd / $img_ht;
  $rel_edge = 'left';
  $abs_edge = 'top';
  $new_img_dim = $new_img_wd;
}
else {
  $new_img_wd = $div_wd;
  $new_img_ht = $new_img_wd * $img_ht / $img_wd;
  $rel_edge = 'top';
  $abs_edge = 'left';
  $new_img_dim = $new_img_ht;
}

5. Центрируем имидж. Вписанный по ширине - по вертикали, вписанный по высоте - по горизонтали. Для этого используем технику выравнивания, описанную в предыдущей статье. Помещаем искомую строку стиля в переменную $img_style:

$img_style = 'position:absolute; ' . $rel_edge . ':50%; width:' .
             $new_img_wd . 'px; height:' . $new_img_ht . 'px; margin-' .
             $rel_edge . ':-' . ($new_img_dim / 2) . 'px; ' .
             $abs_edge . ':0';

Теперь можно выстроить всю конструкцию контейнер - анкор - имидж, строку с которой и будет возвращать наша функция:

return '<div style="position:relative; width:' . $div_wd .
       'px; height:' . $div_ht . 'px; border:1px solid silver;' .
       $div_more_style . '"><a href="' . $a_href . '" '. $a_more .
       '><img src="' . $img_file . '" alt="' . $img_alt . '" title="' .
       $img_title . '" style="' . $img_style . '" /></a></div>';

Вот как она (конструкция то бишь) выглядит в браузере:

Monkey

Достигли ли мы желаемого результата? Не совсем. Попробуйте навести курсор на наш блок и убедитесь, что поля между имиджем и границами контейнера не попадают в ссылку. Чтобы ссылка охватывала весь блок, сделаем следующее:

  1. Наш вписанный и отцентрированный имидж расположим перед анкором ссылки.
  2. Вместо него внутрь анкора поместим прозрачный PNG-имидж, размеры которому зададим равными размерам контейнера.

Таким образом, наша картинка перекроется прозрачным имиджем и останется видимой. Зона же действия линка растянется до границ контейнера.

Модифицированный фрагмент кода, возвращающий значение функции, примет следующий вид:

return '<div style="position:relative; width:' . $div_wd .
       'px; height:' . $div_ht . 'px; border:1px solid silver;' .
       $div_more_style . '"><img src="' . $img_file . '" style="' .
       $img_style . '" /><a href="' . $a_href . '" '. $a_more .
       '><img src="images/Transparent.png" alt="' .
       $img_alt . '" title="' . $img_title . '" width="' .
       $div_wd . '" height="' . $div_ht .
       '" style="position:absolute; top:0px; left:0px;" /></a></div>';

Наведите курсор теперь и почувствуйте разницу:

Monkey

Собрав воедино все вышеприведенные части кода, получим функцию в окончательном виде:

function out_adjusted_link_image($img_file, $img_alt, $img_title,
                                 $a_href, $div_wd, $div_ht,
                                 $div_more_style = '', $a_more = '') {
  define('ALIGN_BY_WD', 0);
  define('ALIGN_BY_HT', 1);
 
  $size = getimagesize($img_file);
  $img_wd = $size[0];
  $img_ht = $size[1];
 
  if ($div_wd / $div_ht > $img_wd / $img_ht)
    $align = ALIGN_BY_HT;
  else
    $align = ALIGN_BY_WD;
 
  if ($align == ALIGN_BY_HT) {
    $new_img_ht = $div_ht;
    $new_img_wd = $new_img_ht * $img_wd / $img_ht;
    $rel_edge = 'left';
    $abs_edge = 'top';
    $new_img_dim = $new_img_wd;
  }
  else {
    $new_img_wd = $div_wd;
    $new_img_ht = $new_img_wd * $img_ht / $img_wd;
    $rel_edge = 'top';
    $abs_edge = 'left';
    $new_img_dim = $new_img_ht;
  }
 
  $img_style = 'position:absolute; ' . $rel_edge . ':50%; width:' .
               $new_img_wd . 'px; height:' . $new_img_ht . 'px; margin-' .
               $rel_edge . ':-' . ($new_img_dim / 2) . 'px; ' .
               $abs_edge . ':0';
 
  return '<div style="position:relative; width:' . $div_wd .
         'px; height:' . $div_ht . 'px; border:1px solid silver;' .
         $div_more_style . '"><img src="' . $img_file . '" style="' .
         $img_style . '" /><a href="' . $a_href . '" '. $a_more .
         '><img src="images/Transparent.png" alt="' .
         $img_alt . '" title="' . $img_title . '" width="' .
         $div_wd . '" height="' . $div_ht .
         '" style="position:absolute; top:0px; left:0px;" /></a></div>';
}

Пример вызова функции. Именно он рендерит в вашем браузере эту милую вписанную в кликабельный квадрат мартышку:

echo out_adjusted_link_image('images/monkey.jpg', 'Monkey', 'Monkey',
                    '#anchor', 200, 200,
                    'left:50%; margin-left:-100px', 'target="_blank"');

Здесь еще и сам контейнер отцентририрован по горизонтали внутри своего собственного родительского блока все по той же методике.

В одной из последующих статей я планирую описать, как я встроил приведенный здесь код в содержимое материала сайта на Joomla.

Комментарии  

Николай
0 # Николай 05.03.2014 05:00
Доброго времени суток (у Вас, наверное, поздний вечер в данный момент)! Не могли бы помочь ссылкой на информацию по следующему вопросу? Сайт на Joomla 3. Необходимо дать ссылку (в моем случае, на всплывающее окно) на кусочек рисунка бэкграунда одной из позиций.
Я пытался добавить модуль с HTML в данное место, прописав в пользовательский текст прозрачную картинку и присвоив модулю стиль: position:absolute; margin-left; margin-top;
Но выше другой модуль с меню с аккордеоном и при раскрытии аккордеона моя прозрачная картинка-ссылка смещается.
Ответить | Ответить с цитатой | Цитировать
Николай
0 # Николай 05.03.2014 05:12
Забыл добавить, что сайтостроением занимаюсь менее полугода и программированием не владею.
Ответить | Ответить с цитатой | Цитировать
Ogri
0 # Ogri 05.03.2014 14:12
Здравствуйте, Николай. Попробовал смоделировать ваш случай: прямо в эту статью перед мартышками вставил аккордеон (на локалке, понятно). Картинка-ссылка никуда не съехала. Предположу поэтому, что у вас где-то в реализации ошибка. А может, и в другом месте страницы что-то влияет на нормальный поток документа. Пришлите код страницы, попробую разобраться. Можете приаттачить на мыло, .
Ответить | Ответить с цитатой | Цитировать
Paige
0 # Paige 24.09.2021 17:50
It's perfect time to make a few plans for the future and it's time to be happy.
I have read this put up and if I may I wish to counsel you some fascinating issues or
tips. Perhaps you could write next articles relating to this article.
I want to learn more issues approximately
it!

Also visit my homepage ... vh [Paige]
Ответить | Ответить с цитатой | Цитировать
Понятие дворяне
0 # Понятие дворяне 23.08.2022 22:18
{
{Я|я} просматривал онлайн-страницы более {трех|3|2|4}
часов сегодня, но так и не нашел ни одной интересной статьи,
подобной вашей. {Это|это} вполне достаточно для меня.
{По моему мнению|лично|по моему мнению}, если бы все {веб-мастера|владельцы сайтов|владельцы веб-сайтов|владельцы
веб-сайтов} и блоггеры делали хороший контент, как вы, {интернет|сеть|сеть}
будет {гораздо более| намного
больше} полезно, чем когда-либо
прежде.|
Я {не мог|не мог} {сопротивляться|воздерживаться} от
комментариев. {Очень хорошо|Отлично|Хорошо|Исключительно
хорошо} написано!|
{Я|я} {немедленно|немедленно} {схватит|схватит|сцепление|схватит|схватит|вырвет}
ваш {rss|rss-канал}, так как я {не могу|не могу}
{найти| найти|найти} вашу {email|e-mail}
подписку {ссылка|гиперссылка} или
{новостной бюллетень|электронный информационный бюллетень}.
У {у вас есть|у вас есть} какие-нибудь?
{Пожалуйста|любезно} {позвольте|разрешите|позвольте} мне {осознать|узнать|понять|узнать|узнать} {чтобы|для того, чтобы} я
{мог просто|мог|мог} подписаться.
Спасибо.|
{Это|это} {подходящее|идеальное|лучшее} время, чтобы строить планы на будущее, и {это|это} время быть счастливым.
{Я|я} прочитал этот пост, и если бы я мог,
я {хочу|хочу|хочу} предложить вам {несколько|некоторых} интересных вещей или {советов|предложений|подсказок}.
{Возможно|возможно} вы {могли бы|можете} написать следующие
статьи со ссылкой на эту статью.

Я {хочу|хочу|хочу} прочитать {больше|даже больше} вещей
об этом!|
{Сейчас|это} {подходящее|идеальное|лучшее} время, чтобы составить
{несколько|какие-то} планы на {будущее|долгосрочную|долгосрочную}
и {пришло|пришло} время быть счастливым.
{Я|я} {прочитал|узнал} это {опубликовать|отправить|опубликовать|выложить}, и если я {могу просто|могу|могу} я {хочу|хочу|желаю}
{предложить|рекомендовать |советовать} вам
{несколько|некоторые} {интересные|увлекательные|привлекающие внимание} {вещи|вопросы} или {советы|предложения|советы}.
{Возможно|возможно} вы {могли
бы|можете} написать {следующие|последующие}
статьи {относящиеся|относящиеся|относительно} этой статьи.
Я {хочу|хочу|желаю} {прочитать|узнать} {больше|даже больше}
{вещей|вопросов} {примерно|об этом}!|
{Я|я} был {серфингом|просматривал} {онлайн|он-лайн} {более|более} {трех|3} часов {в
эти дни|сегодня|сегодня|в последнее время|в последнее
время}, { пока|но} я {никогда|ни в коем случае} {никогда|никогда не находил|обнаружил} какую-либо {интересную|увлекательную|привлекающую внимание} статью,
подобную вашей. {Это|это} {прекрасно|красиво|красиво} {стоит|ценность|цена} {достаточно|достаточно} для меня.
{По моему мнению|лично|по моему мнению}, если все {веб-мастера|владельцы сайтов|владельцы веб-сайтов|владельцы веб-сайтов} и блоггеры сделали {правильно|хорошо|отлично} {контент|контент}, как {вы|вы,
вероятно, сделал}, {интернет|нет|веб} {будет|будет|может быть|вероятно будет|может быть|вероятно будет} {намного больше|намного больше} {полезнее|полезнее}, чем когда-либо прежде.|
Ага, это {мило|приятно|хорошо|привередливо} {обсуждение|разговор|диалог} {относительно|относительно|о|по теме} этой {статьи|поста|письма|абзаца} {здесь|в этом месте} на этом {блоге|веблоге|веб-странице|веб-сайте|веб-сайте} я прочитал все это, поэтому {сейчас|в это время} я также комментирую {здесь|в этом месте}.|
Я уверен, что эта {статья|пост|статья|абзац} тронула
всех {пользователей|людей|зрителей|посетителей} Интернета,
она действительно {милая|приятная|хорошая|привередливая} {статья|пост|часть письма |параграф} о создании нового {блога|веб-блога|веб-страницы|веб-сайта|веб-сайта}.|
Вау, эта {статья|пост|сочинение|абзац} {милая|приятная|хорошая|привередливая}, моя {сестра|младшая сестра} анализирует {такие|такие|такие} вещи, {так|таким образом| поэтому} я собираюсь {сказать|информировать|дать знать|передать} ей.|
{Сохранено в избранном|в закладках!!}, {мне очень нравится|мне нравится|мне нравится} {ваш
блог|ваш сайт|ваш веб-сайт|ваш веб-сайт}!|
Круто! Некоторые {очень|чрезвычайно}
важные моменты! Я ценю, что вы {написали это|написали
это} {статью|пост|рецензию} {и|а
также|плюс} остальную часть {сайта|веб-сайта} {также очень|чрезвычайно|очень|также действительно |действительно} хорошо.|
Привет, {я верю|я думаю} {это превосходно|это великолепно} {блог|веб-сайт|веб-сайт|сайт}.
Я натыкаюсь на это ;) {я|я собираюсь|я собираюсь|я могу} {вернуться|вернуться|пересмотреть} {еще раз|еще раз}
{так как я|так как у меня есть}
{закладка|книга отмечен|отмечен в
закладки|сохранен как избранное} это.
Деньги и свобода {лучший|величайший} способ измениться, пусть ты станешь богатым и продолжаешь {помогать|направлять} {другим людям|другим}.|
Вау! Я действительно {люблю|наслаждаюсь|копаюсь} в шаблоне/теме этого {сайта|веб-сайта|блога}.

Это просто, но эффективно. Очень часто
{очень сложно|очень сложно|сложно|тяжело|трудно|трудно} добиться «идеального баланса» между {превосходным удобством использования|удобством использования|юзабилити} и {внешним внешним видом|визуальной привлекательностью|внешним
видом}. Я должен сказать, {что вы|вы|вы} проделали {потрясающую|потрясающую|очень хорошую|превосходную|фантастическую|превосходную|о тличную} работу с этим.
{Кроме того|Дополнительно|Также} блог загружается {очень|чрезвычайно|супер} {быстро|быстро} для
меня в {Safari|Internet Explorer|Chrome|Opera|Firefox}.
{Превосходный|Исключительный|Выдающийся|Отличный} Блог!|
Это {действительно|на самом деле|на самом деле|действительно|искренне} {велико|огромные|я|впечатляющие|замечательные|фант астические}
идеи в {относительно|относительно|о|по теме} ведения
блога. Вы коснулись некоторых {хороших|приятных|хороших|привередливых} {точек|факторов|вещей} здесь.

В любом случае, продолжайте писать.

|
{Я люблю|мне очень нравится|мне нравится|мне нравится|всем нравится} то, что
вы, ребята, {обычно|обычно|склонны
делать} тоже. {Такой|такой тип|такой|такой вид} умной
работы и {разоблачения|освещения|репортажа}!
Продолжайте в том же духе {превосходно|потрясающе|очень
хорошо|отлично|хорошо|потрясающе|фантастически|отл ично|потрясающе|замечательно}, ребята, я {включил||добавил|включил} вас, ребята,
в {|мой|наш||мой личный |мой собственный} блогролл.|
{Привет|Привет|Привет|Привет|Привет|Привет}!
Кто-то из моей группы {Myspace|Facebook} поделился с нами этим {сайтом|веб-сайтом}, поэтому я пришел, чтобы {посмотреть|просмотреть|взглянуть|проверить}.

Я определенно {наслаждаюсь|люблю} информацию.
Я {book-marking|bookmarking} и буду твитить это своим
подписчикам! {Потрясающий|Замечательный|Отличный|Фантастический |Выдающийся|Исключительный|Превосходный|Отличный}
блог и {замечательный|потрясающий|блестящий|потрясающий|в еликолепный|отличный|фантастический|выдающийся|пре восходный} {стиль и дизайн|дизайн
и стиль|дизайн}. |
{Я люблю|мне очень нравится|мне
нравится|мне нравится|всем
нравится} то, что вы, ребята, {обычно|обычно|склонны делать} тоже.
{Такой|такой тип|такой|такой вид} умной работы и {разоблачения|освещения|репортажа}!
Продолжайте в том же духе {превосходно|потрясающе|очень хорошо|отлично|хорошо|потрясающе|фантастически|отл ично|потрясающе|замечательно}, ребята, я {включил|добавил|включил} вас, ребята, в {|мой|наш|мой личный|мой
собственный} блогролл.|
{Привет|Привет|Привет|Привет|Привет|Привет} не могли бы вы {указать|поделиться}, с какой платформой блога вы {работаете|используете}?
Я {надеюсь|планирую|собираюсь} начать
свой собственный блог {в ближайшем будущем|скоро}, но у меня {тяжелое|трудное|тяжелое} время {принимать решение|выбирать|выбирать|решать} между BlogEngine /Wordpress/B2evolution и Drupal.
Причина, по которой я спрашиваю, заключается в том, что ваш {дизайн и стиль|дизайн|макет}
отличается от большинства блогов, и я ищу что-то {совершенно
уникальное|уникальное}. P.S {Мои извинения|Извинения|Извините} за {получение|быть} не по теме,
но я должен был спросить!|
{Привет|Привет|Привет|Привет|Привет|Привет}
не могли бы вы сообщить мне, какой {веб-хостинг|хостинговая компания|веб-хостинг} вы {используете|работаете с|используете}?

Я загружал ваш блог в 3 {совершенно разных|разных} {интернет-браузерах|веб-браузерах|браузерах}, и я должен сказать, что этот
блог загружается намного {быстрее|быстрее},
чем большинство других. Можете ли вы {предложить|рекомендовать} хорошего поставщика {интернет-хостинга|веб-хостинга|хостинга} по {честной|разумной|справедливой} цене?
{Большое спасибо|Слава|Ура|Спасибо|Большое спасибо|Спасибо}, я ценю это!|
{Я люблю|Мне очень нравится|Мне
нравится|Все любят} это {когда люди|когда люди|когда люди|когда
люди} {собираются вместе|собираются вместе} и делятся {мнениями|мыслями|взглядами|идеями}.
Отличный {блог|веб-сайт|сайт}, {так
держать|продолжайте хорошую
работу|продолжайте в том же духе}!|
Спасибо за {благоприятный|хороший} отзыв.
На самом деле это был забавный счет.
Посмотрите продвинутый на {дальнее|еще} добавлено приятное от вас!
{Кстати|Однако}, как {можем|могли} мы общаться?|
{Привет|Привет|Привет|Привет|Привет|Привет} просто
хотел предупредить вас. {Текст|слова} в вашем {контенте|сообщении|статье} кажутся убегающими за пределы экрана в {т.е.|Internet Explorer|Chrome|Firefox|Safari|Opera}.
Я не уверен, является ли это проблемой {форматирования|форматирования}
или чем-то связанным с {веб-браузером|интернет-браузером|браузером}, но я {подумал|подумал}, что
опубликую, чтобы вы знали.
{стиль и дизайн|дизайн и стиль|макет|дизайн} выглядят
великолепно! Надеюсь, вы скоро
решите {проблема|вопрос} {решена|решена|исправлена}.
{Престижность|Ура|Большое спасибо|Спасибо}|
Это тема, {которая|это|которая} {близка|близка} к моему сердцу...
{Приветствую|Большое спасибо|С наилучшими пожеланиями|Береги себя|Спасибо}!

{Где|Где именно} находятся ваши контактные данные?|
Очень {легко|просто|беспроблемно|прямо|легко} найти любую {тему|вопрос}
в {сети|интернете} по сравнению с {книгами|учебниками}, так как я
нашел эту {статью|пост|часть письмо|абзац} на этом {веб-сайте|веб-сайте|сайте|веб-странице}.|
Есть ли на вашем {сайте|веб-сайте|блоге} контактная страница?
У меня {тяжелое время|проблемы|проблемы} найти его, но я хотел
бы {отправить|снять} вам {электронное письмо|электронное письмо}.
У меня есть {творческие идеи|рекомендации|предложения|идеи}
для вашего блога, которые, возможно,
вам будут интересны. В любом случае,
отличный {сайт|веб-сайт|блог}, и я с
нетерпением жду его {развития|улучшения|расширения|роста}
с течением времени.|
{Привет|Привет|Привет|Привет|Приветствую}!
Я {следил|читал} ваш {сайт|веб-сайт|веб-сайт|веб-блог|блог} в течение {долгого времени|некоторого времени|какое-то время} и, наконец, набрался {смелости|смелости}, чтобы пойти и дать вам привет от {Нью-Кейни|Кингвуд|Хаффман|Портер|Хьюстон|Даллас|О стин|Лаббок|Хамбл|Атаскочита} {Техас|Техас}!
Просто хотел {сказать вам|упомянуть|сказать} не отставать от {фантастической|отличной|отличной|хорошей} {работы|работы}!|
Привет из {Айдахо|Каролины|Огайо|Колорадо|Флориды|Лос-Анджелеса|Калифорнии}!
Мне {скучно до слез|скучно до смерти|скучно}
Ответить | Ответить с цитатой | Цитировать

Добавить комментарий


Работая с этим сайтом, вы даете свое согласие на использование файлов cookie, необходимых для сохранения выбранных вами настроек, а также для нормального функционирования сервисов Google.