The D3 chart encountered an issue with zooming and returned an error message stating "Unable to retrieve the length property of an undefined

I encountered an issue with my d3.v4 charts when zooming, resulting in the error message "Cannot read property 'length' of undefined" at line 'grp.select(".area").attr("d", area.x(function(d) {return xt(d);}));'. The browser console displayed:

**Uncaught TypeError: Cannot read property 'length' of undefined
    at SVGPathElement.t (d3.v4.min.js:2)
    at SVGPathElement.<anonymous> (d3.v4.min.js:2)
    at pt.each (d3.v4.min.js:2)
    at pt.attr (d3.v4.min.js:2)
    at SVGSVGElement.zoomed (pen.js:69)
    at p.apply (d3.v4.min.js:2)
    at N (d3.v4.min.js:2)
    at c.emit (d3.v4.min.js:2)
    at c.zoom (d3.v4.min.js:2)
    at d3.v4.min.js:2**

I need assistance resolving this error. You can view a CodePen example through the following link https://codepen.io/rohitbagde/pen/ZXEVRp

var dataArray=[11,14,27,30,43,47,60,69,77,100];
var dataMonths=[1,2,3,4,5,6,7,8,9,10];
var dataDate=[1,2,3,4,5,6,7,8,9,10];

var height=150;
var width=1000;
var parseMonth= d3.timeParse('%m');
var area = d3.area().x(function(d,i){return x(parseMonth(dataMonths[i]));} )
            .y0(height)
            .y1(function(d){return y(d);});


var svg = d3.select("body").append("svg").attr("height","100%").attr("width","100%");

var grp=svg.append('g').attr('transform','translate(40,0)').attr("class", "charts");

// Domain is referred to data i.e. x-axis
//This for y scale
var y=d3.scaleLinear().domain([0,200]).range([150,0]);
var x=d3.scaleTime()
.domain([d3.min(dataMonths,function(d){ return parseMonth(d);}),
        d3.max(dataMonths,function(d){ return parseMonth(d);})])
.range([0,1000]);

//This is for yaxis
var yAxis=d3.axisLeft(y).ticks(5).tickPadding(10);
var xAxis=d3.axisBottom(x);

grp.append('g').attr('class','axis y').call(yAxis);
grp.append('g').attr('class','axis x').attr('transform','translate(0,150)').call(xAxis);

//for plotting lines
grp.append("path")
  .attr("fill","none")
.attr("stroke","black")
.attr("stroke-width","2")
.attr("class", "area")
  .attr("d",area(dataArray));

//For plotting points
grp.selectAll("circle.grpcircle")
.data(dataArray)
.enter().append("circle")
.attr("class","circle")
.attr("cx",function(d,i){return x(parseMonth(dataMonths[i]));})
.attr("cy",function(d){return y(d);})
.attr("r",'4') 



 //For zooming
var zoom = d3.zoom()
    .scaleExtent([1, 32])
    .translateExtent([[0, 0], [width, height]])
    .extent([[0, 0], [width, height]])
    .on("zoom", zoomed);

var d0=parseMonth(1);
var d1=parseMonth(12);
 svg.call(zoom).transition()
      .duration(1500)
      .call(zoom.transform, d3.zoomIdentity
          .scale(width / (x(d1) - x(d0)))
          .translate(-x(d0), 0)); 

function zoomed() {
  var t = d3.event.transform, xt = t.rescaleX(x);
  area.x(function(d) {alert("Hi");return xt(d);});

  grp.select(".area").attr("d", area.x(function(d) {return xt(d);}));
  grp.select(".x").call(xAxis.scale(xt));
} 

Answer №1

To make it work, you need to initially bind the data array to the SVG path.

//for plotting lines
grp.append("path")
  .datum(dataArray)
  .attr("fill","none")
  .attr("stroke","black")
  .attr("stroke-width","2")
  .attr("class", "area")
  .attr("d",area);

var dataArray = [11, 14, 27, 30, 43, 47, 60, 69, 77, 100];
var dataMonths = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
var dataDate = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];

var height = 150;
var width = 1000;
var parseMonth = d3.timeParse('%m');
var area = d3.area().x(function(d, i) {
    return x(parseMonth(dataMonths[i]));
  })
  .y0(height)
  .y1(function(d) {
    return y(d);
  });


var svg = d3.select("body").append("svg").attr("height", "100%").attr("width", "100%");


svg.append("defs").append("clipPath")
  .attr("id", "clip")
  .append("rect")
  .attr("width", width)
  .attr("height", height);

var grp = svg.append('g').attr('transform', 'translate(40,0)').attr("class", "charts");

// Domain represents data for x-axis
//This is for y scale
var y = d3.scaleLinear().domain([0, 200]).range([150, 0]);
var x = d3.scaleTime()
  .domain([d3.min(dataMonths, function(d) {
      return parseMonth(d);
    }),
    d3.max(dataMonths, function(d) {
      return parseMonth(d);
    })
  ])
  .range([0, 1000]);

//This is for y axis
var yAxis = d3.axisLeft(y).ticks(5).tickPadding(10);
var xAxis = d3.axisBottom(x);

grp.append('g').attr('class', 'axis y').call(yAxis);
grp.append('g').attr('class', 'axis x').attr('transform', 'translate(0,150)').call(xAxis);

//for plotting lines
grp.append("path")
  .datum(dataArray)
  .attr("fill", "none")
  .attr("stroke", "black")
  .attr("stroke-width", "2")
  .attr("class", "area1")
  .attr("d", area);

grp.selectAll("circle.grpcircle")
  .data(dataArray)
  .enter().append("circle")
  .attr("class", "circle")
  .attr("cx", function(d, i) {
    return x(parseMonth(dataMonths[i]));
  })
  .attr("cy", function(d) {
    return y(d);
  })
  .attr("r", '4')

//For zooming
var zoom = d3.zoom()
  .scaleExtent([1, 32])
  .translateExtent([
    [0, 0],
    [width, height]
  ])
  .extent([
    [0, 0],
    [width, height]
  ])
  .on("zoom", zoomed);

var d0 = parseMonth(1);
var d1 = parseMonth(12);
svg.call(zoom).transition()
  .duration(1500)
  .call(zoom.transform, d3.zoomIdentity
    .scale(width / (x(d1) - x(d0)))
    .translate(-x(d0), 0));

function zoomed() {
  var t = d3.event.transform,
    xt = t.rescaleX(x);
  grp.select(".area1").attr("d", area.x(function(d, i) {
    return xt(parseMonth(dataMonths[i]));
  }));
  grp.select(".x").call(xAxis.scale(xt));
  grp.selectAll("circle")
    .attr("cx", function(d, i) {
      return xt(parseMonth(dataMonths[i]));
    });
}
html,
body {
  height: 100%;
}

.area1 {
  clip-path: url(#clip);
}
<body>

  <script src="https://d3js.org/d3.v4.min.js"></script>
</body>

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

Menu selection that changes dynamically based on radio button selection

Currently, I have four radio buttons and my goal is to have a drop-down menu change based on the selected radio button. Should I pre-write all the drop-down options and display them accordingly, or would it be better to use ajax to fetch the values from th ...

When utilizing res.redirect in Express, an error is triggered stating "Uncaught SyntaxError: Unexpected token <""

Utilizing Node.js, Express, Socket.io, firebase admin+auth, and Handlebars. An error Uncaught SyntaxError: Unexpected token < keeps popping up. Whenever I use res.redirect('/login');, I encounter the error. It disappears when I remove res.re ...

The view has no access to $scope but the controller does

I need to display the iso code using a $scope when selecting a country from a list. The list of countries is fetched through a $http call in a factory and then stored in a scope. ///////// get countries //////////////// tableFactory.getCountries().then(f ...

Creating a dynamic input box with an add/remove button in each row using jQuery

Need help with a jQuery-based UI that allows users to dynamically add input boxes. The desired look is as follows: Default appearance: INPUT_BOX [ADD_BUTTON] [REMOVE_BUTTON] Clicking on the [Add_Button] should add another row like this, and so on: ...

Eliminate blank double quotation marks in a JavaScript string

Hey there! Currently, I'm working on tidying up a JSON string. Let me show you an example of what I have: " .tagline-wrapper ":{ " padding-top":"398px", " font-size":" 1.8rem", " " }, ".tagline ":{ " padding-top":"398px", " font-size":" 1.8rem", " ", ...

What is the correct method for accessing $event in VueJS on Firefox after clicking an element?

Utilizing VueJS 2.3.0 to update images and other details when a user clicks on the menu. The menu is dynamically created using JSON data with a VueJS template: <template id=\"rac-menu\"> <ul class=\"col-md-3\" v-show=&bso ...

Leveraging Shared Workers within a React application

I am currently working on a backend app that continuously sends events to my React app through Web Sockets. One of the requirements is for a new browser tab to be opened when a specific event is received. However, since the application will be used by a si ...

Guide on how to navigate to a different webpage once the ajax request is complete

When making a JQuery ajax call to invoke a void method, I have encountered the need to redirect the user to the home page upon successful login. Below is an example of how this can be achieved: var options = { url: "/Account/Login", data: formvalu ...

Invoke a PHP function within the current file

One thing I'm wondering about is whether it's possible to call a php query from within the same file. Let me show you the code I have: <?php function aggiungiPagine(){ global $conn; header('Access-Control-Allow-Origin: *&apos ...

Is there a way to resolve an alert issue in Vue JS?

Exploring Vue, I have a basic index.html file where I added a click event to a button that should trigger an alert for the user. index.html <!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <meta http-equiv="X-UA-C ...

Troubleshoot the issue of the service function not being triggered

Seeking help with my Angular project as I am facing an issue with resolve and $resource. Despite spending a whole day on it, I couldn't find a solution. When using resolve to fetch data with $resource and ui-router, the service method never gets calle ...

Modifying icons with JavaScript

When I click on the play icon, it changes to the pause icon. However, I am only able to change the first icon from play to pause in my JavaScript code. How can I apply this functionality to all the audio elements on the page? let playIcon = "https://ima ...

Utilizing Angular for enhanced search functionality by sending multiple query parameters

I'm currently facing an issue with setting up a search functionality for the data obtained from an API. The data is being displayed in an Angular Material table, and I have 8 different inputs that serve as filters. Is there a way to add one or more s ...

Retrieve information from the Firebase database in order to update a text string

When I execute this function to retrieve data from firebase database app.listen(3000) app.engine('html', require('ejs').renderFile) var bodyParser = require('body-parser'); var sm = require('sitemap') var firebase ...

Transforming HTML 'img' elements into React components without losing styling: How do I achieve this with html-to-react?

I am seeking guidance regarding the usage of the html-to-react library. Consider the following html string: '<div> <img src="test.png" style="width: 100px;"/> <img src="test2.png" style="margin: 0px 4px;"/> </div>' ...

Unable to terminate ChildProcess on Ubuntu

I am attempting to terminate the application in Ubuntu with the following code: import {ChildProcess, exec} from "child_process"; export default class VisiviTTS { private static process?: ChildProcess; public static speak(text: string): ...

The 'exhaustive-deps' warning constantly insists on requiring the complete 'props' object instead of accepting individual 'props' methods as dependencies

This particular issue is regarding the eslint-plugin-react-hooks. While working in CodeSanbox with a React Sandbox, I noticed that I can use individual properties of the props object as dependencies for the useEffect hook: For instance, consider Example ...

Troubleshooting: Issues with MongoDB Aggregation not reflecting updates in my collection

Currently, I am attempting to execute an aggregation query in Mongo utilizing their nodejs driver. The query involves aggregating some fields, calculating averages, and other operations. I constructed the aggregation in Mongo Cloud and then exported it to ...

Exploring different ways to make API requests using technologies like jQuery, Angular, and more

I'm new to APIs and I want to create an eco game with Facebook for London and Amsterdam. To do this, I need to obtain data from APIs in each city. After doing some research, I think I can request information on the client side of the app, process it, ...

Updating an array element in Mongoose, the MongoDB ORM

I am currently in the process of making changes to a MongoDb collection that contains an array of documents called items. To achieve this, I am utilizing the express and mongoose frameworks. This is how my schema is structured: const mongoose = require(" ...