gene.ts 1.95 KB
Newer Older
Remi  PLANEL's avatar
Remi PLANEL committed
1
import { select, Selection } from "d3-selection"
Remi  PLANEL's avatar
Remi PLANEL committed
2
3
import { ScaleLinear } from "d3-scale";

Remi  PLANEL's avatar
Remi PLANEL committed
4
import { arrowShape } from "./gene-shapes";
5
import linearGene from "../../layout/linear-gene";
6
7
import { of } from "rxjs";
import { mergeMap } from "rxjs/operators";
8

9
import { GeneData, PositionedGeneData } from "../../types";
10

Remi  PLANEL's avatar
Remi PLANEL committed
11
12

export default function () {
13
  function gene(
Remi  PLANEL's avatar
Remi PLANEL committed
14
    _selection: Selection<SVGElement, Array<GeneData>, SVGElement, any>,
15
16
17
    xScale: ScaleLinear<number, number>,
    geneHeight: number = 30,
    yPosition: number = 60
18
  ) {
Remi  PLANEL's avatar
Remi PLANEL committed
19
20
    _selection.each(function (_data: Array<GeneData>) {
      const container = select(this);
21
22
      const genes = container
        .selectAll<SVGGElement, PositionedGeneData>('.gene')
23
        .data(linearGene(_data, xScale, yPosition));
Remi  PLANEL's avatar
Remi PLANEL committed
24
25

      // ENTER
26
27
28
29
      const enterGenes = genes
        .enter()
        .append<SVGGElement>('g')
        .classed("gene", true);
30

Remi  PLANEL's avatar
Remi PLANEL committed
31
      enterGenes.append("path");
32

Remi  PLANEL's avatar
Remi PLANEL committed
33
34
35
36
37
38
      // EXIT
      genes.exit().remove()

      // UPDATE
      const updateGenes = genes.merge(enterGenes);

39
      // set the positions
40
      updateGenes.attr("transform", d => "translate(" + d.position.x + "," + d.position.y + ")");
41
      updateGenes
42
        .select<SVGPathElement>("path")
43
44
45
46
47
        .style("fill", d => d.fill || null)
        .style("fill-opacity", 0.85)
        .style("stroke", d => d.stroke || null)
        .style("stroke-width", '1px')
        .style("stroke-opacity", 0.8)
48
49
        .attr(
          "transform",
50
          ({ strand, position: { width } }) => (strand === "-")
Remi  PLANEL's avatar
Remi PLANEL committed
51
            ? "translate(0," + (geneHeight + 5) + ") translate(" + width + "," + geneHeight + ") rotate(180)"
52
53
54
            : null
        )
        .attr("d", d => arrowShape(d, geneHeight))
Remi  PLANEL's avatar
Remi PLANEL committed
55
56
57
58
59
60
61
        .on("click", d => {
          if (d.eventHandler) {
            return of(d)
              .pipe(mergeMap(d => of<[number, number]>([d.begin, d.end])))
              .subscribe(d.eventHandler.click);
          }
        });
Remi  PLANEL's avatar
Remi PLANEL committed
62
63
64
65
66
67
68
69
    })
  }
  return gene;

}