Add transparency to elements that are not currently being hovered over using d3's mouseover feature

I'm attempting to implement a mouseover effect that increases the opacity of elements that are not being hovered on.

My SVG map consists of various regions, with the current function applying an opacity of 0.8 to the selected region.

My goal is to reverse this so that the remaining regions receive the opacity of 0.8.

Below is the snippet of my code:

function render(svg) {

  d3.select("body").node().append(svg.documentElement)

  data.forEach(d => {

    d3.selectAll(`g[aria-label="${d.id}"]`)
    .datum(data)
      .selectAll('path')
      .style("fill", colorScale(d.value))

      .on('mouseover', function() {
      d3.selectAll(`g[aria-label="${d.id}"]`)
                .filter(function(e) {
            return e.id !== d.id
          })
          .style('opacity', 0.8)
      })
      
      
       .on('mouseout', function() {
       d3.selectAll(`g[aria-label="${d.id}"]`)
         
          .style('opacity', 1)
      })

  })

I initially added e.id !==d.id to achieve this effect, but it yielded the opposite result.

Link to my fiddle: jsfiddle

Answer №1

e.id is undefined because e is linked to data. To address this issue, consider utilizing the following selector:

g[aria-label]:not([aria-label="${d.id}"])

This selector is designed to target all g elements with an aria-label, excluding those with an aria-label that matches d.id

For demonstration purposes, I have implemented the use of mouseenter to reduce the number of events triggering and applied a 0.5 opacity for visual impact:

var data = [{
    "id": "Scotland ",
    "value": 5000
  },
  {
    "id": "Wales ",
    "value": 3000
  },
  {
    "id": "Ireland ",
    "value": 750
  },
  {
    "id": "North West ",
    "value": 1250
  },
  {
    "id": "North East ",
    "value": 4500
  },
  {
    "id": "East Midlands ",
    "value": 2000
  },
  {
    "id": "South East ",
    "value": 350
  },
  {
    "id": "South West ",
    "value": 6000
  },
  {
    "id": "East of England ",
    "value": 4000
  },
  {
    "id": "West Midlands ",
    "value": 2500
  },
  {
    "id": "Northern Ireland ",
    "value": 1000
  },
  {
    "id": "Isle of Man ",
    "value": 3000
  },
  {
    "id": "Yorkshire and the Humber ",
    "value": 1500
  },
  {
    "id": "Greater London ",
    "value": 5000
  }

];


var colorScale = d3
  .scaleLinear()
  .domain(d3.extent(data, (d) => d.value))
  .range(["#5C4D87", "#EC4E6B"])
  .interpolate(d3.interpolateHcl)


const svgUrl = "https://raw.githubusercontent.com/gangrel11/samplefiles/main/amCharts.pixelMap.svg";

d3.xml(svgUrl).then(render);


function render(svg) {

  d3.select("body").node().append(svg.documentElement);
  
  data.forEach(d => {
    d3.selectAll(`g[aria-label="${d.id}"]`)
      .datum(data)
      .selectAll('path')
      .style("fill", colorScale(d.value))  
      .on('mouseenter', function() {
        d3.selectAll(`g[aria-label]:not([aria-label="${d.id}"])`)
          .style('opacity', 0.5)
      })
      .on('mouseout', function() {
        d3.selectAll(`g[aria-label]:not([aria-label="${d.id}"])`)
          .style('opacity', 1)
      })
  });
}
.amcharts-bg {
  fill: #EEF1FA
}

.amcharts-map-image {
  cursor: pointer;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>

Due to the slight separation of the hex shapes, there is noticeable flickering. To address this, an update can be made to the above example where hovering over a hex will maintain its opacity rather than reverting all hexes back to opacity of 1:

var data = [{
    "id": "Scotland ",
    "value": 5000
  },
  {
    "id": "Wales ",
    "value": 3000
  },
  {
    "id": "Ireland ",
    "value": 750
  },
  {
    "id": "North West ",
    "value": 1250
  },
  {
    "id": "North East ",
    "value": 4500
  },
  {
    "id": "East Midlands ",
    "value": 2000
  },
  {
    "id": "South East ",
    "value": 350
  },
  {
    "id": "South West ",
    "value": 6000
  },
  {
    "id": "East of England ",
    "value": 4000
  },
  {
    "id": "West Midlands ",
    "value": 2500
  },
  {
    "id": "Northern Ireland ",
    "value": 1000
  },
  {
    "id": "Isle of Man ",
    "value": 3000
  },
  {
    "id": "Yorkshire and the Humber ",
    "value": 1500
  },
  {
    "id": "Greater London ",
    "value": 5000
  }

];


var colorScale = d3
  .scaleLinear()
  .domain(d3.extent(data, (d) => d.value))
  .range(["#5C4D87", "#EC4E6B"])
  .interpolate(d3.interpolateHcl)


const svgUrl = "https://raw.githubusercontent.com/gangrel11/samplefiles/main/amCharts.pixelMap.svg";

d3.xml(svgUrl).then(render);


function render(svg) {

  d3.select("body").node().append(svg.documentElement);
  
  data.forEach(d => {
    d3.selectAll(`g[aria-label="${d.id}"]`)
      .datum(data)
      .selectAll('path')
      .style("fill", colorScale(d.value))  
      .on('mouseenter', function() {
        d3.selectAll(`g[aria-label]:not([aria-label="${d.id}"])`)
          .style('opacity', 0.5)
        d3.selectAll(`g[aria-label="${d.id}"]`)
          .style('opacity', 1)
      })
      .on('mouseout', function() {
      })
  });
    
}
.amcharts-bg {
  fill: #EEF1FA
}

.amcharts-map-image {
  cursor: pointer;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Using Selenium and Python to choose from a list of search results

Although I have come across similar questions, I have been unable to implement the suggested solutions in my specific case. Hence, I am reaching out for help regarding my particular problem. The code snippet in question is as follows: driver.get("ht ...

File handling in Angular 2 using Typescript involves understanding the fundamental syntax for managing files

Would someone be able to explain the fundamental syntax for reading and writing text files, also known as file handling in TypeScript? If there is a corresponding link that anyone could provide, it would be greatly appreciated. ...

What is the best way to choose two <li> elements with multiple classes in my WordPress navigation menu?

I am looking for a JavaScript function that will add the class "current_highlight" when an element with the class "activo2" also has the class "active". Here is my HTML code: <div class="navbar-header"> <button type="button " class="navbar-to ...

How can I incorporate fetch into my code using VSCode?

I am completely new to using JS. I want to incorporate fetch in VSCode, but I'm having trouble importing it. When I try: import fetch from "node-fetch"; I get this error: (node:19856) Warning: To load an ES module, set "type": &q ...

Looking to crop a canvas without changing its dimensions using jQuery

I'm currently working on a project that involves overlaying two images; one uploaded by the user and the other a default image. However, I am facing an issue when the uploaded image is a rectangle instead of a square, causing the canvas to resize it. ...

Hiding a specific tag with vanilla JavaScript based on its content

I am facing a challenge with my code that is supposed to hide div elements containing a specific word along with additional text. I have tried multiple solutions but none seem to work effectively. Any assistance on how to hide divs properly will be greatl ...

Creating a Dynamic Dropdown Menu in Rails 4

I am attempting to create a dynamic selection menu following this tutorial; however, I am encountering issues as the select statement does not seem to be updating. Below is the code snippet I currently have: #characters_controller.rb def new ...

Generating a dynamic row within a table using pdfMake

My JavaScript Array of Objects has the following structure: arr=[[1,2,3],[1,2,4],[3,5,6],[2,4,5]] I'm looking to remove the outer array from this data. The expected output is shown below. With this output, I plan to generate a table in pdfMake. The ...

Tips for accessing the information received from an AJAX call

When making an AJAX post request for processed data from the database in the form of an array [value1, value2, value3,...,valueN], I aim to use it on a ChartJS object. Here is the AJAX Request: $(document).ready($.post('callMeForAJAX.jsp', func ...

Verify if any choices are available before displaying the div block

I need to determine if there is a specific option selected in a dropdown menu, and then display a div if the option exists, otherwise hide it. I'm not just checking the currently selected option, but all available options. if (jQuery(".sd select opti ...

Interactive JavaScript button that navigates me to a document without the need to click

I'm facing an issue with my small project. I've been learning javascript and managed to create a script that calculates the square of a number provided by the user. var checkIt = function(){ var theNumber = Number(prompt("Please enter a number ...

The string that matches the duration of hour, minute, and second (HMS)

There is a need to extract the digits before h, m, and s into their own groups. The objective is to capture all three groups if possible, but if one or two groups are missing, then the last group(s) should be captured. Currently, the regex /(\d+)(?=h ...

The beforeCreate function is failing to execute when a new user is being created

I'm currently working with sailsjs version 0.11.0. My goal is to ensure that when a new user is created, their password is encrypted before being stored in the database. To achieve this, I have implemented the use of the bcrypt library. In my User.js ...

Tips for resuming a video playback in HTML5 after pausing it for a brief moment

I am working with a video called introVid, and my goal is for it to pause for 2 seconds when it reaches the 1 second mark before resuming playback. Although I've attempted to achieve this using the code below, the video remains in a paused state after ...

Displaying multiple div elements when a button is clickedLet multiple divs be

ISSUE Hello there! I'm facing a challenge where I need to display a div when a button is clicked. The issue arises from having multiple divs with the same class, making it difficult for me to target each individual div... Image1 Image2 Desired Outco ...

Tips for creating a validator function in Angular that only allows whole numbers between 0 and 30, excluding decimals

When a user enters a value between 0 and 30, the input should accept whole numbers like 0, 2, or 20 but not decimal values such as 20.1 or 0.1. I tried using validators min(0) and max(30), but they still allow decimal values. I need a validator that restr ...

Delete any fields that start with the name "XX"

Here is an example document extracted from a collection: { "teamAlpha": { }, "teamBeta": { }, "leader_name": "leader" } My goal is to remove all fields that begin with "team" from this document. Therefore, the expected outcome would be: {leader_name: "l ...

What is causing onbeforeunload to consistently display a dialog box?

I'm facing an issue where my javascript code displays a confirmation dialog even when there is no unsaved data. I have simplified the problem to this bare minimum: window.addEventListener("beforeunload", (e) => { e.returnValue = null; retu ...

Is there a way to prevent pop-up windows from appearing when I click the arrow?

Is there a way to display a pop-up window when the green arrow is clicked and then hide it when the arrow is clicked again? I tried using the code below but the pop-up window disappears suddenly. How can I fix this issue using JavaScript only, without jQue ...

Navigating with Angular - sending users to an external webpage?

When working with AngularJS routes, there is the option to use an otherwise route as a replacement for a 404 error: $routeProvider .when(...) .otherwise({ redirectTo: 'my/path' }); Is it possible to configure the otherwise route to redirect ...