gpt4 book ai didi

javascript - d3.js 范围可能会溢出

转载 作者:行者123 更新时间:2023-11-30 15:16:08 25 4
gpt4 key购买 nike

我有一个基于 Angular d3 指令,用于创建多系列折线图。在该指令内有 mouseovermouseentermousemove 事件。出于某种原因,它们流向了不同的 div,其中包含相同的指令。当我将鼠标悬停在一个图表上时,它会在两个图表上绘制圆圈。有没有办法控制它?有人可以向我解释一下为什么示波器会像那样流血吗?

enter image description here

这是 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/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com