【问题标题】:Split image into many smaller images and allow hyperlinks from each individual image (like an imagemap)将图像分割成许多较小的图像,并允许来自每个单独图像的超链接(如图像映射)
【发布时间】:2022-01-06 06:02:21
【问题描述】:

总结

我有一张图片(1920 像素 x 1080 像素),我想将其拆分为 40 像素 x 40 像素的小图片。我想在网页上显示图像,使其看起来像原始的完整 1920x1080 图像。它将是 48 个图像宽(列)乘 27 行。

对于每张图片,我希望能够拥有不同的超链接和替代文本。

当屏幕尺寸发生反应性改变时,我希望图像也按比例缩小,这样它们就不会环绕页面,或者滚出页面。

框架

目前正在使用 Vue 和 Vuetify。

试过

  1. 我尝试过使用完整图像而不将其拆分并在其上放置图像映射。这在全屏时完美运行,但是,当页面响应调整以调整大小时,图像映射坐标会随着基础图像大小的变化而中断。我不知道如何获得图像的比例来相应地调整图像映射。

            <template v-slot:activator="{ on, attrs }">
            <v-img ref="imageShow" usemap="" class="image" contain src="@/assets/sections/fullsize_image.jpg" v-resize="onResize">
                <!-- Loop over array of plots by row & col to generate this.
                    Eg. top: = rowId * 40... 
                        left: = colPos * 40
                -->
                <span v-for="(i, row) in listSections"
                    :key="row"
                    justify="center" align="center" class="d-flex flex-nowrap"
                >
                    <!-- i contains an object with URL, alt text etc in it -->
                    <span
                        v-for="col in Object.keys(i)"
                        :key="col"
                    >
                        <a v-bind="attrs" v-on="on" @click="info = i[col]" :style="`${ returnStyle(row,col) }`"></a>
                    </span>
                </span>
            </v-img>
            </template>
    

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's 和 v-col's 来包含 v-img...图像没有正确缩小,或者它们正在换行或只是滚动页面 (class="d-flex flex-nowrap")。

     <v-container pa-0 fluid ma-0>
         <v-row no-gutters style="maxWidth: 1920px; width: 100%;" class="d-flex flex-nowrap">
             <v-col>
                 <v-img :src="require(`../assets/section/section_0_0.jpg`)"></v-img>
             </v-col>
             <!-- ... 46 more v-col/v-img's  -->                                  
         </v-row>
         <v-row no-gutters style="maxWidth: 1920px; width: 100%;" class="d-flex flex-nowrap">
             <v-col>
                 <v-img :src="require(`../assets/section/section_2_0.jpg`)"></v-img>
             </v-col>
             <!-- ... 46 more v-col/v-img's  -->                          
         </v-row>       
         <v-row no-gutters style="maxWidth: 1920px; width: 100%;" class="d-flex flex-nowrap">
             <v-col>
                 <v-img :src="require(`../assets/section/section_2_0.jpg`)"></v-img>
             </v-col>
             <!-- ... 46 more v-col/v-img's  -->
         </v-row>             
     </v-container>
    

我曾建议为此考虑使用 Flex 或 CSS Grid,但是,我有点担心我会结束对它们的试验并最终遇到同样的问题。

非常感谢任何建议。谢谢。

【问题讨论】:

  • 拥有这么多图像我听起来有点噩梦 - 并确保无论视口尺寸如何,它们都会绝对准确地相互对接(没有分割像素)。当你说你想要一个不同的替代文本时,你真的希望屏幕阅读器能正确读出吗?就点击将用户带到正确位置的href而言?

标签: css vue.js flexbox vuetify.js


【解决方案1】:

您可以将图像作为背景放置到具有视口宽度(或您需要的任何其他尺寸)的容器中,并据此计算合适的高度并显示为网格。

这是一个简单的纯 JS/CSS 示例:

const numCols = 1920 / 40;
const numRows = 1080 / 40;
const container = document.querySelector('.container');
for (col = 1; col <= numCols; col++) {
  for (row = 1; row <= 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;
}
<div class="container">
</div>

您可能希望在每个单元格中包含一个带有 src(透明 png)的实际 img,以便在其中也获取 alt。

【讨论】:

  • 太棒了,非常感谢。在过去的 5 分钟里,我刚刚坐在这里调整窗口大小,效果很好。太感谢了!现在把它改造成我的 Vue 代码。 :)
猜你喜欢
  • 2020-06-21
  • 2012-03-27
  • 2019-04-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-06-30
  • 1970-01-01
  • 2011-04-08
相关资源
最近更新 更多