使 HTML 个地图元素可见

Make HTML map element visible

HTML 自古以来就支持图像地图。你知道,这种事情

<img src="url/to/your/image.jpg" alt="" usemap="#Map" />
<map name="Map" id="Map">
  <area href="#" shape="poly" coords="381,90,386,64,421,32,462,19,501,32,535,62,540,83" />
  <area href="#" shape="poly" coords="509,115,511,127,492,132,483,119,487,112" />
  <area href="#" shape="poly" coords="425,113,433,108,449,118,444,128,429,128" />
</map>

我在数据库中有一些数据可以确定图像的来源并定义命名的区域坐标集。这被存储为一个 JSON 的字符串,它被解析成一个对象图,并且 knockout 将它全部呈现到一个网页中,并带有点击处理程序,return 每个区域的正确标识符。

所有这一切都很好,我提到它只是为了提供操作上下文。

当用户点击一个区域时,我想切换它的可见性。例如,想象一下在解剖图上指示一个或多个受影响的受伤区域,或在保险索赔应用程序中指示汽车的弯曲部位,诸如此类。

问题是使某个区域可见。区域不渲染。所以我需要绘制图像。我知道这是可以做到的; google 地图做到了。

我不知道从哪里开始或搜索什么。这是我第一次需要直接绘制 - 通常我提供元素并让浏览器按它的意愿呈现。

那么,一些搜索词、关键词甚至视频教程链接怎么​​样?特别是我需要覆盖图像,所以我需要在相同的坐标 space 中绘制。当你们都忙着否决这个问题时,我将研究 "canvas" 和 "drawing over images"。

从对其他相关问题的回答来看,HTML 委员会似乎已经为 canvas 的图像地图争论了五年。

简短版本:你不能。

长版本:使用 canvas,将图像设置为背景并进行您自己的命中测试。

您可以 "highlight" 像这样映射您的 img 部分:

  • 使用 CSS
  • 准确覆盖相同大小的 canvas 元素
  • 告诉 canvas 不要响应 mouse/touch 事件:pointer-events:none
  • 单击映射区域时,告诉 canvas 使用路径命令以低不透明度填充绘制该区域:

    context.beginPath();
    context.moveTo(381,90);
    context.lineTo(386,64);
    context.lineTo(421,32);
    context.lineTo(462,19);
    context.lineTo(501,32);
    context.lineTo(535,62);
    context.lineTo(540,83);
    context.closePath();
    // fill the path area with a low-opacity red (or color of you choosing)
    context.globalAlpha=0.15;
    context.fillStyle='red';
    context.fill();   // this fills the path
    context.globalAlpha=1.00;  // just resetting to default opacity
    

这样您就可以保留使用 img 的现有代码。

或者,如果您的设计允许进行重大重构,您可以在 canvas 上绘制图像并使用 context.isPointInPath 对每条路径与鼠标单击位置进行命中测试。然后用低不透明度填充填充命中路径。

[补充:保存区域坐标供以后在命中测试中使用]

警告:未经测试的代码,可能需要调整

为了方便重复使用每个区域的坐标,您可以将每组坐标放在一个对象中,然后将这些对象放在一个数组中:

var areas=[];
// first area coordinates
arrays.push([ {x:381,y:90}, {x:386,y:64}, ... etc ]);
// second area coordinates
arrays.push([ {x:509,y:115}, {x:511,y:127}, ... etc ]);
...

然后使用这些保存的区域坐标进行命中测试:

function isMouseInArea(mouseX,mouseY){

    var index;  // index of any "hit" area. leave it initially null
    for(var i=0;i<areas.length;i++){

        // create a path from this area's coordinates
        defineAreaPath(areas[i]);

        // test if the mouse is inside this area
        if(ctx.isPointInPath(mouseX,mouseY)){
            index=i;
        }

    }
    // return any "hit" index of areas[] or return null if no hits
    return(index);
}

// utility function to define a path from the supplied coordinates
function defineAreaPath(pts){
    // create a path from this area's coordinates
    ctx.beginPath();
    ctx.moveTo(pts[0].x,pts[0].y);
    for(var i=1;i<pts.length;i++){
        ctx.lineTo(pts[i].x,pts[i].y);
    }
    ctx.closePath();
}

您可以像这样使用 isMouseInArea 函数:

var index=isMouseInArea(mouseX,mouseY)
if( index ){
    // draw the area path that was "hit" by the mouse
    defineAreaPath(areas[index]);
    // fill that path with low-opacity fill
    ctx.globalAlpha=0.15;
    ctx.fillStyle='red';
    ctx.fill();
    ctx.globalAlpha=1.00;
}