动态

详情 返回 返回

React中使用map+area標籤實現img圖片特定區域標記功能(可用Photoshop精準拾取對應點位) - 动态 详情

需求描述

  • 前段時間,工作中筆者接到了一個有意思的需求
  • 就是給圖片做特定的交互效果
  • 圖片中有幾個特殊區域
  • 當用户hover特殊區域的時候,高亮
  • 點擊特殊區域的時候,彈框給到一些提示信息

效果圖和線上演示

線上效果演示地址:https://ashuai.site/reactExamples/imagePoint

技術方案選擇

  • 這個需求如果圖片中的特定區域都是矩形
  • 我們完全可以直接使用通過定位的方式,寫幾個div去定位到相應的位置
  • 如下示例
<body>
  <!-- 父元素開啓絕對定位 -->
  <div class="wrap">
    <!-- 圖片和父元素寬高保持一致 -->
    <img src="./a.png" alt="a.png">
    <!-- 各個矩形設置寬高,再absolute微調定位到對應位置即可 -->
    <div class="rectangle1"></div>
    <div class="rectangle2"></div>
  </div>
</body>
  • 但若是圖片中的特定區域不是常見的矩形
  • 而是一些特殊的樣子形狀
  • 直接使用div就不太好畫出來了
  • 當然,我們也可以使用css的clip-path畫出來特定稀奇古怪的形狀
  • 但是,我們不太好控制形狀的大小寬高半徑之類的具體參數(不太好和圖片中的區域保持一致)

一些clip-path的繪製效果

當然,也可以使用svg或者canvas去繪製稀奇古怪的幾何圖形,但是針對於這種需求,不是最佳實踐

使用map和area標籤映射圖片關聯

代碼示意

  • 給img使用useMap取個唯一的名字(類似id),叫做#pathMap
  • 使用map映射剛剛的名字pathMap (#號類似錨點)
  • 這樣的話,就完成了圖片和圖片地圖的映射關係
  • 然後使用area標籤,在圖片的指定座標打點,搭配shape形狀,就能繪製出區域了
  <div>
    <img
        src={exampleImg}
        className="example-image"
        useMap="#pathMap"
    />
    <map name="pathMap">
        <area
            shape="rect"
            coords="84,188,200,255"
            href="#"
            onClick={(e) => { e.preventDefault(); showPathInfo('矩形區域'); }}
            title="矩形區域"
        />
    </map>
</div>

平面直角座標系知識

  • 矩形兩個點可以確定 84,188,200,255就是 x1 y1 x2 y2
  • 三角形三個點 439,158,513,284,366,284 就是 x1 y1 x2 y2 z1 z2
  • 圓形是一個點搭配一個半徑 752,221,72就是 x1 y1 r (r半徑的意思)
<area
    shape="rect"
    coords="84,188,200,255"
/>
<area
    shape="poly"
    coords="439,158,513,284,366,284"
/>
<area
    shape="circle"
    coords="752,221,72"
/>

使用Photoshop拾取對應點位

上述各個形狀的各個座標點,可以通過ps進行拾取確定

使用jquery和jquery.maphilight進行區域審查效果

  • map、area這兩個標籤,F12審查dom元素看不到
  • 可以自己不停按下Tab鍵進行切換查看,但是依舊不直觀
  • 這裏我們可以藉助jquery和jquery.maphilight這兩個庫
  • 在項目初始化的時候,進行一些對應的控制,如下
if ($ && $.fn.maphilight) {
    // 初始化maphilight,使用正確的選擇器
    // jquery選中圖片,使用jquery.maphilight.js提供的maphilight函數,進行高亮控制
    $('.example-image').maphilight({ 
        fill: true,          // 填充區域
        fillOpacity: 0.3,    // 填充透明度(0.3為半透明)
        // 為true的話,會初始高亮,為false的話,則是懸浮高亮
        // alwaysOn: true,
        alwaysOn: false,
    });
}

當然 我們要提前對應引入

<script src="/js/jquery-3.6.0.min.js"></script>
<script src="/js/jquery.maphilight.js"></script>

完整代碼

整個代碼在筆者的github倉庫裏:https://github.com/shuirongshuifu/react-examples

import React, { useEffect } from 'react'
import exampleImg from '@/assets/img/example.png'
import { message } from 'antd'

export default function ImagePoint() {
    useEffect(() => {
        // 確保 jQuery 和 maphilight 已加載
        if ($ && $.fn.maphilight) {
            // 初始化maphilight,使用正確的選擇器
            $('.example-image').maphilight({
                fill: true,          // 填充區域
                fillOpacity: 0.3,    // 填充透明度(0.3為半透明)
                // 為true的話,會初始高亮,為false的話,則是懸浮高亮
                // alwaysOn: true,
                alwaysOn: false,
            });
        }
    }, []);

    const showPathInfo = (pathName) => {
        message.info(pathName);
    };

    return (
        <div>
            <h2>圖片區域打點</h2>
            <p>鼠標懸停在圖片的矩形、多邊形、圓形區域上查看高亮效果,點擊查看信息</p>
            <img
                src={exampleImg}
                alt="example"
                className="example-image"
                useMap="#pathMap"
                style={{ width: 'fit-content', height: 'auto' }}
            />
            <map name="pathMap" id="pathMapID">
                <area
                    shape="rect"
                    coords="84,188,200,255"
                    href="#"
                    onClick={(e) => { e.preventDefault(); showPathInfo('矩形區域'); }}
                    alt="矩形"
                    title="矩形區域"
                />
                <area
                    shape="circle"
                    coords="752,221,72"
                    href="#"
                    onClick={(e) => { e.preventDefault(); showPathInfo('圓形區域'); }}
                    alt="圓形"
                    title="圓形區域"
                />
                <area
                    shape="poly"
                    coords="439,158,513,284,366,284"
                    href="#"
                    onClick={(e) => { e.preventDefault(); showPathInfo('多邊形區域'); }}
                    alt="多邊形"
                    title="多邊形區域"
                />
            </map>
        </div>
    )
}

參考:

user avatar dingtongya 头像 yangxiansheng_5a1b9b93a3a44 头像 cynthia_59675eba1a2ee 头像 waluna 头像 kasong 头像 gomi 头像 zengh 头像 jackn 头像 zhaoxiaoman 头像 jiavan 头像
点赞 10 用户, 点赞了这篇动态!
点赞

Add a new 评论

Some HTML is okay.