Разделите изображение на множество более мелких изображений и разрешите гиперссылки с каждого отдельного изображения (например, с карты изображений).

#css #vue.js #flexbox #vuetify.js

Вопрос:

Краткие сведения

У меня есть изображение (1920 пикселей x 1080 пикселей), которое я хочу разделить на изображения размером 40 пикселей на 40 пикселей. Я хочу отобразить изображения на веб-странице так, чтобы они выглядели как исходное полное изображение 1920х1080. Это будет 48 изображений шириной (столбцы) по 27 строк.

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

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

Рамки

В настоящее время использует Vue и Vuetify.

Пытался

  1. Я попытался использовать полное изображение, не разделяя его и не помещая на него карту изображений. Это отлично работает во время полноэкранного режима, однако, когда страница реагирует на изменение размера, координаты карты изображений изменяются по мере изменения размера основного изображения. Я не мог понять, как получить масштаб изображения, чтобы соответствующим образом настроить карту изображений.
     lt;template v-slot:activator="{ on, attrs }"gt;  lt;v-img ref="imageShow" usemap="" class="image" contain src="@/assets/sections/fullsize_image.jpg" v-resize="onResize"gt;  lt;!-- Loop over array of plots by row amp; col to generate this.  Eg. top: = rowId * 40...   left: = colPos * 40  --gt;  lt;span v-for="(i, row) in listSections"  :key="row"  justify="center" align="center" class="d-flex flex-nowrap"  gt;  lt;!-- i contains an object with URL, alt text etc in it --gt;  lt;span  v-for="col in Object.keys(i)"  :key="col"  gt;  lt;a v-bind="attrs" v-on="on" @click="info = i[col]" :style="`${ returnStyle(row,col) }`"gt;lt;/agt;  lt;/spangt;  lt;/spangt;  lt;/v-imggt;  lt;/templategt;  

А returnStyle-это вычисляемая функция, которая вычисляет карту изображения для разделов изображения. Если изображение скорректировано из-за реактивного изменения размера изображения, я не уверен, как это учесть в вычисляемой функции:

 computed: {  returnStyle: function() {  return function(row, col) {  return "position:absolute; top: "   (row * 40)   "px; left: "   (col * 40)   "px; height:40px; width: 40px;"  }  }  }  
  1. Я попробовал Vuetify v-row и v-col, чтобы содержать v-img… изображения неправильно уменьшались, или они обертывались, или просто прокручивались со страницы (класс=»d-flex flex-nowrap»).
     lt;v-container pa-0 fluid ma-0gt;  lt;v-row no-gutters style="maxWidth: 1920px; width: 100%;" class="d-flex flex-nowrap"gt;  lt;v-colgt;  lt;v-img :src="require(`../assets/section/section_0_0.jpg`)"gt;lt;/v-imggt;  lt;/v-colgt;  lt;!-- ... 46 more v-col/v-img's --gt;   lt;/v-rowgt;  lt;v-row no-gutters style="maxWidth: 1920px; width: 100%;" class="d-flex flex-nowrap"gt;  lt;v-colgt;  lt;v-img :src="require(`../assets/section/section_2_0.jpg`)"gt;lt;/v-imggt;  lt;/v-colgt;  lt;!-- ... 46 more v-col/v-img's --gt;   lt;/v-rowgt;   lt;v-row no-gutters style="maxWidth: 1920px; width: 100%;" class="d-flex flex-nowrap"gt;  lt;v-colgt;  lt;v-img :src="require(`../assets/section/section_2_0.jpg`)"gt;lt;/v-imggt;  lt;/v-colgt;  lt;!-- ... 46 more v-col/v-img's --gt;  lt;/v-rowgt;   lt;/v-containergt;  

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

Любые предложения будут высоко оценены. Спасибо.

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

1. Мне кажется немного кошмарным иметь так много изображений — и быть уверенным, что они будут абсолютно точно совпадать друг с другом (без разделения пикселей) независимо от размеров окна просмотра. Когда вы говорите, что хотите, чтобы для каждого из них был свой альтернативный текст, на самом ли деле вы хотите, чтобы программа чтения с экрана считывала правильно? А с точки зрения href для клика, чтобы переместить пользователя в нужное место?

Ответ №1:

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

Вот простой пример чисто JS/CSS:

 const numCols = 1920 / 40; const numRows = 1080 / 40; const container = document.querySelector('.container'); for (col = 1; col lt;= numCols; col  ) {  for (row = 1; row lt;= numRows; row  ) {  let a = document.createElement('a');  a.style.gridColumn = col   ' / '   (col   1);  a.style.gridRow = row   ' / '   (row   1);  a.style.opacity = 0;  a.href = 'url for cell '   row   ', '   col;  container.appendChild(a);  } } 
 * {  padding: 0;  margin: 0; }  .container {  display: grid;  grid-template-columns: repeat(40, 1fr);  grid-template-rows: repeat(27, 1fr);  width: 100vw;  height: calc(100vw * 1080 / 1920);  gap: 0;  background-image: url(https://picsum.photos/id/1016/1920/1080);  background-size: contain;  background-repeat: no-repeat; } 
 lt;div class="container"gt; lt;/divgt; 

Возможно, вам захочется включить фактический img с src (прозрачный png) в каждую ячейку, чтобы также добавить туда alt.

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

1. Удивительно, большое спасибо за это. Я просто сидел здесь последние 5 минут, играя с изменением размера окна, и это работает очень хорошо. Большое вам спасибо! Теперь, чтобы включить это в мой код Vue. 🙂