utilizing d3 version 4 to overlay d3 paths on google maps

I am working with a code snippet that integrates a google map and appends a layer over it. However, I have encountered an issue with the projection causing an error and preventing the layer from displaying on the google map alone. Any assistance in resolving this problem would be greatly appreciated. It's worth noting that I am utilizing version 4 of d3. Do you have any suggestions?


    var map = new google.maps.Map(d3.select("#map").node(), {
      zoom: 7,
      center: new google.maps.LatLng(31.5852,36.2384),
      mapTypeId: google.maps.MapTypeId.ROADMAP });

 d3.json("Export.json", function(error, jordanLevel2) {
      if (error) throw error
      var overlay = new google.maps.OverlayView();

      overlay.onAdd = function() {

        var layer = d3.select(this.getPanes().overlayLayer).append("div");

        overlay.draw = function() {

          layer.select('svg').remove();

          var w = 900;
          var h = 900;


          var overlayProjection = this.getProjection();

          // Turn the overlay projection into a d3 projection
          var googleMapProjection = function(coordinates) {
            var googleCoordinates = new google.maps.LatLng(coordinates[1], coordinates[0]);
            var pixelCoordinates = overlayProjection.fromLatLngToDivPixel(googleCoordinates);
            return [pixelCoordinates.x, pixelCoordinates.y];
          }

          var path = d3.geoPath().projection(googleMapProjection);


          var svg = layer.append("svg")
            .attr('width', w)
            .attr('height', h)

          var g = svg.append('g')
            .attr("id", "mapGroup");


          g.selectAll("path")
            .data(jordanLevel2.features)
            .enter()
            .append("path")
            .attr("d", path)
            .attr('class', 'state selected')

            .style('opacity', .7);

        }
      }
      overlay.setMap(map);

    });

Answer №1

Resolution

To ensure compatibility with D3 version 3, it is necessary to substitute the googleMapProjection function with the d3.geoTransform function:

transform = d3.geoTransform({point: function(x, y) {
                  d = new google.maps.LatLng(y, x);
                  d = overlayProjection.fromLatLngToDivPixel(d);
                  this.stream.point(d.x, d.y);
                }
              });

Subsequently, replace the existing path variable with:

var path = d3.geoPath().projection(transform);

Clarification

It appears that you are already familiar with the adjustments introduced in D3 version 4 as elaborated by Mike Bostock here. Notably, given that we are dealing with a planar transformation (converting geographical coordinates into pixels), employing d3.geoTransform() becomes imperative.

Both in versions 3 and 4, an analogous function is required where the inputs correspond to the latitude/longitude coordinates* of the outline for the overlay shape to be displayed atop the Google map. This function then translates these values into pixel positions within the SVG overlay via the fromLatLngToDivPixel method, subsequently relaying them back to the path object through the projection.stream method during the overlay rendering process.

Distinguishing aspects between versions 3 and 4 include:

  1. The inability to resort to the fallback projection mechanism necessitating the utilization of the projection.stream method instead.
  2. The alteration in the behavior of the googleMapProjection function, now encapsulated within the transform variable, which processes individual x and y coordinates rather than a unified array.

*or relative coordinates, e.g. leveraging topojson

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

Ways to stop the click event from being triggered in JQuery

There is a single toggle switch that, when clicked, switches ON and a popup with close and OK buttons appears. However, if the toggle is clicked again, it switches OFF and disappears. The specific requirement is that with every click where the toggle switc ...

There is an issue with transmitting data from an HTML page to the server and then retrieving data from the server

Upon running this code, I encountered an issue with sending and receiving data. I kindly request assistance in correcting my code. Highlighted below is the server-side code var http = require("http") ; var fs = require("fs") ; http.createServer(function( ...

Exploring the numerical values within a JavaScript array for comparison purposes

I am currently working with an array as shown below var nums = ["1", "2", "2", "3", "4", "4", "5"]; My goal is to compare the values in the array and determine whether they are in ascending order or not. In case two values in the array are identical, I ...

Is there a way to implement a css/javascript property specifically for a div that is selected in the url?

Take for instance the scenario where I possess the URL example.com/#foo. In this case, CSS styling will be directed to the div with the id foo. If achieving this solely in CSS is not feasible, what methods in JavaScript or jQuery can be used efficiently ...

Incorporating a prop in keyframe animation with styled components

How should props be properly used within animations: ${styledKeyFrame} ${props.myProps}? The problem: import styled from 'styled-components'; const KeyFrameTest = styled.keyframes` from { opacity: 0; } to { opacity: 1; } `; const Style ...

Live Search: Find Your Answers with Ajax

I've come across this issue multiple times, but haven't found a solution that fits my specific requirements. I've encountered several URLs with links like example.com/ajax/search?query=Thing I'm currently working on a header and using ...

Vue.js encountered an error during rendering: "Cannot read the length property of undefined."

I am working on a vuejs component that includes a select box. The first step involves selecting an agent or group, which then reveals the second select option. However, if the user fails to select an option from the first select, I want to hide the second ...

"Using AngularJS to display a blank option as preselected in an ng-option

Having an issue with displaying a preselected value as the selected option in my select element. Check out the code below: <select ng-model="data.company" ng-options="company as company.name for company in companies"></select> $scope.compani ...

Show a Jquery message, make an Ajax call, and finally conceal the message

Here's an example I'd like to share: document.ready(function() { $("#Show").bind("click", function() { var F = ExecuteFunction(); if (F) { // Perform other tasks. } } }); function Execute ...

Angular - Dealing with the value of zero in the @if template syntax

Having a dilemma with the Angular template flow syntax using @if. There is a value within an RxJs Observable, which is handled with the async pipe and assigned to a variable. @if (currentPageNumber$ | async; as currentPageNumber) { // currentPageNumber is ...

"Upon initial activation, the CSS animation will loop twice before coming to a stop

Is there a way to create a navigation bar that starts off transparent at the top of the page and then becomes opaque as you scroll down? I have tried implementing an animation for this effect, but it seems like the animation triggers twice when it should o ...

What is the best practice for incorporating CSS and JavaScript files into a PHP template?

I've created a basic template for my PHP website, but I'm struggling to find the best way to include my CSS and JavaScript files. Take a look at my index.php file below: <?php include'core/template.php'; $temp=new Template(); $sett ...

Tips for preventing the inner surface from appearing transparent in WebGL

I am working with the code snippet provided below. The issue I am currently facing is that one side of the partial sphere is non-transparent, while the other side remains transparent. How should I modify the code to make both sides non-transparent? Thank y ...

Unable to adjust layout when code is functioning alongside background-color

I'm looking to dynamically change the position of an item on my webpage when it is clicked. Is there a way I can achieve this without relying on id names? I currently have a code snippet that successfully changes the background color, but for some rea ...

Angular sending information from one page and retrieving it on another

The reportForm page allows users to input information and submit it to create a report. reportData = { headline: $scope.headline, fromDate: $scope.fldFromDate, toDate: $scope.fldToDate, whatever: $scope.whatever } $http.post(reportUrl + $scope.repor ...

There is no component factory available for the DialogDataExampleDialog. Have you ensured to include it in the @NgModule entryComponents?

Currently, I am a beginner in Angular. I recently started integrating MatDialog into my project. To do this, I followed the code provided on the official Angular documentation page https://material.angular.io/components/dialog/overview. However, upon click ...

In jQuery, a dropdown selection can be filled with multiple textboxes sharing the same class

I'm experimenting with the idea of using multiple textboxes with the same class filled with different dropdown options that also have the same class. However, I am encountering some issues. When I click on a dropdown option, it changes the value in a ...

Modifying an object's attribute in React.js by toggling a checkbox

As I delve into learning React, I am constructing a straightforward todo list. Here's the object contained within my initialState: getInitialState:function(){ return { items: [ { text:"Buy Fish", ...

Expanding an abstract class with Typescript

In order to create a new instance of a base abstract class that implements an interface, I have the interface, the base class, and some properties in an Angular component. Surprisingly, no errors are thrown in the browser (perhaps due to JavaScript's ...

The Functionality of JQuery Dropdowns

Just dipping my toes into the world of JQuery.. only about 2 hours in. Started working on a drop-down menu for a login box that looks like this: HTML: <button id="loginButton">Login</button> When you hover over the button, this JQuery functio ...