繁体   English   中英

D3图表上的缩放和刷牙问题

[英]Zooming and Brushing issues on D3 chart

我在下面的代码中使用d3.area()而不是d3.line() 有两个组“焦点”“上下文” 焦点是主要图表,而上下文用于通过使用brushed()zoomed()选择范围。

问题在于,焦点区域的圆圈在上下文消失时会根据上下文群组中的选定范围正确移动。

我假设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> 

通过替换使它正常工作

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']); });    

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM