我有一个多线图,我希望有一个工具提示,以便当我将鼠标悬停在线上时,它会显示x和y轴上的点。
我的数据位于下面的某个地方,我从某处here
重新呈现鼠标事件部分我的数据格式如下,我将它作为对象传递给组件之间的角色
{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));
}
}
我不确定 pricelineVar(d.values)在这里做了什么,我得到的错误是:
**core.js:1598 ERROR TypeError: Cannot read property 'peoplesum' of undefined
at SVGPathElement.<anonymous> (d3graph.component.ts:140)**
答案 0 :(得分:0)
通过将代码更改为以下代码段,我能够解决错误
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");