Javascript d3中的多线图工具提示出现错误
我有一个多线图,我想在上面有一个工具提示,这样当我将鼠标悬停在这条线上时,它会显示x轴和y轴上的点 我的数据在下表的某个地方,我从某个地方引用鼠标事件部分 我有我的数据在下面的格式,我传递它作为对象之间的角度组件Javascript d3中的多线图工具提示出现错误,javascript,angular,d3.js,Javascript,Angular,D3.js,我有一个多线图,我想在上面有一个工具提示,这样当我将鼠标悬停在这条线上时,它会显示x轴和y轴上的点 我的数据在下表的某个地方,我从某个地方引用鼠标事件部分 我有我的数据在下面的格式,我传递它作为对象之间的角度组件 {storeid: "", peoplesum: 137.14285714285714, date: "2018-06-02"} {storeid: "", peoplesum: 139.28571428571428, date: "2018-06-03"} {storeid: "",
{storeid: "", peoplesum: 137.14285714285714, date: "2018-06-02"}
{storeid: "", peoplesum: 139.28571428571428, date: "2018-06-03"}
{storeid: "", peoplesum: 123, date: "2018-06-04"}
{storeid: "", peoplesum: 144, date: "2018-06-05"}
{storeid: "", peoplesum: 150, date: "2018-06-06"}
{storeid: "", peoplesum: 154.28571428571428, date: "2018-06-07"}
{storeid: "", peoplesum: 159.85714285714286, date: "2018-06-08"}
{storeid: "", peoplesum: 145.71428571428572, date: "2018-06-09"}
{storeid: "", peoplesum: 129.42857142857142, date: "2018-06-10"}
{storeid: "", peoplesum: 147, date: "2018-06-11"}
{storeid: "", peoplesum: 123, date: "2018-06-12"}
代码
import { Component, OnInit, Input } from '@angular/core';
import * as d3 from "d3"
import * as d3Scale from 'd3-scale';
import * as d3Shape from 'd3-shape';
import * as d3Array from 'd3-array';
import * as d3Axis from 'd3-axis';
import {timeParse} from "d3-time-format";
@Component({
selector: 'app-d3graph',
template: `
<h2>{{subtitle}}</h2>
`
})
export class D3graphComponent implements OnInit {
@Input() storeIntraffic: string;
@Input() dateForD3: string;
@Input() peopleInSumStr: string;
title: string = 'D3.js with Angular 2!';
subtitle: string = 'Line Chart';
peopleInSumArr: any[];
private margin = {top: 20, right: 20, bottom: 30, left: 50};
private width: number;
private height: number;
private x: any;
private y: any;
private svg: any;
private priceline: any;
private line: d3Shape.Line<[number, number]>;
d3Data: any;
dashboard_date: any;
myArray: any[];
groupName: string;
data: any;
constructor() {
this.margin = { top: 30, right: 20, bottom: 70, left: 50 },
this.width = 1300 - this.margin.left - this.margin.right,
this.height = 800 - this.margin.top - this.margin.bottom;
}
ngOnInit() { }
ngAfterViewChecked() {
if (this.storeIntraffic !== undefined && typeof this.storeIntraffic === 'string') {
this.data = JSON.parse(this.peopleInSumStr);
this.peopleInSumArr = JSON.parse(this.peopleInSumStr);
this.dashboard_date = this.dateForD3;
// this.dashboard_date = this.dateForD3;
// console.log('d3 this.peopleInSumArr', this.peopleInSumStr);
// this.peopleInSumArr = JSON.parse(this.peopleInSumStr);
// console.log('d3 this.peopleInSumArr jajdjhdhjd', this.peopleInSumArr);
// console.log('this.dateForD3', this.dateForD3);
// this.storeIntraffic_plot();
this.initSvg();
this.initAxis();
this.drawAxis();
this.drawLine();
}
}
private initSvg() {
d3.select("svg").remove();
this.svg = d3.select("#svgcontainer")
.append("svg")
.attr("width", this.width + this.margin.left + this.margin.right)
.attr("height", this.height + this.margin.top + this.margin.bottom)
.append("g")
.attr("transform",
"translate(" + this.margin.left + "," + this.margin.top + ")")
.attr("stroke-width", 2);
}
private initAxis() {
// Parse the date / time
var parseDate = timeParse("%b %Y");
// Set the ranges
this.x = d3Scale.scaleTime().range([0, this.width]);
this.y = d3Scale.scaleLinear().range([this.height, 0]);
}
private drawAxis() {
var X = this.x;
var Y = this.y;
// Define the line
this.priceline = d3Shape.line()
.x(function (d) { return X(new Date(d.date)); })
.y(function (d) { return Y(d.peoplesum); });
}
private drawLine() {
var mindate = new Date(this.dashboard_date['startTime']),
maxdate = new Date(this.dashboard_date['endTime']);
this.x.domain(d3.extent([mindate, maxdate]));
// Scale the range of the data
var svgVar = this.svg;
var pricelineVar = this.priceline;
var margin = this.margin;
var height = this.height;
this.y.domain([0, d3.max(this.data, function (d) { return d.peoplesum; })]);
console.log("this.data", this.data);
// Nest the entries by symbol
var dataNest = d3.nest()
.key(function (d) { return d.storeid;})
.entries(this.data);
console.log("asdasd", dataNest);
// set the colour scale
var color = d3.scaleOrdinal(d3.schemeCategory10);
console.log("width", this.width);
console.log("width", dataNest.length);
var legendSpace = this.width / dataNest.length; // spacing for the legend
console.log("this.legendSpace", legendSpace);
// Loop through each symbol / key
dataNest.forEach(function (d, i) {
svgVar.append("path")
.attr("class", "line")
.style("stroke", function () { // Add the colours dynamically
return d.color = color(d.key);
})
.on("mouseover", onMouseOver)
.attr("d",d.peoplesum)
.attr("d", pricelineVar(d.values))
.attr("stroke-width", 3)
.style("fill", "none")
function onMouseOver(d, i) {
d3.select(this)
.attr('class', 'highlight');
d3.select(this)
.transition()
.duration(200)
//.attr('width', this.x.bandwidth() + 5)
.attr("y", function(d) { return this.y(d.peoplesum) - 10; })
.attr("height", function(d) { return height - this.y(d.peoplesum) + 10; })
.append("text")
.attr('class', 'val')
.attr('x', function() {
return this.X(d.date);
})
.attr('y', function() {
return this.Y(d.peoplesum) ;
})
}
// Add the Legend
svgVar.append("text")
.attr("x", (legendSpace / 2) + i * legendSpace) // space legend
.attr("y", height + (margin.bottom / 2) + 5)
.attr("class", "legend") // style the legend
.style("fill", function () { // Add the colours dynamically
return d.color = color(d.key);
})
.text(d.key)
.attr("stroke-width", 3)
});
console.log("after", dataNest);
// Add the X Axis
this.svg.append("g")
.attr("class", "axis")
.attr("transform", "translate(0," + this.height + ")")
.call(d3.axisBottom(this.x));
// Add the Y Axis
this.svg.append("g")
.attr("class", "axis")
.call(d3.axisLeft(this.y));
}
}
从'@angular/core'导入{Component,OnInit,Input};
从“d3”导入*作为d3
从“d3比例”导入*作为d3比例;
从“d3形状”导入*作为d3形状;
从“d3数组”导入*作为d3数组;
从“d3轴”导入*作为d3轴;
从“d3时间格式”导入{timeParse};
@组成部分({
选择器:“app-d3graph”,
模板:`
{{副标题}
`
})
导出类D3graphComponent实现OnInit{
@Input()storeIntraffic:字符串;
@Input()dateForD3:字符串;
@Input()peopleInSumStr:string;
标题:string='D3.js,带角度2!';
副标题:字符串='折线图';
人:任何[];
私人保证金={顶部:20,右侧:20,底部:30,左侧:50};
私有宽度:数字;
私人身高:数字;
私人x:任何;
私人y:任何;
私人svg:任何;
私人价格线:任何;
专用线:d3Shape.line;
数据:任何;
仪表盘日期:任何;
myArray:任意[];
groupName:string;
资料:有;
构造函数(){
this.margin={top:30,right:20,bottom:70,left:50},
this.width=1300-this.margin.left-this.margin.right,
this.height=800-this.margin.top-this.margin.bottom;
}
ngOnInit(){}
ngAfterViewChecked(){
if(this.storeIntraffic!==未定义和类型this.storeIntraffic==='string'){
this.data=JSON.parse(this.peopleInSumStr);
this.peopleinsumar=JSON.parse(this.peopleInSumStr);
this.dashboard_date=this.dateForD3;
//this.dashboard_date=this.dateForD3;
//log('d3 this.peopleinsumar',this.peopleInSumStr);
//this.peopleinsumar=JSON.parse(this.peopleInSumStr);
//log('d3 this.peopleinsumar jajdjhdhjd',this.peopleinsumar');
//log('this.dateForD3',this.dateForD3');
//此.storeintranffice_plot();
this.initSvg();
这个.initAxis();
这个.drawAxis();
这是一条绳();
}
}
私有initSvg(){
d3.选择(“svg”).remove();
this.svg=d3.select(#svgcontainer)
.append(“svg”)
.attr(“宽度”,this.width+this.margin.left+this.margin.right)
.attr(“高度”,this.height+this.margin.top+this.margin.bottom)
.附加(“g”)
.attr(“转换”,
“翻译(“+this.margin.left+”,“+this.margin.top+”)
.attr(“笔划宽度”,2);
}
私有initAxis(){
//解析日期/时间
var parseDate=timeParse(“%b%Y”);
//设定范围
this.x=d3Scale.scaleTime().range([0,this.width]);
this.y=d3Scale.scaleLinear().range([this.height,0]);
}
私人提款轴(){
var X=这个.X;
var Y=这个.Y;
//界定界线
this.priceline=d3Shape.line()
.x(函数(d){返回x(新日期(d.Date));})
.y(函数(d){返回y(d.peoplesum);});
}
专用抽绳(){
var mindate=新日期(此.dashboard_日期['startTime']),
maxdate=新日期(此.dashboard_日期['endTime']);
这个.x.域(d3.范围([mindate,maxdate]);
//缩放数据的范围
var svgVar=this.svg;
var pricelineVar=this.priceline;
var保证金=此保证金;
var高度=此高度;
this.y.domain([0,d3.max(this.data,函数(d){return d.peoplesum;})]);
log(“this.data”,this.data);
//按符号嵌套条目
var dataNest=d3.nest()
.key(函数(d){return d.storeid;})
.条目(此数据);
log(“asdasd”,dataNest);
//设置颜色比例
var color=d3.scaleOrdinal(d3.schemeCategory 10);
console.log(“宽度”,this.width);
log(“宽度”,dataNest.length);
var legendSpace=this.width/dataNest.length;//图例的间距
log(“this.legendSpace”,legendSpace);
//循环遍历每个符号/键
forEach(函数(d,i){
svgVar.append(“路径”)
.attr(“类”、“行”)
.style(“笔划”,函数(){//动态添加颜色
返回d.color=color(d.key);
})
.on(“鼠标悬停”,onMouseOver)
.attr(“d”,d.peoplesum)
.attr(“d”,pricelineVar(d.values))
.attr(“笔划宽度”,3)
.style(“填充”、“无”)
mouseover(d,i)上的函数{
d3.选择(本)
.attr(“类”、“突出显示”);
d3.选择(本)
.transition()
.持续时间(200)
//.attr('width',此.x.带宽()+5)
.attr(“y”,函数(d){返回这个.y(d.peoplesum)-10;})
.attr(“height”,函数(d){返回height-this.y(d.peoplesum)+10;})
.append(“文本”)
.attr('class','val')
.attr('x',function(){
返回此.X(d.date);
})
.attr('y',函数(){
返回此.Y(d.peoplesum);
})
}
//添加图例
svgVar.append(“文本”)
.attr(“x”,(legendSpace/2)+i*legendSpace)//空间图例
.attr(“y”,高度+(下边距/2)+5)
.attr(“类”、“图例”)//设置图例的样式
.style(“fill”,函数(){//动态添加颜色
返回d.color=color(d.key);
})
.文本(d.key)
.attr(“笔划宽度”,3)
});
log(“之后”,dataNest);
//添加X轴
this.svg.append(“g”)
.attr(“类”、“轴”
**core.js:1598 ERROR TypeError: Cannot read property 'peoplesum' of undefined
at SVGPathElement.<anonymous> (d3graph.component.ts:140)**
svgVar.selectAll("path")
.data(dataNest)
.enter()
.append("path")
.attr("class", "line")
.style("stroke", function () { // Add the colours dynamically
return d.color = color(d.key);
})
.on("mouseover", onMouseOver)
.attr("d", function(d) { return pricelineVar(d.values); })
.attr("fill","none");