如何在AM Charts JavaScript中实现国家单选?修复选中状态异常
Hey, I get exactly what's going on here—when you click a new country, the old one deselects like it should, but hovering back over it brings that selected state right back. The core issue is that your current code only adjusts the fill property and calls setState("default"), but you're not accounting for the map component's built-in hover behavior overriding those changes. Here's how to fix it:
Why Your Current Code Fails
When you hover over a polygon, most map libraries (like AmCharts, which this code looks like it's using) automatically trigger a hover state that applies its own styling. Your code resets the old polygon to default state, but doesn't prevent the hover event from switching it back to a highlighted state when the mouse moves over it. Plus, directly modifying properties.fill can clash with the library's state-based styling system.
Solution: Control State and Hover Behavior Explicitly
We need to:
- Mark the currently active country so we can distinguish it from others
- Prevent hover styling from affecting the active country
- Properly reset the previous country's state and styling
Here's the revised code (adjust default/hover colors to match your setup):
// Define your default and hover colors first const defaultFill = "#e0e0e0"; // Replace with your actual default color const hoverFill = "#cccccc"; // Replace with your actual hover color let currentActive = null; // Clear existing event listeners to avoid duplicates polygonTemplate.events.off("hit"); polygonTemplate.events.off("over"); polygonTemplate.events.off("out"); // Handle country click polygonTemplate.events.on("hit", function (event) { // Reset previously active country if (currentActive) { currentActive.setState("default"); currentActive.properties.fill = defaultFill; currentActive.removeClass("active-country"); } // Set new active country chart.maxZoomLevel = 32; currentActive = event.target; currentActive.properties.fill = colorSet.getIndex(4); currentActive.addClass("active-country"); }); // Handle hover: only apply to non-active countries polygonTemplate.events.on("over", function (event) { const target = event.target; if (!target.hasClass("active-country")) { target.setState("hover"); target.properties.fill = hoverFill; } }); // Handle mouse out: only reset non-active countries polygonTemplate.events.on("out", function (event) { const target = event.target; if (!target.hasClass("active-country")) { target.setState("default"); target.properties.fill = defaultFill; } });
Even Better: Use Built-in State Management
If your map library supports state-based styling (like AmCharts does), use that instead of directly modifying fill properties—it's more reliable:
// Define state styles upfront when setting up the polygon template polygonTemplate.states.create("active", { fill: colorSet.getIndex(4) }); polygonTemplate.states.create("hover", { fill: "#cccccc" // Your hover color }); let currentActive = null; polygonTemplate.events.on("hit", function (event) { if (currentActive) { currentActive.setState("default"); } currentActive = event.target; currentActive.setState("active"); chart.maxZoomLevel = 32; }); // Block hover state for active countries polygonTemplate.events.on("over", function (event) { if (event.target.getState() !== "active") { event.target.setState("hover"); } }); polygonTemplate.events.on("out", function (event) { if (event.target.getState() !== "active") { event.target.setState("default"); } });
This way, the library handles all styling based on the element's state, so you don't have to manually sync fill properties and states.
内容的提问来源于stack exchange,提问作者Vijayant

