带有 JS 的 SVG 地图 - 更改悬停时多条路径的状态

Posted

技术标签:

【中文标题】带有 JS 的 SVG 地图 - 更改悬停时多条路径的状态【英文标题】:SVG Map w/ JS- Changing the states of multiple paths on hover 【发布时间】:2018-08-08 18:16:40 【问题描述】:

我正在使用 Raphael 库制作可点击的 SVG 地图,并参考来自 this tutorial 的详细信息。我还设置了一个工作 jsfiddle here。基本上,对于地图中的每个州,我都为地图形状本身和州缩写标签定义了路径——在小提琴的情况下,我展示了一个州,PA,用于演示目的。我为“区域”和“标签”定义了单独的数组。目前,我的悬停状态适用于状态形状(将其颜色更改为深蓝色),但希望在悬停状态时将状态缩写标签更改为白色。

我定义了以下数组和循环来处理区域(形状)的悬停和单击事件,我想添加逻辑来找到匹配的标签并将其填充属性更改为悬停时的白色(并恢复鼠标移出):

// REGION ARRAY
var regions = ;
regions["pennsylvania"] = href: "#", path: map.path("path here");

// LABEL ARRAY
var labels = ;
labels["pennsylvania"] = href: "#", path: map.path("path here");

// REGION STYLES
var animationSpeed = 500;
var shapeStyle = 
    fill: "#cdd6e9",
    stroke: "#fff",
    "stroke-width": 0.25,
    "stroke-linejoin": "round",
    cursor: "pointer"
;
var hoverStyle = 
  fill: "#0a3a62"


// REGION LOOP
for (var regionName in regions) 
    (function(region) 

        region.path.attr(shapeStyle);
        region.path[0].addEventListener("mouseout", function() 
            region.path.animate(shapeStyle, animationSpeed);
        , true);

        region.path[0].addEventListener("mouseover", function() 
            region.path.animate(hoverStyle, animationSpeed);
        , true);

        region.path[0].addEventListener("click", function() 
            location.href = region.href;
        , true);

    )(regions[regionName]);

因此,在遍历区域数组时,我将如何调整脚本以在标签数组中找到匹配的标签并更改其填充状态?感谢您在这里提供任何见解。

【问题讨论】:

为什么不传递regionName(而不是regions[regionName])作为函数参数。然后在循环中,您可以通过名称访问区域和标签?或者将其同时传递 (regions[regionName],labels[regionName]) 作为参数? 【参考方案1】:

在设置区域事件时设置标签事件,以便您可以在regionName 上进行匹配。您可以在 for 循环中使用 let 关键字,也可以按照 @Ian 的建议将 regionName 或两者(regions[regionName],labels[regionName])传递给立即函数。

var labelHoverStyle =  // add
    fill: '#FFFFFF'


var labelStyle = 
    fill: "#0a3a62",
    stroke: "#0a3a62",
    "stroke-width": 0.25,
    "stroke-linejoin": "round",
    cursor: "pointer" 

使用Let

for(let regionName in regions)  // notice the variable declaration
    (function (region) 

        if (regionName == "district-of-columbia") 
            region.path.attr(shapeStyle2);
            region.path[0].addEventListener("mouseout", function() 
            region.path.animate(shapeStyle2, animationSpeed);
            labels[regionName].path.animate(labelStyle, animationSpeed);
            , true);
         else 
            region.path.attr(shapeStyle);
            region.path[0].addEventListener("mouseout", function() 
            region.path.animate(shapeStyle, animationSpeed);
            labels[regionName].path.animate(labelStyle, animationSpeed);
            , true);
        

        region.path[0].addEventListener("mouseover", function() 
            region.path.animate(hoverStyle, animationSpeed);
            labels[regionName].path.animate(labelHoverStyle, animationSpeed);
        , true);

        region.path[0].addEventListener("click", function() 
            location.href = region.href;         
        , true);

    )(regions[regionName]);

传递 regionName 或 (regions[regionName],labels[regionName])

for(var regionName in regions) 
    (function (region, label)  // notice the parameters

        if (region.href.indexOf('district-of-columbia') > -1) 
            region.path.attr(shapeStyle2);
            region.path[0].addEventListener("mouseout", function() 
            region.path.animate(shapeStyle2, animationSpeed);
            label.path.animate(labelStyle, animationSpeed);
            , true);
         else  
            region.path.attr(shapeStyle);
            region.path[0].addEventListener("mouseout", function() 
            region.path.animate(shapeStyle, animationSpeed);
            label.path.animate(labelStyle, animationSpeed);
            , true);
         

        region.path[0].addEventListener("mouseover", function() 
            region.path.animate(hoverStyle, animationSpeed);
            label.path.animate(labelHoverStyle, animationSpeed);
        , true);

      ....

    )(regions[regionName], labels[regionName]); // notice the arguments

【讨论】:

不确定 regionName 在没有关闭的情况下是否可用,不过我可能错了。 @Ian 我也可能完全错了,但我的理解是在循环中声明的变量的作用域是外部函数,这使得词法范围可以访问内部立即函数。似乎在 jsfiddle 中工作......至少对于“宾夕法尼亚州”。 @ian 非常感谢您的回复-我已经更新了小提琴并将尝试添加到完整的地图中,看看是否一切正常 @nickpish 查看遵循@Ians 建议的更新答案。您可能还需要将 labels 定义移到此 for 循环上方。 @nickpish MDN 有一篇很好的文章介绍了闭包和函数工厂here,它们还介绍了您的确切用例here。我的错误是没有使用let 关键字(见上文)。问题是闭包都共享相同的词法环境,所以它只使用最后一次迭代的regionName

以上是关于带有 JS 的 SVG 地图 - 更改悬停时多条路径的状态的主要内容,如果未能解决你的问题,请参考以下文章

鼠标悬停时的SVG工具提示?

悬停链接并在 SVG 中更改颜色 [重复]

悬停时更改 SVG 填充和文本突出显示颜色

将鼠标悬停在图像上时如何更改 SVG 的颜色?

鼠标悬停时的 SVG 地图工具提示,可单击

悬停按钮时如何更改svg颜色