Skip to content

Commit 6bebefc

Browse files
committed
Add two new Ref. Line viewing "verbosity" modes.
You can have a dotted line follow the mouse and extend to the top of the chart to see how well things line up. Or you can have "major" lines always show the dotted line going up to the top of the chart.
1 parent 0f99c72 commit 6bebefc

File tree

1 file changed

+149
-17
lines changed

1 file changed

+149
-17
lines changed

d3_resources/SpectrumChartD3.js

Lines changed: 149 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,6 @@ Feature TODO list (created 20160220):
4040
- Move to using D3 v6 with modules to minimize code sizes and such.
4141
- For peak labels, make a border around text (maybe add some padding, maybe make border same color as peak), make background translucent so you can read the text even if in a cluttered area.
4242
- Make sure that d3 selections are iterated over using each(...), rather than forEach(...)
43-
- lots of other issues
4443
*/
4544

4645
SpectrumChartD3 = function(elem, options) {
@@ -86,6 +85,7 @@ SpectrumChartD3 = function(elem, options) {
8685

8786
if( (typeof this.options.refLineWidth) !== 'number' ) this.options.refLineWidth = 1;
8887
if( (typeof this.options.refLineWidthHover) !== 'number' ) this.options.refLineWidthHover = 2;
88+
if( (typeof this.options.refLineVerbosity) !== 'number' ) this.options.refLineVerbosity = 0;
8989
if( (typeof this.options.featureLineWidth) !== 'number' ) this.options.featureLineWidth = 2;
9090

9191
this.options.refLineTopPad = 30;
@@ -401,6 +401,9 @@ SpectrumChartD3 = function(elem, options) {
401401
.on("touchstart", self.handleChartTouchStart())
402402
.on("touchend", self.handleChartTouchEnd())
403403
;
404+
405+
// Handle window blur (alt-tab away) to clean up mouse interactions
406+
d3.select(window).on("blur.chart" + this.chart.id, self.handleChartMouseLeave());
404407

405408
/*
406409
To allow markers to be updated while mouse is outside of the chart, but still inside the visual.
@@ -482,13 +485,6 @@ SpectrumChartD3 = function(elem, options) {
482485
.attr("x", 0)
483486
.attr("dy", "1em");
484487

485-
/*Add a small red circle on the x axis to help indicate which line the info is */
486-
/* currently showing for. */
487-
self.refLineInfo.append("circle")
488-
.attr("cx", 0)
489-
.attr("cy", self.size.height)
490-
.attr("r", 2)
491-
.style("fill","red");
492488

493489
this.chartBody = this.vis.append("g")
494490
.attr("clip-path", "url(#clip" + this.chart.id + ")");
@@ -1460,7 +1456,6 @@ SpectrumChartD3.prototype.handleResize = function( dontRedraw ) {
14601456

14611457
this.yAxisBody.attr("height", this.size.height );
14621458

1463-
this.refLineInfo.select("circle").attr("cy", this.size.height);
14641459
this.mouseInfo.attr("transform","translate(" + this.size.width + "," + this.size.height + ")");
14651460

14661461
if( this.xGrid ) {
@@ -2243,6 +2238,15 @@ SpectrumChartD3.prototype.handleChartMouseLeave = function() {
22432238
self.mousedOverRefLine = null;
22442239
self.refLineInfo.style("display", "none");
22452240
self.mouseInfo.style("display", "none");
2241+
2242+
const ref = self.vis.selectAll("g.ref");
2243+
ref.select("line.temp-extension").remove();
2244+
ref.select("circle.ref-hover-indicator").remove();
2245+
ref.selectAll("line")
2246+
.attr("stroke-width", self.options.refLineWidth );
2247+
ref.select(".major-extension")
2248+
.style("opacity", 0.5)
2249+
.style("stroke-width", self.options.refLineWidth);
22462250
}
22472251
}
22482252

@@ -4057,13 +4061,13 @@ SpectrumChartD3.prototype.drawRefGammaLines = function() {
40574061
const h = self.size.height;
40584062
const m = Math.min(h,self.options.refLineTopPad); // leave 20px margin at top of chart
40594063

4060-
gy.enter().insert("g", "a")
4064+
gy.enter()
4065+
.insert("g", "a")
40614066
.attr("class", "ref")
40624067
.attr("transform", tx)
40634068
.append("line")
40644069
.style("stroke-dasharray", dashfunc )
40654070
.attr("stroke", stroke )
4066-
.attr("stroke-width", self.options.refLineWidth )
40674071
.attr("y1", h )
40684072
.attr("dx", "-0.5" );
40694073

@@ -4086,9 +4090,34 @@ SpectrumChartD3.prototype.drawRefGammaLines = function() {
40864090
*/
40874091

40884092
gy.select("line")
4093+
.attr("stroke-width", self.options.refLineWidth )
40894094
.attr("y2", y2Lin )
40904095
//.attr("y2", y2Log )
40914096
.attr("y1", h ); //needed for initial load sometimes
4097+
4098+
// Add dotted extension lines for major reference lines (only if refLineVerbosity >= 2)
4099+
if( self.options.refLineVerbosity >= 2 ) {
4100+
const majorLines = gy.filter(function(d) { return d.major; });
4101+
4102+
// Remove any existing major line extensions
4103+
gy.select("line.major-extension").remove();
4104+
4105+
// Add dotted extension lines for major lines
4106+
const extension_dash = "" + self.options.refLineWidthHover + "," + 2*self.options.refLineWidthHover;
4107+
majorLines.append("line")
4108+
.attr("class", "major-extension")
4109+
.style("stroke-dasharray", extension_dash)
4110+
.style("opacity", 0.5)
4111+
.attr("stroke", stroke)
4112+
.attr("stroke-width", self.options.refLineWidth)
4113+
.attr("y1", function(d) { return y2Lin(d); })
4114+
.attr("y2", self.options.refLineTopPad)
4115+
.attr("x1", 0)
4116+
.attr("x2", 0);
4117+
} else {
4118+
// Remove any existing major line extensions if verbosity < 2
4119+
gy.select("line.major-extension").remove();
4120+
}
40924121
}
40934122

40944123

@@ -4156,6 +4185,12 @@ SpectrumChartD3.prototype.setRefLineWidths = function( width, hoverWidth ) {
41564185
this.options.refLineWidth = width;
41574186
this.options.refLineWidthHover = hoverWidth;
41584187
this.drawRefGammaLines();
4188+
this.updateMouseCoordText();
4189+
}
4190+
4191+
SpectrumChartD3.prototype.setRefLineVerbosity = function( verbosity ) {
4192+
this.options.refLineVerbosity = verbosity;
4193+
this.drawRefGammaLines();
41594194
}
41604195

41614196
SpectrumChartD3.prototype.setKineticReferenceLines = function( data ) {
@@ -4412,7 +4447,26 @@ SpectrumChartD3.prototype.updateMouseCoordText = function() {
44124447
/* but with out it sometimes lines will stay fat that arent supposed to. */
44134448
/* Also, I think setting attr values is expensive, so only doing if necassary. */
44144449
if( d.__data__.mousedover && d !== self.mousedOverRefLine ){
4415-
d3.select(d).attr("stroke-width",1).attr("dx", "-0.5" );
4450+
const dSelection = d3.select(d);
4451+
dSelection
4452+
.attr("stroke-width",self.options.refLineWidth)
4453+
.attr("dx", -0.5*self.options.refLineWidth );
4454+
// Handle extension line cleanup for this line
4455+
if( self.options.refLineVerbosity >= 1 ) {
4456+
const dLinedata = d.__data__;
4457+
4458+
if( dLinedata.major && self.options.refLineVerbosity >= 2 ) {
4459+
// For major lines with verbosity >= 2, reset the existing extension line
4460+
dSelection.select("line.major-extension")
4461+
.attr("stroke-width", self.options.refLineWidth)
4462+
.style("opacity", 0.5);
4463+
} else {
4464+
// For non-major lines or major lines with verbosity == 1, remove the temporary extension line
4465+
dSelection.select("line.temp-extension").remove();
4466+
}
4467+
}
4468+
// Remove hover indicator circle
4469+
dSelection.select("circle.ref-hover-indicator").remove();
44164470
d.__data__.mousedover = null;
44174471
}
44184472

@@ -4426,7 +4480,27 @@ SpectrumChartD3.prototype.updateMouseCoordText = function() {
44264480

44274481
if( nearestpx > 10 ) {
44284482
if( self.mousedOverRefLine ){
4429-
d3.select(self.mousedOverRefLine).attr("stroke-width",1).attr("dx", "-0.5" );
4483+
const prevLineSelection = d3.select(self.mousedOverRefLine);
4484+
prevLineSelection
4485+
.select("line")
4486+
.attr("dx", -0.5*self.options.refLineWidth )
4487+
.attr("stroke-width",self.options.refLineWidth);
4488+
// Handle extension line cleanup for previously hovered line
4489+
if( self.options.refLineVerbosity >= 1 ) {
4490+
const prevLinedata = self.mousedOverRefLine.__data__;
4491+
4492+
if( prevLinedata.major && self.options.refLineVerbosity >= 2 ) {
4493+
// For major lines with verbosity >= 2, reset the existing extension line
4494+
prevLineSelection.select("line.major-extension")
4495+
.attr("stroke-width", self.options.refLineWidth)
4496+
.style("opacity", 0.5);
4497+
} else {
4498+
// For non-major lines or major lines with verbosity == 1, remove the temporary extension line
4499+
prevLineSelection.select("line.temp-extension").remove();
4500+
}
4501+
}
4502+
// Remove hover indicator circle
4503+
prevLineSelection.select("circle.ref-hover-indicator").remove();
44304504
self.mousedOverRefLine.__data__.mousedover = null;
44314505
}
44324506
self.mousedOverRefLine = null;
@@ -4438,7 +4512,27 @@ SpectrumChartD3.prototype.updateMouseCoordText = function() {
44384512
return;
44394513

44404514
if( self.mousedOverRefLine ){
4441-
d3.select(self.mousedOverRefLine).attr("stroke-width",1).attr("dx", "-0.5" );
4515+
const prevLineSelection = d3.select(self.mousedOverRefLine);
4516+
prevLineSelection
4517+
.select("line")
4518+
.attr("dx", -0.5*self.options.refLineWidth )
4519+
.attr("stroke-width",self.options.refLineWidth);
4520+
// Handle extension line cleanup for previously hovered line
4521+
if( self.options.refLineVerbosity >= 1 ) {
4522+
const prevLinedata = self.mousedOverRefLine.__data__;
4523+
4524+
if( prevLinedata.major && self.options.refLineVerbosity >= 2 ) {
4525+
// For major lines with verbosity >= 2, reset the existing extension line
4526+
prevLineSelection.select("line.major-extension")
4527+
.attr("stroke-width", self.options.refLineWidth)
4528+
.style("opacity", 0.5);
4529+
} else {
4530+
// For non-major lines or major lines with verbosity == 1, remove the temporary extension line
4531+
prevLineSelection.select("line.temp-extension").remove();
4532+
}
4533+
}
4534+
// Remove hover indicator circle
4535+
prevLineSelection.select("circle.ref-hover-indicator").remove();
44424536
self.mousedOverRefLine.__data__.mousedover = null;
44434537
}
44444538

@@ -4478,6 +4572,11 @@ SpectrumChartD3.prototype.updateMouseCoordText = function() {
44784572
}
44794573

44804574
self.refLineInfo.style("display", null).attr("transform", "translate("+linepx+",0)" );
4575+
4576+
// Add circle to the hovered reference line
4577+
const lineSelection = d3.select(nearestline);
4578+
const nearLineEl = lineSelection.select("line");
4579+
44814580
var svgtxt = self.refLineInfoTxt.select("text")
44824581
.attr("dy", "1em")
44834582
.attr("fill", linedata.parent.color);
@@ -4498,10 +4597,43 @@ SpectrumChartD3.prototype.updateMouseCoordText = function() {
44984597
self.refLineInfoTxt.attr("transform", tx );
44994598
}
45004599

4501-
d3.select(nearestline)
4600+
nearLineEl
45024601
.attr("stroke-width",self.options.refLineWidthHover)
4503-
.select("line")
4504-
.attr("dx", "-1" );
4602+
.attr("dx", -0.5*self.options.refLineWidthHover );
4603+
4604+
// Handle extension line for hovered reference line (only if refLineVerbosity >= 1)
4605+
if( self.options.refLineVerbosity >= 1 ) {
4606+
const hoveredLinedata = nearestline.__data__;
4607+
const nearestlineSelection = d3.select(nearestline);
4608+
4609+
if( hoveredLinedata.major && self.options.refLineVerbosity >= 2 ) {
4610+
// For major lines with verbosity >= 2, just modify the existing extension line
4611+
nearestlineSelection.select("line.major-extension")
4612+
.attr("stroke-width", self.options.refLineWidthHover)
4613+
.style("opacity", 1.0);
4614+
} else {
4615+
// For non-major lines or major lines with verbosity == 1, add a temporary extension line
4616+
const y2Lin = function(d){ return Math.min(h - (h-m)*d.h/d.parent.maxVisibleAmp,h-2); };
4617+
nearestlineSelection.append("line")
4618+
.attr("class", "temp-extension")
4619+
.style("stroke-dasharray", "2,2")
4620+
.attr("stroke", hoveredLinedata.color ? hoveredLinedata.color : hoveredLinedata.parent.color)
4621+
.attr("stroke-width", self.options.refLineWidthHover)
4622+
.attr("y1", y2Lin(hoveredLinedata))
4623+
.attr("y2", self.options.refLineTopPad)
4624+
.attr("x1", 0)
4625+
.attr("x2", 0);
4626+
}
4627+
}
4628+
4629+
lineSelection.select("circle.ref-hover-indicator").remove(); // Remove any existing circle
4630+
const circleY = self.options.refLineVerbosity >= 1 ? nearLineEl.attr("y2") : self.size.height;
4631+
lineSelection.append("circle")
4632+
.attr("class", "ref-hover-indicator")
4633+
.attr("cx", 0)
4634+
.attr("cy", circleY)
4635+
.attr("r", 2)
4636+
.style("fill", "red");
45054637
}
45064638

45074639
SpectrumChartD3.prototype.setShowMouseStats = function(d) {

0 commit comments

Comments
 (0)