简体   繁体   English

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

[英]Zooming and Brushing issues on D3 chart

I'm using d3.area() instead of d3.line() in below code. 我在下面的代码中使用d3.area()而不是d3.line() There are 2 groups "focus" and "context" . 有两个组“焦点”“上下文” focus is the main chart while context is for selecting range by using brushed() and zoomed() . 焦点是主要图表,而上下文用于通过使用brushed()zoomed()选择范围。

Problem is circles of focus group are moving properly according to the selected range in context group while area is getting disappear. 问题在于,焦点区域的圆圈在上下文消失时会根据上下文群组中的选定范围正确移动。

I'm assuming area() is not returning proper values. 我假设area()没有返回正确的值。 JSFiddle 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> 

Got it working, By replacing 通过替换使它正常工作

focus.select(".areaR").attr("d", area);
focus.select(".areaW").attr("d", area);

with

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