實(shí)現(xiàn)一個(gè)Vue圖片熱區(qū)組件

目前在做的電商項(xiàng)目是通過(guò)cms系統(tǒng)生成了頁(yè)面配置的json文件來(lái)前端渲染頁(yè)面,其中有一個(gè)熱區(qū)組件,通過(guò)給圖片畫區(qū)域,然后用戶點(diǎn)擊不同區(qū)域跳轉(zhuǎn)到不同的頁(yè)面去瀏覽。

1.如何實(shí)現(xiàn)熱區(qū)

當(dāng)時(shí)想到的方法是通過(guò)定位根據(jù)json里面的配置的坐標(biāo)點(diǎn)來(lái)畫盒子。然后對(duì)這個(gè)盒子加一個(gè)點(diǎn)擊事件。想到這種方式去實(shí)現(xiàn)有點(diǎn)耗時(shí)間,先排除,去找度娘。通過(guò)度娘我們發(fā)現(xiàn),html是自帶有熱區(qū)的標(biāo)簽的maparea。心情一下子就舒暢了起來(lái),我們的宗旨是能少敲點(diǎn)代碼就盡量不多敲一個(gè)字母。

2.愉快的實(shí)現(xiàn)我們的熱區(qū)組件

  1. 通過(guò)查詢了解到一個(gè)熱區(qū)map會(huì)生成一系列的area,這個(gè)area就是每一塊的小熱區(qū)塊。area元素有一個(gè)coords屬性,這個(gè)屬性值是這個(gè)方形的坐標(biāo)點(diǎn)。同時(shí)我們需要給area標(biāo)簽上設(shè)置shape="rect"。
<map>
    <area shape="rect" coords="0,0,10,10"/>
</map>
  1. coords屬性的值如何排列
    coords的值是4個(gè),分別是由,號(hào)隔開(kāi)。前兩個(gè)表示起始點(diǎn)的坐標(biāo),我們?cè)跒g覽器頁(yè)面中坐標(biāo)系的0點(diǎn)是在我們的左上角,后面兩個(gè)是結(jié)束點(diǎn)的坐標(biāo),也就是起始點(diǎn)對(duì)角的坐標(biāo)點(diǎn)。


    image.png

    如上圖所示,那么我們這個(gè)區(qū)域的熱區(qū)coords的值就是‘10,10,20,25’

  2. 接口中給我們的坐標(biāo)點(diǎn)如何轉(zhuǎn)換成我們項(xiàng)目中的坐標(biāo)
    首先得和后端人員確定下,他們是以什么比例來(lái)畫的區(qū)塊。我們這邊后端cms系統(tǒng)中是以400的寬度生成的坐標(biāo)點(diǎn),那么前端在拿到坐標(biāo)點(diǎn)后,需要用后端的(默認(rèn)寬度400)/(屏幕的可視寬度)*(以坐標(biāo)值),那么上面的coords的值就是(屏幕可視寬度w = window.innerWidth)10 * (400/w),10 * (400/w),20 * (400/w),25 * (400/w)這個(gè)才是我們前端展示的真正的坐標(biāo)。
  3. 與圖片如何對(duì)應(yīng)
    熱區(qū)和圖片一一對(duì)應(yīng),需要在img標(biāo)簽上設(shè)置usemap屬性和ismap,然后在map標(biāo)簽上設(shè)置相同值的name和id與之對(duì)應(yīng)
<img src='path' usemap='img1' ismap>
<map name='img1' id='img1'>
  <area coords="x,x,x,x">
</map>

如上步驟,在area標(biāo)簽上加href屬性跳轉(zhuǎn)或者加click事件跳轉(zhuǎn),就能實(shí)現(xiàn)熱區(qū)效果了。

3. 封裝成vue組件

  1. 從上面步驟我們可以發(fā)現(xiàn),基本上map是不會(huì)變動(dòng)的變動(dòng)的只是area,如果有多個(gè)熱區(qū)的新增area就可以了。那么vue中我們可以通過(guò)v-for來(lái)遍歷我們熱區(qū)塊。
  2. 封裝通用組件
    template:
<template>
  <div>
      <slot name="img" :usemap="usemap">
      <map :name="usemap" :id="usemap">
        <area :coords="coords(p)" v-for="(p, i) in item.props" :key="i">
      </map>
  </div>
</template>

js:

function* nextId() {
  let index = 0;
  while(true) {
    yield index++;
  }
}
let mapAreaId = nextId();

export default {
  data(){
     return {
        index: 0
      }
  },
  props: {
    configDefaultWth: { // 后端默認(rèn)寬度
      type: [Number],
      default: 400
    },
    id: { // 熱區(qū)id
        type: String,
        default: 'id'
    }
   item: {
       type: [Object],
       default(){
          return {
            props: [
              "rightBottomSpot":"401,304",
                "leftTopSpot":"0,0",  // 坐標(biāo)
                "link":"B", // 跳轉(zhuǎn)地址
            ]
          }
        }
    }
    ...
  },
  mounted () {
    this.index = mapAreaId.next().value;
  },
  methods: {
    coords(item){
      return 計(jì)算的坐標(biāo)值
    }
  }
}

使用:

生成一個(gè)輪播圖熱區(qū)
<swipe>
  <swipe-item v-for="(item, index) in componentConfig.props"  :key="index" >
      <mapAreaImg :item="item" :id="item.componentType">
        <template slot="img" slot-scope="slotProps">
          <img :src="imgPath+item.urlPath" :usemap="slotProps.usemap" ismap alt="" srcset="">
        </template>
      </mapAreaImg>
  <swipe-item>
</swipe>

普通熱區(qū)
<mapAreaImg :item="item" :id="item.componentType">
   <template slot="img" slot-scope="slotProps">
      <img :src="imgPath+item.urlPath" :usemap="slotProps.usemap" ismap alt="" srcset="">
   </template>
</mapAreaImg>

到此一個(gè)vue的熱區(qū)組件就封裝完了,之所以想用slot-scope而不是直接傳一個(gè)img的src到組件中去,是想著圖片可以受父組件控制。如果本文對(duì)你有所幫助,可以幫忙點(diǎn)個(gè)小愛(ài)心,如果有不對(duì)的地方望大佬們多加指點(diǎn),康桑密達(dá)!

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容