作者热门文章
- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我有一个基于 Angular d3 指令,用于创建多系列折线图。在该指令内有 mouseover
、mouseenter
和 mousemove
事件。出于某种原因,它们流向了不同的 div,其中包含相同的指令。当我将鼠标悬停在一个图表上时,它会在两个图表上绘制圆圈。有没有办法控制它?有人可以向我解释一下为什么示波器会像那样流血吗?
这是 d3 指令:
angular.module('MissionControlApp').directive('d3MultiSeriesLine', ['d3', function(d3) {
return {
restrict: 'E',
scope: {
data: '=',
keys: '=',
onClick: '&d3OnClick'
},
link: function(scope, ele) {
var svg = d3.select(ele[0])
.append("svg")
.attr("width", "100%");
// on window resize, re-render d3 canvas
window.onresize = function() {
return scope.$apply();
};
scope.$watch(function(){
return angular.element(window)[0].innerWidth;
}, function(){
return scope.render(scope.data);
}
);
// watch for data changes and re-render
scope.$watch("data", function(newVals) {
if(!newVals) return;
return scope.render(newVals);
}, true);
scope.render = function (data) {
if(!data) return;
svg.selectAll("*").remove();
// setup variables
var width, height;
var margin = {top: 5, right: 10, bottom: 20, left: 30};
width = d3.select(ele[0])[0][0].offsetWidth - margin.left - margin.right;
height = 300 - margin.top - margin.bottom;
// set the height based on the calculations above
svg.attr('height', height + margin.top + margin.bottom);
var parseDate = d3.time.format('%Y-%m-%dT%H:%M:%S.%LZ').parse;
var dateFormat = d3.time.format("%d %b");
var x = d3.time.scale()
.range([0, width]);
var y = d3.scale.linear()
.range([height, 0]);
var color = d3.scale.category10();
var xAxis = d3.svg.axis()
.scale(x)
.orient("bottom")
.ticks(6)
.tickFormat(dateFormat);
var yAxis = d3.svg.axis()
.scale(y)
.orient("left")
.ticks(9);
var line = d3.svg.line()
.interpolate("basis")
.x(function (d) { return x(d.date); })
.y(function (d) { return y(d.value); });
color.domain(scope.keys);
data.forEach(function (d) { d.date = parseDate(d.createdOn) });
x.domain(d3.extent(data, function(d) { return d.date; }));
var lineData = color.domain().map(function(name){
return {
name: name,
values: data.map(function (d) {
return {date: parseDate(d.createdOn), value: +d[name]};
})
}
});
var maxValue = d3.max(lineData, function(c) {
return d3.max(c.values, function(v) {
return v.value;
});
});
y.domain([0, maxValue + 20]);
// Add the X Axis
svg.append("g")
.attr("class", "axisMain")
.attr("transform", "translate(" + margin.left + "," + (height + margin.top) + ")")
.call(xAxis);
// Add the Y Axis
svg.append("g")
.attr("class", "axisMain")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")")
.call(yAxis);
var svgLine = svg.selectAll(".city")
.data(lineData)
.enter().append("g")
.attr("class", "city");
svgLine.append("path")
.attr("class", "line")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")")
.attr("d", function(d) { return line(d.values); })
.style("stroke", function(d) { return color(d.name); })
.attr("stroke-width", 1.5)
.attr("fill", "none")
.style("opacity", 0)
.transition()
.duration(1500)
.style("opacity", 1);
svgLine.append("text")
.datum(function(d) { return {name: d.name, value: d.values[d.values.length - 1]}; })
.attr("transform", function(d) { return "translate(" + x(d.value.date) + "," + y(d.value.value) + ")"; })
.attr("x", margin.left)
.attr("y", -2)
.attr("text-anchor", "end")
.attr("dy", ".35em")
.text(function(d) { return d.name; });
var mouseG = svg.append("g")
.attr("class", "mouse-over-effects");
mouseG.append("path") // this is the black vertical line to follow mouse
.attr("class", "mouse-line")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")")
.style("stroke", "grey")
.style("stroke-width", "1px")
.style("stroke-dasharray", "3,3")
.style("opacity", "0");
var lines = document.getElementsByClassName('line');
var mousePerLine = mouseG.selectAll('.mouse-per-line')
.data(lineData)
.enter()
.append("g")
.attr("class", "mouse-per-line");
mousePerLine.append("circle")
.attr("r", 6)
.style("stroke", function(d) { return color(d.name); })
.style("fill", "none")
.style("stroke-width", "1px")
.style("opacity", "0");
mousePerLine.append("text")
.attr("transform", "translate(10,-6)");
mouseG.append('svg:rect') // append a rect to catch mouse movements on canvas
.attr('width', width) // can't catch mouse events on a g element
.attr('height', height)
.attr('fill', 'none')
.attr("transform", "translate(" + margin.left + "," + margin.top + ")")
.attr('pointer-events', 'all')
.on('mouseout', function() { // on mouse out hide line, circles and text
d3.select(".mouse-line")
.style("opacity", "0");
d3.selectAll(".mouse-per-line circle")
.style("opacity", "0");
d3.selectAll(".mouse-per-line text")
.style("opacity", "0");
})
.on('mouseover', function() { // on mouse in show line, circles and text
d3.select(".mouse-line")
.style("opacity", "1");
d3.selectAll(".mouse-per-line circle")
.style("opacity", "1");
d3.selectAll(".mouse-per-line text")
.style("opacity", "1");
})
.on('mousemove', function() { // mouse moving over canvas
var mouse = d3.mouse(this);
d3.select(".mouse-line")
.attr("d", function() {
var d = "M" + mouse[0] + "," + height;
d += " " + mouse[0] + "," + 0;
return d;
});
d3.selectAll(".mouse-per-line")
.attr("transform", function(d, i) {
console.log(width/mouse[0]);
var xDate = x.invert(mouse[0]),
bisect = d3.bisector(function(d) { return d.date; }).right;
bisect(d.values, xDate);
var beginning = 0,
end = lines[i].getTotalLength();
var pos;
var target;
while (true) {
target = Math.floor((beginning + end) / 2);
pos = lines[i].getPointAtLength(target);
if ((target === end || target === beginning) && pos.x !== mouse[0]) {
break;
}
if (pos.x > mouse[0]) end = target;
else if (pos.x < mouse[0]) beginning = target;
else break; //position found
}
d3.select(this).select('text')
.text(y.invert(pos.y).toFixed(2));
return "translate(" + (mouse[0]+margin.left) + "," + (pos.y + margin.top) +")";
});
});
};
}
};
}]);
这是 HTML 代码:
<div class="row">
<div class="panel-group" id="p1">
<div class="panel panel-default">
<div class="panel-heading" data-toggle="collapse" data-parent="#p1" data-target="#collapseP1">
<h4 class="panel-title">Views / Views on Sheet</h4>
</div>
<div id="collapseP1" class="panel-collapse collapse in">
<div class="panel-body">
<d3-multi-series-line data="vm.d3ViewStatsData" keys="vm.ViewKeys" d3-on-click="vm.d3OnClick(item)"></d3-multi-series-line>
</div>
</div>
</div>
</div>
</div>
<div class="row">
<div class="panel-group" id="p2">
<div class="panel panel-default">
<div class="panel-heading" data-toggle="collapse" data-parent="#p2" data-target="#collapseP2">
<h4 class="panel-title">Schedules / Schedules on Sheet</h4>
</div>
<div id="collapseP2" class="panel-collapse collapse in">
<div class="panel-body">
<d3-multi-series-line data="vm.d3ViewStatsData" keys="vm.ScheduleKeys" d3-on-click="vm.d3OnClick(item)"></d3-multi-series-line>
</div>
</div>
</div>
</div>
</div>
最佳答案
这是我的一些旧代码:)
当我最初写这篇文章时,我假设文档中有一张图表。那里有几行在整个文档中全局选择/查找内容。像这样的行:
var lines = document.getElementsByClassName('line');
和
d3.selectAll(".mouse-per-line")
不是基于您的原始 elem[0]
的选择,因此不限于您的指令。
简单的解决方法是将所有 d3.select...
替换为 svg.select...
并将行替换为如下内容:
var lines = [];
svg.selectAll('line').each(function(){
lines.append(this);
});
关于javascript - d3.js 范围可能会溢出,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44438505/
java.lang.Throwable 的哪些子类可能被空语句抛出? 通过短语“空语句”,我指的是“无”、“分号”和“分号”: // .... A(); B(); C(); try { //
我是一名优秀的程序员,十分优秀!