UNPKG

@rcsb/rcsb-saguaro

Version:
114 lines (113 loc) 4.94 kB
import { select } from "d3-selection"; import { RcsbD3Constants } from "../RcsbD3Constants"; import { asyncScheduler } from "rxjs"; export class RcsbD3FastSequenceManager { constructor() { this.textElements = select(RcsbD3Constants.EMPTY); this.MONOSPACE_BEGIN = 2.5; this.FONT_FAMILY = "Monaco, Menlo, Lucida, monospace"; } plot(config) { var _a; const xScale = config.xScale; const yScale = config.yScale; this.textElements = config.elements.select(RcsbD3Constants.TEXT); this.textElements .attr(RcsbD3Constants.X, (d) => { return this.textBegin(xScale, d); }) .attr(RcsbD3Constants.TEXT_LENGTH, (d) => { return this.textLength(xScale, d); }) .attr(RcsbD3Constants.Y, (_a = yScale(Math.floor(config.height * 0.5) + 4)) !== null && _a !== void 0 ? _a : 0) .attr(RcsbD3Constants.FONT_SIZE, "10") .attr(RcsbD3Constants.FONT_FAMILY, this.FONT_FAMILY) .attr(RcsbD3Constants.TEXT_ANCHOR, "start") .attr(RcsbD3Constants.FILL, (d) => { if (typeof d.color === "string") { return d.color; } else if (typeof config.color === "string") { return config.color; } else { console.warn("Config color noy found"); return "#CCCCCC"; } }) .text((d) => { return d.label || ""; }) .attr(RcsbD3Constants.FILL_OPACITY, () => { return RcsbD3FastSequenceManager.opacity(xScale, config.intervalRatio); }); addSequenceEvents(this.textElements, config); } static plotSequenceLine(config) { var _a, _b; RcsbD3FastSequenceManager.clearLine(config); config.trackG.append(RcsbD3Constants.LINE) .style(RcsbD3Constants.STROKE_WIDTH, 2) .style(RcsbD3Constants.STROKE, "#DDDDDD") .attr(RcsbD3Constants.STROKE_DASH, "2") .attr(RcsbD3Constants.X1, config.xScale.range()[0]) .attr(RcsbD3Constants.Y1, (_a = config.yScale(config.height * 0.5)) !== null && _a !== void 0 ? _a : 0) .attr(RcsbD3Constants.X2, config.xScale.range()[1]) .attr(RcsbD3Constants.Y2, (_b = config.yScale(config.height * 0.5)) !== null && _b !== void 0 ? _b : 0); const rect = config.trackG.append(RcsbD3Constants.RECT); rect.attr(RcsbD3Constants.ID, RcsbD3FastSequenceManager.RECT_ID) .attr(RcsbD3Constants.X, config.xScale.range()[0]) .attr(RcsbD3Constants.Y, config.yScale.range()[0]) .attr(RcsbD3Constants.WIDTH, config.xScale.range()[1] - config.xScale.range()[0]) .attr(RcsbD3Constants.HEIGHT, config.height) .attr(RcsbD3Constants.FILL_OPACITY, 0); addSequenceEvents(rect, config); } static clearLine(config) { config.trackG.select(RcsbD3Constants.LINE).remove(); config.trackG.select(`${RcsbD3Constants.RECT}#${RcsbD3FastSequenceManager.RECT_ID}`).remove(); } move(config) { asyncScheduler.schedule(() => { const xScale = config.xScale; this.textElements .attr(RcsbD3Constants.X, (d) => { return this.textBegin(xScale, d); }) .attr(RcsbD3Constants.TEXT_LENGTH, (d) => { return this.textLength(xScale, d); }) .attr(RcsbD3Constants.FILL_OPACITY, () => { return RcsbD3FastSequenceManager.opacity(xScale, config.intervalRatio); }); }); } static opacity(xScale, intervalRatio) { const r = (xScale.range()[1] - xScale.range()[0]) / (xScale.domain()[1] - xScale.domain()[0]); const o_min = 0.2; const a = intervalRatio[0]; const b = intervalRatio[1]; if (r < b) { return (1 - o_min) / (b - a) * (r - a) + o_min; } else { return 1; } } textLength(xScale, d) { //TODO Not cool but I did not found any other way. // It seems that svg > text > textLength attribute behaves slightly different in safari if (/^((?!chrome|android).)*safari/i.test(navigator.userAgent)) return xScale(d.begin + d.label.length) - xScale(d.begin); return xScale(d.begin + d.label.length - 1) - xScale(d.begin) + 2 * this.MONOSPACE_BEGIN; } textBegin(xScale, d) { return xScale(d.begin) - this.MONOSPACE_BEGIN; } } RcsbD3FastSequenceManager.RECT_ID = "line-rect"; function addSequenceEvents(element, config) { element.on(RcsbD3Constants.CLICK, event => config.mouseclick(event)); element.on(RcsbD3Constants.MOUSE_MOVE, event => config.mousemove(event)); element.on(RcsbD3Constants.MOUSE_OUT, event => config.mouseleave(event)); }