2016-02-17 19 views
0

在我的图中,我已将tooltip添加到路径中。但目前我只是用对象标签显示鼠标值。而不是显示鼠标值如何显示在点的确切数组值(绘图值)?d3js - 在`path`上如何显示`path`值而不是显示`mouse`值?

有人请帮我吗?

var datas = [ 
 
    {"date":1404075600000,"ActualPercentage" : 10, "PlanPercentage" : 5}, 
 
    {"date":1404680400000,"ActualPercentage" : 20, "PlanPercentage" : 15}, 
 
    {"date":1405285200000,"ActualPercentage" : 30, "PlanPercentage" : 25}, 
 
    {"date":1405890000000,"ActualPercentage" : 40, "PlanPercentage" : 35}, 
 
    {"date":1406494800000,"ActualPercentage" : 50, "PlanPercentage" : 45}, 
 
    {"date":1407099600000,"ActualPercentage" : 60, "PlanPercentage" : 55}, 
 
    {"date":1407704400000,"ActualPercentage" : 70, "PlanPercentage" : 65}, 
 
    {"date":1408309200000,"ActualPercentage" : 80, "PlanPercentage" : 85}, 
 
    {"date":1408914000000,"ActualPercentage" : 90, "PlanPercentage" : 90}, 
 
    {"date":1409518800000,"ActualPercentage" : 100, "PlanPercentage" :95} 
 
] 
 

 

 

 
var margin = {top: 20, right: 80, bottom: 30, left: 50}, 
 
    width = 960 - margin.left - margin.right, 
 
    height = 500 - margin.top - margin.bottom; 
 

 
var parseDate = d3.time.format("%Y%m%d").parse; 
 

 
var x = d3.time.scale().range([0, width]); 
 
var y = d3.scale.linear().range([height, 0]); 
 

 
var toolTipScale = d3.scale.linear().domain([height + 80, 80]).range([0, 100]); 
 
var iScale = d3.scale.linear().domain([width + 80, 80]).range([datas.length, 0]); 
 

 
var color = d3.scale.ordinal() 
 
     .domain(["ActualPercentage", "PlanPercentage"]) 
 
     .range(["#FF0000", "#009933"]); 
 

 
var xAxis = d3.svg.axis() 
 
    .scale(x) 
 
    .orient("bottom"); 
 

 
var yAxis = d3.svg.axis() 
 
    .scale(y) 
 
    .orient("left"); 
 

 
var line = d3.svg.line() 
 
    .interpolate("basis") 
 
    .x(function(d) { return x(d.date); }) 
 
    .y(function(d) { return y(d.temperature); }); 
 

 

 
var svg = d3.select("body").append("svg") 
 
    .attr("width", width + margin.left + margin.right) 
 
    .attr("height", height + margin.top + margin.bottom) 
 
    .append("g") 
 
    .attr("transform", "translate(" + margin.left + "," + margin.top + ")"); 
 

 
var div = d3.select("body").append("div") 
 
\t \t \t   .attr("class", "tooltips") 
 
\t \t \t   .style("opacity", 0); 
 

 
    color.domain(d3.keys(datas[0]).filter(function(key) { return key !== "date"; })); 
 

 
    datas.forEach(function(d) { 
 
    
 
    var date = new Date(d.date); 
 
    
 
    }); 
 

 
    var cities = color.domain().map(function(name) { 
 
    return { 
 
     name: name, 
 
     values: datas.map(function(d) { 
 
     return {date: d.date, temperature: +d[name]}; 
 
     }) 
 
    }; 
 
    }); 
 
    
 

 
    x.domain(d3.extent(datas, function(d) { return d.date; })); 
 

 
    y.domain([ 
 
    d3.min(cities, function(c) { return d3.min(c.values, function(v) { return v.temperature; }); }), 
 
    d3.max(cities, function(c) { return d3.max(c.values, function(v) { return v.temperature; }); }) 
 
    ]); 
 

 
    svg.append("g") 
 
     .attr("class", "x axis") 
 
     .attr("transform", "translate(0," + height + ")") 
 
     .call(xAxis); 
 

 
    svg.append("g") 
 
     .attr("class", "y axis") 
 
     .call(yAxis) 
 
    // .append("text") 
 
    // .attr("transform", "rotate(-90)") 
 
    // .attr("y", 6) 
 
    // .attr("dy", ".71em") 
 
    // .style("text-anchor", "end") 
 
    // .text("Temperature (ºF)"); 
 

 
    var city = svg.selectAll(".city") 
 
     .data(cities) 
 
     .enter().append("g") 
 
     .attr("class", "city"); 
 

 
    var path = city.append("path") 
 
     .attr("class", "line") 
 
     .style('cursor', 'pointer') 
 
     .attr("d", function(d) { return line(d.values); }) 
 
     .style("stroke", function(d) { return color(d.name); }); 
 
     
 
    var totalLength = [path[0][0].getTotalLength()]; 
 
    
 
    path 
 
     .attr("stroke-dasharray", totalLength + " " + totalLength) 
 
     .attr("stroke-dashoffset", totalLength) 
 
     .transition() 
 
     .duration(2000) 
 
     .ease("linear") 
 
     .attr("stroke-dashoffset", 0); 
 
     
 
var circles = city.selectAll("circle") 
 
     
 
\t \t \t \t \t  .data(function(d) { 
 
\t \t \t \t \t  return d.values 
 
\t \t \t \t \t  }) 
 
\t \t \t \t \t  .enter() 
 
\t \t \t \t \t  .append("circle") 
 
\t \t \t \t \t  .attr('class', 'circle') 
 
\t \t \t \t \t  .attr("r", 3.5) 
 
\t \t \t \t \t  .attr("cx", function(d, i) { 
 
\t \t \t \t \t  return x(d.date) 
 
\t \t \t \t \t  }) 
 
\t \t \t \t \t  .attr("cy", function(d) { 
 
\t \t \t \t \t  return y(d.temperature) 
 
\t \t \t \t \t  }) 
 
\t \t \t \t \t  .attr("fill", "transparent") 
 
\t \t \t \t \t  .attr("stroke", "black") 
 
\t \t \t \t \t  .attr("stroke-width", 0) 
 
\t \t \t \t \t  .transition() 
 
\t \t \t \t \t  .duration(3000) 
 
\t \t \t \t \t  .attr("stroke-width", 2); 
 
\t \t \t \t \t  
 
\t \t \t \t \t  path.on("mouseover", function (d, i) { 
 
\t \t \t \t \t \t 
 
\t \t \t \t \t \t div.transition() 
 
\t \t \t \t    .duration(200) 
 
\t \t \t \t    .style("opacity", 0.9); 
 

 
\t \t \t \t   div.html(d.name +" : " + Math.ceil(toolTipScale(d3.event.pageY))) 
 
\t \t \t \t    .style("left", (d3.event.pageX) + "px") 
 
\t \t \t \t    .style("top", (d3.event.pageY - 28) + "px"); 
 

 
\t \t \t \t \t }) 
 
\t \t \t \t \t .on("mouseout", function (d, i) { 
 
      \t \t \t \t 
 
      \t \t \t \t div.transition() 
 
\t \t \t \t    .duration(500) 
 
\t \t \t \t    .style("opacity", 0); 
 

 
\t \t \t \t \t })
body { 
 
    font: 10px sans-serif; 
 
} 
 

 
.axis path, 
 
.axis line { 
 
    fill: none; 
 
    stroke: #000; 
 
    shape-rendering: crispEdges; 
 
} 
 

 
.x.axis path { 
 
    display: none; 
 
} 
 

 
.line { 
 
    fill: none; 
 
    stroke: steelblue; 
 
    stroke-width: 1.5px; 
 
} 
 

 
body > div.tooltips { 
 
\t 
 
\t position: absolute; 
 
\t text-align: center; 
 
\t padding: 1em; 
 
\t font: 1.2em sans-serif; 
 
\t background: #02335D; 
 
\t border: 1px solid #fff; 
 
\t border-radius: 0.8em; 
 
\t pointer-events: none; 
 
\t color: #fff; 
 
\t white-space: no-wrap; 
 
} 
 
\t 
 
.overlay { 
 
\t fill: none; 
 
\t pointer-events: all; 
 
} 
 

 
.focus circle{ 
 
\t fill: none; 
 
\t stroke: steelblue; 
 

 
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>

+0

[* “?如何返回d3.js路径的y坐标” *](/ Q/12431595) – altocumulus

+0

见这里:http://stackoverflow.com/a/34887578/16363 – Mark

回答

2

我不知道是否有准确的显示在路径对鼠标的值的一些可能性。但是,可以在鼠标悬停的圆上显示工具提示值。

希望这是有帮助的。

工作代码段:

var datas = [{ 
 
    "date": 1404075600000, 
 
    "ActualPercentage": 10, 
 
    "PlanPercentage": 5 
 
}, { 
 
    "date": 1404680400000, 
 
    "ActualPercentage": 20, 
 
    "PlanPercentage": 15 
 
}, { 
 
    "date": 1405285200000, 
 
    "ActualPercentage": 30, 
 
    "PlanPercentage": 25 
 
}, { 
 
    "date": 1405890000000, 
 
    "ActualPercentage": 40, 
 
    "PlanPercentage": 35 
 
}, { 
 
    "date": 1406494800000, 
 
    "ActualPercentage": 50, 
 
    "PlanPercentage": 45 
 
}, { 
 
    "date": 1407099600000, 
 
    "ActualPercentage": 60, 
 
    "PlanPercentage": 55 
 
}, { 
 
    "date": 1407704400000, 
 
    "ActualPercentage": 70, 
 
    "PlanPercentage": 65 
 
}, { 
 
    "date": 1408309200000, 
 
    "ActualPercentage": 80, 
 
    "PlanPercentage": 85 
 
}, { 
 
    "date": 1408914000000, 
 
    "ActualPercentage": 90, 
 
    "PlanPercentage": 90 
 
}, { 
 
    "date": 1409518800000, 
 
    "ActualPercentage": 100, 
 
    "PlanPercentage": 95 
 
}] 
 

 

 

 
var margin = { 
 
    top: 20, 
 
    right: 150, 
 
    bottom: 30, 
 
    left: 50 
 
    }, 
 
    width = 960 - margin.left - margin.right, 
 
    height = 500 - margin.top - margin.bottom; 
 

 
var parseDate = d3.time.format("%Y%m%d").parse; 
 

 
var x = d3.time.scale().range([0, width]); 
 
var y = d3.scale.linear().range([height, 0]); 
 

 
var toolTipScale = d3.scale.linear().domain([height + 80, 80]).range([0, 100]); 
 
var iScale = d3.scale.linear().domain([width + 80, 80]).range([datas.length, 0]); 
 

 
var color = d3.scale.ordinal() 
 
    .domain(["ActualPercentage", "PlanPercentage"]) 
 
    .range(["#FF0000", "#009933"]); 
 

 
var xAxis = d3.svg.axis() 
 
    .scale(x) 
 
    .innerTickSize(-height) 
 
    .orient("bottom"); 
 

 
var yAxis = d3.svg.axis() 
 
    .scale(y) 
 
    .innerTickSize(-width) 
 
    .orient("left"); 
 

 
var line = d3.svg.line() 
 
    .x(function(d) { 
 
    return x(d.date); 
 
    }) 
 
    .y(function(d) { 
 
    return y(d.temperature); 
 
    }); 
 

 

 
var svg = d3.select("body").append("svg") 
 
    .attr("width", width + margin.left + margin.right) 
 
    .attr("height", height + margin.top + margin.bottom) 
 
    .append("g") 
 
    .attr("transform", "translate(" + margin.left + "," + margin.top + ")"); 
 

 
var div = d3.select("body").append("div") 
 
    .attr("class", "tooltips") 
 
    .style("opacity", 0); 
 

 
color.domain(d3.keys(datas[0]).filter(function(key) { 
 
    return key !== "date"; 
 
})); 
 

 
datas.forEach(function(d) { 
 

 
    var date = new Date(d.date); 
 

 
}); 
 

 
var cities = color.domain().map(function(name) { 
 
    return { 
 
    name: name, 
 
    values: datas.map(function(d) { 
 
     return { 
 
     date: d.date, 
 
     temperature: +d[name] 
 
     }; 
 
    }) 
 
    }; 
 
}); 
 

 

 
x.domain(d3.extent(datas, function(d) { 
 
    return d.date; 
 
})); 
 

 
y.domain([ 
 
    d3.min(cities, function(c) { 
 
    return d3.min(c.values, function(v) { 
 
     return v.temperature; 
 
    }); 
 
    }), 
 
    d3.max(cities, function(c) { 
 
    return d3.max(c.values, function(v) { 
 
     return v.temperature; 
 
    }); 
 
    }) 
 
]); 
 

 
svg.append("g") 
 
    .attr("class", "x axis") 
 
    .attr("transform", "translate(0," + height + ")") 
 
    .call(xAxis); 
 

 
svg.append("g") 
 
    .attr("class", "y axis") 
 
    .call(yAxis); 
 

 
var city = svg.selectAll(".city") 
 
    .data(cities) 
 
    .enter().append("g") 
 
    .attr('id', function(d) { 
 
    return d.name; 
 
    }) 
 
    .attr("class", "city"); 
 

 
var path = city.append("path") 
 
    .attr("class", "line") 
 
    .style('cursor', 'pointer') 
 
    .attr("d", function(d) { 
 
    return line(d.values); 
 
    }) 
 
    .style("stroke", function(d) { 
 
    return color(d.name); 
 
    }); 
 

 
var totalLength = [path[0][0].getTotalLength()]; 
 

 
path 
 
    .attr("stroke-dasharray", totalLength + " " + totalLength) 
 
    .attr("stroke-dashoffset", totalLength) 
 
    .transition() 
 
    .duration(2000) 
 
    .ease("linear") 
 
    .attr("stroke-dashoffset", 0); 
 

 
var circles = city.selectAll("circle") 
 
    .data(function(d) { 
 
    return d.values 
 
    }) 
 
    .enter() 
 
    .append("circle") 
 
    .attr('class', 'circle') 
 
    .attr("r", 3.5) 
 
    .attr("cx", function(d, i) { 
 
    return x(d.date) 
 
    }) 
 
    .attr("cy", function(d) { 
 
    return y(d.temperature) 
 
    }) 
 
    .attr("fill", "transparent") 
 
    .attr("stroke", "black") 
 
    .attr("stroke-width", 0); 
 

 
circles.transition() 
 
    .duration(3000) 
 
    .attr("stroke-width", 2); 
 

 
circles.on("mouseover", function(d, i) { 
 

 
    div.transition() 
 
     .duration(200) 
 
     .style("opacity", 0.9); 
 
    var data = d3.select(this.parentNode).select("path").data()[0]; 
 
    div.html(data.name + " : " + d.temperature) 
 
     .style("left", (d3.event.pageX) + "px") 
 
     .style("top", (d3.event.pageY - 28) + "px"); 
 

 
    }) 
 
    .on("mouseout", function(d, i) { 
 

 
    div.transition() 
 
     .duration(500) 
 
     .style("opacity", 0); 
 

 
    }); 
 

 
var legend = svg.selectAll('.legend') 
 
    .data(cities); 
 

 
var legends = legend 
 
    .enter() 
 
    .append('g') 
 
    .attr('class', 'legend') 
 
    .attr('transform', function(d, i) { 
 
    return "translate(" + (width+20) + "," + (i * 20) + ")"; 
 
    }); 
 

 
legends 
 
    .append('circle') 
 
    .attr('r', 7) 
 
    .style('fill', function(d) { 
 
    return color(d.name); 
 
    }); 
 

 
legends 
 
    .append('text') 
 
    .attr("dx", 10) 
 
    .attr("dy", 3.5) 
 
    .text(function(d) { 
 
    return d.name 
 
    }); 
 

 
legends.on('click', function(d) { 
 
    var path = d3.select("#" + d.name); 
 
    var visibility = path.style("opacity"); 
 
    path.style("opacity", visibility == 1 ? 0 : 1) 
 
});
body { 
 
    font: 10px sans-serif; 
 
} 
 
.axis path, 
 
.axis line { 
 
    fill: none; 
 
    stroke: #000; 
 
    shape-rendering: crispEdges; 
 
} 
 
.x.axis path { 
 
    display: none; 
 
} 
 
.line { 
 
    fill: none; 
 
    stroke: steelblue; 
 
    stroke-width: 1.5px; 
 
} 
 
body > div.tooltips { 
 
    position: absolute; 
 
    text-align: center; 
 
    padding: 1em; 
 
    font: 1.2em sans-serif; 
 
    background: #02335D; 
 
    border: 1px solid #fff; 
 
    border-radius: 0.8em; 
 
    pointer-events: none; 
 
    color: #fff; 
 
    white-space: no-wrap; 
 
} 
 
.overlay { 
 
    fill: none; 
 
    pointer-events: all; 
 
} 
 
.focus circle { 
 
    fill: none; 
 
    stroke: steelblue; 
 
} 
 
.tick line{ 
 
    opacity: 0.2; 
 
    stroke-dasharray: 5,5; 
 
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>

+0

是的,这工作正常。进一步扩大你的帮助,我需要2个按钮两个开关“关”,并用圆圈打开路径。所以用户可以查看他们想要的任何状态。你能不能更新一下呢? - 感谢您的延长帮助。 – 3gwebtrain

+0

你是否想要显示/隐藏圆圈? – Gilsha

+0

不仅包括路径的圈子。例如,点击绿色按钮时,我不想用圆圈显示绿线(让动画恢复)。 (切换数据) – 3gwebtrain