向 jQuery 图像地图插件添加反向突出显示?

发布于 2024-08-11 06:23:16 字数 1505 浏览 4 评论 0原文

我正在使用 jQuery Map Hilighter 插件,但不是在每个区域上淡出深色斑块,我想扭转这一点,而是使周围区域变暗,使悬停区域保持相同的颜色。

我查看了该插件的代码,它似乎使用 canvas 元素(我猜是 MS 的等效元素)来进行突出显示。然而,Firebug 并不太清楚形状的定义位置 - 在上面的演示中它只是显示了这一点:

 <canvas style="border: 0pt none ; padding: 0pt; width: 960px; height: 593px; position: absolute; left: 0pt; top: 0pt; opacity: 1;" height="593" width="960"></canvas>

而且我看不到任何指定要悬停的元素形状的内容。这是 JS 中似乎正在创建形状的部分:

add_shape_to = function(canvas, shape, coords, options) {
    var i, context = canvas.getContext('2d');
    context.beginPath();
    if(shape == 'rect') {
        context.rect(coords[0], coords[1], coords[2] - coords[0], coords[3] - coords[1]);
    } else if(shape == 'poly') {
        context.moveTo(coords[0], coords[1]);
        for(i=2; i < coords.length; i+=2) {
            context.lineTo(coords[i], coords[i+1]);
        }
    } else if(shape == 'circ') {
        context.arc(coords[0], coords[1], coords[2], 0, Math.PI * 2, false);
    }
    context.closePath();
    if(options.fill) {
        context.fillStyle = css3color(options.fillColor, options.fillOpacity);
        context.fill();
    }
    if(options.stroke) {
        context.strokeStyle = css3color(options.strokeColor, options.strokeOpacity);
        context.lineWidth = options.strokeWidth;
        context.stroke();
    }
    if(options.fade) {
        fader(canvas, 0);
    }
};

I'm using the jQuery Map Hilighter plugin, but instead of fading a dark patch over each area, I would like to reverse this and instead make the surrounding area dark, keeping the hovered area the same colour.

I've looked at the code for the plugin and it appears to use the canvas element (and an MS equivalent I guess) to do the highlighting. However, Firebug isn't very forthcoming with exactly where the shapes are defined - on the demo above it just shows this:

 <canvas style="border: 0pt none ; padding: 0pt; width: 960px; height: 593px; position: absolute; left: 0pt; top: 0pt; opacity: 1;" height="593" width="960"></canvas>

And I can't see anything that specifies an element shape to hover. This is the part of the JS that appears to be creating the shape:

add_shape_to = function(canvas, shape, coords, options) {
    var i, context = canvas.getContext('2d');
    context.beginPath();
    if(shape == 'rect') {
        context.rect(coords[0], coords[1], coords[2] - coords[0], coords[3] - coords[1]);
    } else if(shape == 'poly') {
        context.moveTo(coords[0], coords[1]);
        for(i=2; i < coords.length; i+=2) {
            context.lineTo(coords[i], coords[i+1]);
        }
    } else if(shape == 'circ') {
        context.arc(coords[0], coords[1], coords[2], 0, Math.PI * 2, false);
    }
    context.closePath();
    if(options.fill) {
        context.fillStyle = css3color(options.fillColor, options.fillOpacity);
        context.fill();
    }
    if(options.stroke) {
        context.strokeStyle = css3color(options.strokeColor, options.strokeOpacity);
        context.lineWidth = options.strokeWidth;
        context.stroke();
    }
    if(options.fade) {
        fader(canvas, 0);
    }
};

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

浮云落日 2024-08-18 06:23:16

元素的形状被定义为 HTML 代码中

元素内的

元素。

您的问题的简单答案是在 context.beginPath(); 行之后添加类似的内容,然后在默认值中添加

  if (options.inverseFill) {
    context.rect(0,0, canvas.width,canvas.height);
  }

一个选项:inverseFill: true,,然后确保图像映射中的所有区域都以相同的顺时针方向声明。

发生的情况是,您为定义暗块的路径定义了一个额外的子路径,并且当您填充时,只要子路径的缠绕数取消,重叠区域(即原始块)就会抵消,从而导致你想要的倒立行为。

如果您的区域多边形定义可以双向旋转,事情就会变得更加复杂。例如,如果您对美国地图的原始 MapHilight 演示执行上述操作,则只有某些州会表现正确,因为它们的形状是按正确的顺时针方向定义的 - 其余州保持黑暗,因为它们的缠绕数字是错误的符号。

如果您可以完全控制图像映射定义,我的建议是保留它并确保所有区域都朝同一方向(即,只需反转每个不起作用的区域的坐标列表)。

如果没有,那么在初始化时您需要预先计算每个形状的缠绕数。这很可能涉及检查点列表并对每两个连续线段之间的角度求和 - 使用 atan2 计算。然后在 add_shape_to 函数中以正确的方向遍历画布的 4 个角。

无论如何,我希望这对您有所帮助

更新:

抱歉,我之前没有看到您的评论。
对于圆形区域,在 add_shape_to 函数中,替换
} else if(shape == 'circ') { 部分 with

  } else if(shape == 'circ') {
    context.closePath();
    context.moveTo(coords[0] + coords[2], coords[1]);
    context.arc(coords[0], coords[1], coords[2], 0, Math.PI * 2, true);
    context.closePath(); 
  }

它关闭前后子路径,然后移动到正确的位置,避免讨厌的红线到顶角,然后更改逆时针参数设置为 true 以匹配外部矩形。根据需要修改

The shapes of the elements are defined as <area> elements inside a <map> element in the HTML code.

The simple answer to your question is to add something like this

  if (options.inverseFill) {
    context.rect(0,0, canvas.width,canvas.height);
  }

after the context.beginPath(); line, then an option in the defaults: inverseFill: true,, and then to make sure that all the areas in your image map are declared in the same clockwise direction.

What happens is that you define an extra subpath for the path that defines the dark patch, and when you fill, the overlapping area (ie, the original patch) will cancel out, as long as the winding numbers of the subpaths cancel, resulting in your desired inverted behaviour.

It gets rather more complicated if your area polygon definitions can rotate in both directions. For example if you do the above for the original MapHilight demo of the US map, only some of the states will behave correctly, since their shapes are defined in the correct clockwise direction - the rest stay dark, as their winding numbers are the wrong sign.

If you have full control over the image map definition, my advice would be to leave it at that and just ensure all areas go the same direction (ie, just reverse the coords list for each area that doesn't work).

If not, then at init time you'd need to precalculate for each shape the winding number. This would most likely involve going over the list of points and summing the angle between every two consecutive segments - calculated using atan2. Then in the add_shape_to function traverse the 4 corners of the canvas in the correct direction.

Anyway, I hope that helps

Update:

sorry I didn't see your comment earlier.
for the circular area, in the add_shape_to function, replace the
} else if(shape == 'circ') { part with

  } else if(shape == 'circ') {
    context.closePath();
    context.moveTo(coords[0] + coords[2], coords[1]);
    context.arc(coords[0], coords[1], coords[2], 0, Math.PI * 2, true);
    context.closePath(); 
  }

It closes the subpath before and after, then moves to the correct place, to avoid nasty red line to the top corner, and then changes the anticlockwise parameter to true to match the outside rectangle. Modify as needed

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文