我在下面的代码中使用 d3.area()而不是 d3.line()。共有2组“焦点”和“上下文”。 焦点是主要图表,而上下文是使用 brushed()和 zoom()来选择范围。< / p>
问题是焦点组的圆圈正在根据上下文组中的选定范围正确移动,而区域正在消失。
我假设 area()没有返回正确的值。 JSFiddle
var data = [
{xLabel: "02:01:00", LastMonday: 200, Today: 500},
{xLabel: "03:02:00", LastMonday: 620, Today: 600},
{xLabel: "10:03:20", LastMonday: 300, Today: 800},
{xLabel: "10:04:00", LastMonday: 440, Today: 700},
{xLabel: "10:05:00", LastMonday: 900, Today: 900},
{xLabel: "10:06:30", LastMonday: 300, Today: 500},
{xLabel: "10:07:00", LastMonday: 50, Today: 300},
{xLabel: "11:08:00", LastMonday: 350, Today: 70},
{xLabel: "12:09:50", LastMonday: 750, Today: 200}
];
var textRotation = true;
var righttoleft = false;
var category = ['LastMonday', 'Today'];
var drawLine = ['Today'],
drawArea = ['LastMonday'];
function initLineChart(data, id) {
var mainwidth = $(id).innerWidth(),
mainheight = $(id).innerHeight();
function getPercent(actualval, perval)
{
return Math.round((actualval / 100) * perval);
}
var margin = {
top: getPercent(mainheight,4),
bottom: getPercent(mainheight,45),
},
margin2 = {
top: getPercent(mainheight,76),
bottom: getPercent(mainheight,16),
};
if(righttoleft)
{
margin.left = getPercent(mainwidth,4);
margin.right = getPercent(mainwidth,8);
margin2.left = getPercent(mainwidth,4);
margin2.right = getPercent(mainwidth,8);
}else
{
margin.left = getPercent(mainwidth,8);
margin.right = getPercent(mainwidth,4);
margin2.left = getPercent(mainwidth,8);
margin2.right = getPercent(mainwidth,4);
}
var width = $(id).innerWidth() - margin.left - margin.right,
height = $(id).innerHeight() - margin.bottom,
height2 = $(id).innerHeight() - margin2.top - margin2.bottom ;
var parseDate = d3.timeParse("%H:%M:%S");
var legendSize = 10,
legendColor = {'LastMonday': 'rgba(255, 160, 233, 0.6)', 'Today': 'rgba(0, 160, 233, 0.2)'};
var x = d3.scaleTime().range([0, width]),
x2 = d3.scaleTime().range([0, width]),
y = d3.scaleLinear().range([height, 0]),
y2 = d3.scaleLinear().range([height2, 0]);
var xAxis = d3.axisBottom(x).tickFormat(d3.timeFormat("%H:%M:%S"))
.tickPadding([6]).tickSize(-height),
xAxis2 = d3.axisBottom(x2).tickFormat(d3.timeFormat("%H:%M:%S")),
yAxis;
if(righttoleft){
yAxis = d3.axisRight(y).ticks(10).tickSize(-width);
}else
{
yAxis = d3.axisLeft(y).ticks(10).tickSize(-width);
}
var brush = d3.brushX()
.extent([[0, 0], [width, height2]])
.on("brush end", brushed);
var zoom = d3.zoom()
.scaleExtent([1, Infinity])
.translateExtent([[0, 0], [width, height]])
.extent([[0, 0], [width, height]])
.on("zoom", zoomed);
var ddata = (function() {
var temp = {}, seriesArr = [];
category.forEach(function (name) {
temp[name] = {category: name, values:[]};
seriesArr.push(temp[name]);
});
data.forEach(function (d) {
category.map(function (name) {
temp[name].values.push({'category': name, 'xLabel': parseDate(d.xLabel), 'num': d[name]});
});
});
return seriesArr;
})();
var ldata = (function() {
var temp = {}, seriesArr = [];
temp[drawLine[0]] = {category: drawLine[0], values:[]};
seriesArr.push(temp[drawLine]);
data.forEach(function (d) {
drawLine.map(function (name) {
temp[name].values.push({'category': name, 'xLabel': parseDate(d.xLabel), 'num': d[name]});
});
});
return seriesArr;
})();
var adata = (function() {
var temp = {}, seriesArr = [];
temp[drawArea[0]] = {category: drawArea[0], values:[]};
seriesArr.push(temp[drawArea]);
data.forEach(function (d) {
drawArea.map(function (name) {
temp[name].values.push({'category': name, 'xLabel': parseDate(d.xLabel), 'num': d[name]});
});
});
return seriesArr;
})();
x.domain( d3.extent(data, function(d) { return parseDate(d.xLabel); }) );
y.domain([
0,
d3.max(ddata, function(c) { return d3.max(c.values, function(v) { return v['num']; }); })+100
]);
x2.domain(x.domain());
y2.domain(y.domain());
var area = d3.area().curve(d3.curveLinear)
.x(function(d) { return x(d.xLabel); })
.y0(height)
.y1(function(d) { return y(d['num']); });
var area2 = d3.area().curve(d3.curveLinear)
.x(function(d) { return x2(d.xLabel); })
.y0(height2)
.y1(function(d) { return y2(d['num']); });
d3.select('#svg-disk').remove();
var svg = d3.select(id).append("svg")
.attr("id", "svg-disk")
.attr("viewBox", "0 1 " + mainwidth + " " + mainheight)
.attr("preserveAspectRatio", "xMinYMin");
svg.append("defs").append("clipPath")
.attr("id", "clip")
.append("rect")
.attr("width", width)
.attr("height", height);
svg.append("rect")
.attr("class", "zoom")
.attr("width", width)
.attr("height", height)
.attr("transform", "translate(" + margin.left + "," + margin.top + ")")
.call(zoom);
var focus = svg.append("g")
.attr("class", "focus")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
var context = svg.append("g")
.attr("class", "context")
.attr("transform", "translate(" + margin2.left + "," + margin2.top + ")");
focus.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
context.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height2 + ")")
.call(xAxis2);
context.append("g")
.attr("class", "brush")
.call(brush)
.call(brush.move, x.range());
focus.selectAll('.x .tick text').each(function(){
var dd = d3.select(this);
if(textRotation)
{
dd.attr("dx", "-1em")
.style("text-anchor", "end")
.attr("transform", "rotate(-65)")
.attr("dy", "1em");
}else
{
dd.attr("dx", "0em")
.style("text-anchor", "middle");
}
});
focus.append("g")
.attr("class", "y axis")
.call(yAxis);
var path = focus.selectAll(".gPath")
.data(adata)
.enter().append("g")
.attr("class", "gPath");
var path2 = context.selectAll(".gPath")
.data(adata)
.enter().append("g")
.attr("class", "gPath");
path.append("path")
.attr("d", function(d) { return area(d['values']); })
.attr("class", 'areaR');
path2.append("path")
.attr("d", function(d) { return area2(d['values']); })
.attr("class", 'areaR');
var lpath = focus.selectAll(".lpath")
.data(ldata)
.enter().append("g")
.attr("class", "lpath");
var lpath2 = context.selectAll(".lpath")
.data(ldata)
.enter().append("g")
.attr("class", "lpath");
lpath.append("path")
.attr("d", function(d) { return area(d['values']); })
.attr("class", "areaW");
lpath2.append("path")
.attr("d", function(d) { return area2(d['values']); })
.attr("class", "areaW");
var points = focus.selectAll(".seriesPoints")
.data(ddata)
.enter().append("g")
.attr("class", "seriesPoints");
points.selectAll(".tipPoints")
.data(function (d) { return d['values']; })
.enter().append("circle")
.attr("class", "tipPoints")
.attr("cx", function (d) { return x(d.xLabel); })
.attr("cy", function (d) { return y(d['num']); })
.text(function (d) { return d['num']; })
.attr("r", "6px")
.style("fill",function (d) { return legendColor[d['category']]; })
.style("stroke", "green")
.on("mouseover", function (d) {
var currentX = $(this)[0]['cx']['animVal']['value'],
currentY = $(this)[0]['cy']['animVal']['value'];
d3.select(this).transition().duration(100).style("opacity", 1);
var ret = $('circle').filter(function(index) {
return ($(this)[0]['cx']['animVal']['value'] === currentX && $(this)[0]['cy']['animVal']['value'] !== currentY);
});
var jud = ret.length;
var mainCate = (function() {
if (jud === 0)
return 'LastMonday/Today';
else
return d['category'];
})();
var viceCate = (function() {
if (category[0] === d['category'])
return category[1];
else
return category[0];
})();
$.each(ret, function(index, val) {
$(val).animate({
opacity: "1"
}, 100);
$(val).tooltip({
'container': 'body',
'placement': 'left',
'title': viceCate + ' | ' + $(this)[0]['textContent'],
'trigger': 'hover'
}).tooltip('show');
});
focus.append("g")
.attr("class", "tipDot")
.append("line")
.attr("class", "tipDot")
.transition()
.duration(50)
.attr("x1", x(d.xLabel))
.attr("x2", x(d.xLabel))
.attr("y2", height);
focus.append("polyline")
.attr("class", "tipDot")
.style("fill", "black")
.attr("points", (x(d.xLabel)-3.5)+","+(0-2.5)+","+x(d.xLabel)+","+(0+6)+","+(x(d.xLabel)+3.5)+","+(0-2.5));
focus.append("polyline")
.attr("class", "tipDot")
.style("fill", "black")
.attr("points", (x(d.xLabel)-3.5)+","+(y(0)+2.5)+","+x(d.xLabel)+","+(y(0)-6)+","+(x(d.xLabel)+3.5)+","+(y(0)+2.5));
try{
$(this).tooltip({
'container': 'body',
'placement': 'left',
'title': mainCate + ' | ' + d['num'],
'trigger': 'hover'
}).tooltip('show');
}catch(e){}
})
.on("mouseout", function (d) {
var currentX = $(this)[0]['cx']['animVal']['value'];
d3.select(this).transition().duration(100).style("opacity", 0);
var ret = $('circle').filter(function(index) {
return ($(this)[0]['cx']['animVal']['value'] === currentX);
});
$.each(ret, function(index, val) {
$(val).animate({
opacity: "0"
}, 100);
try{
$(val).tooltip('destroy');
}catch(e){}
});
d3.selectAll('.tipDot').transition().duration(100).remove();
try{
$(this).tooltip('destroy');
}catch(e){}
});
function brushed() {
if (d3.event.sourceEvent && d3.event.sourceEvent.type === "zoom") return; // ignore brush-by-zoom
var s = d3.event.selection || x2.range();
x.domain(s.map(x2.invert, x2));
focus.select(".x").call(xAxis);
focus.selectAll('.x .tick text').each(function(){
var dd = d3.select(this);
if(textRotation)
{
dd.attr("dx", "-1em")
.style("text-anchor", "end")
.attr("transform", "rotate(-65)")
.attr("dy", "1em");
}else
{
dd.attr("dx", "0em")
.style("text-anchor", "middle");
}
});
focus.select(".areaR").attr("d", area);
focus.select(".areaW").attr("d", area);
focus.selectAll('.tipPoints')
.attr("cx", function (d) { return x(d.xLabel); })
.attr("cy", function (d) { return y(d['num']); });
svg.select(".zoom").call(zoom.transform, d3.zoomIdentity
.scale(width / (s[1] - s[0]))
.translate(-s[0], 0));
}
function zoomed() {
if (d3.event.sourceEvent && d3.event.sourceEvent.type === "brush") return; // ignore zoom-by-brush
var t = d3.event.transform;
x.domain(t.rescaleX(x2).domain());
focus.select(".x").call(xAxis);
focus.selectAll('.x .tick text').each(function(){
var dd = d3.select(this);
if(textRotation)
{
dd.attr("dx", "-1em")
.style("text-anchor", "end")
.attr("transform", "rotate(-65)")
.attr("dy", "1em");
}else
{
dd.attr("dx", "0em")
.style("text-anchor", "middle");
}
});
focus.select(".areaR").attr("d", area);
focus.select(".areaW").attr("d", area);
focus.selectAll('.tipPoints')
.attr("cx", function (d) { return x(d.xLabel); })
.attr("cy", function (d) { return y(d['num']); });
context.select(".brush").call(brush.move, x.range().map(t.invertX, t));
}
return this;
}
var sca = new initLineChart(data, "#linechart");
html,body { width:100%; height:100%; margin:none; padding:none; }
#linechart { width:99%; height:99%; margin:none; padding:none; background-color:#e3ecf3;}
.axis path,
.axis line {
fill: none;
stroke: #f3f3f3;
shape-rendering: crispEdges;
}
.axis text {
font-size: .7em;
color: #a0a0a0;
}
.legendRect {
stroke: #aaabb1;
stroke-width: 1px;
fill: none;
}
.focus .tipPoints {
clip-path: url(#clip);
}
/*
.tipPoints {
stroke: white;
stroke-width: 2px;
opacity: 0;
}
.tipNetPoints {
stroke: white;
stroke-width: 2px;
opacity: 0;
}
.tipDot {
stroke: black;
stroke-width: 0.5px;
} */
.areaR {
fill: rgba(255, 160, 233, 0.6);
}
.areaW {
fill: rgba(0, 160, 233, 0.2);
stroke-width: 2px;
}
.tick {
font-family: serif;
font-size: 18px;
}
.zoom {
cursor: move;
fill: none;
pointer-events: all;
}
rect.selection
{
fill:green;
opacity: 0.4;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.5/js/bootstrap.min.js"></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
<div id="linechart" ></div>
答案 0 :(得分:0)
让它工作,通过替换
focus.select(".areaR").attr("d", area);
focus.select(".areaW").attr("d", area);
与
focus.select(".areaR").attr("d", function(d) { return area(d['values']); });
focus.select(".areaW").attr("d", function(d) { return area(d['values']); });