xref: /webtrees/resources/views/modules/pedigree-chart/chart.phtml (revision 8136679edbff8170fb92bd6e8dd8df8eb645bb1a)
1<?php use Fisharebest\Webtrees\Functions\FunctionsPrint; ?>
2<?php use Fisharebest\Webtrees\I18N; ?>
3<?php use Fisharebest\Webtrees\Module\ModuleThemeInterface; ?>
4
5<div id="pedigree-page">
6    <div id="pedigree_chart" class="layout<?= e($orientation) ?>">
7        <?php foreach ($nodes as $i => $node) : ?>
8            <div id="sosa_<?= ($i + 1) ?>" class="shadow d-flex align-items-center<?= e($flex_direction) ?>" style="<?= e($posn) ?>:<?= e($node['x']) ?>px; top:<?= e($node['y']) ?>px; position:absolute;">
9                <?php if ($orientation === $oldest_at_top) : ?>
10                    <?php if ($i >= $last_gen_start) : ?>
11                        <?= $node['previous_gen'] ?>
12                    <?php endif ?>
13                <?php else : ?>
14                    <?php if ($i === 0) : ?>
15                        <?= $child_menu ?>
16                    <?php endif ?>
17                <?php endif ?>
18
19                <?= FunctionsPrint::printPedigreePerson($nodes[$i]['indi']) ?>
20
21                <?php if ($orientation === $oldest_at_top) : ?>
22                    <?php if ($i === 0) : ?>
23                        <?= $child_menu ?>
24                    <?php endif ?>
25                <?php else : ?>
26                    <?php if ($i >= $last_gen_start) : ?>
27                        <?= $node['previous_gen'] ?>
28                    <?php endif ?>
29                <?php endif ?>
30            </div>
31        <?php endforeach ?>
32        <canvas id="pedigree_canvas" width="<?= e($canvas_width) ?>" height="<?= e($canvas_height) ?>">
33        </canvas>
34    </div>
35</div>
36
37<script>
38  (function() {
39    $("#childarrow").on("click", ".menuselect", function(e) {
40      e.preventDefault();
41      $("#childbox-pedigree").slideToggle("fast");
42    });
43
44    $("#pedigree_chart")
45      .width(<?= json_encode($canvas_width) ?>)
46  .height(<?= json_encode($canvas_height) ?>);
47
48    // Set variables
49    var p0, p1, p2,  // Holds the ids of the boxes used in the join calculations
50        canvas       = $("#pedigree_canvas"),
51        ctx          = canvas[0].getContext("2d"),
52        nodes        = $(".shadow").length,
53        gen1Start    = Math.ceil(nodes / 2),
54        boxWidth     = $(".person_box_template").first().outerWidth(),
55        boxHeight    = $(".person_box_template").first().outerHeight(),
56        useOffset    = true,
57        extraOffsetX = Math.floor(boxWidth / 15), // set offsets to be sensible fractions of the box size
58        extraOffsetY = Math.floor(boxHeight / 10),
59        addOffset;
60
61    // Draw joining lines on the <canvas>
62    function drawLines(context, x1, y1, x2, y2) {
63      x1 = Math.floor(x1);
64      y1 = Math.floor(y1);
65      x2 = Math.floor(x2);
66      y2 = Math.floor(y2);
67      if (<?= json_encode($orientation < $oldest_at_top) ?>) {
68        context.moveTo(x1, y1);
69        context.lineTo(x2, y1);
70        context.lineTo(x2, y2);
71        context.lineTo(x1, y2);
72      } else {
73        context.moveTo(x1, y1);
74        context.lineTo(x1, y2);
75        context.lineTo(x2, y2);
76        context.lineTo(x2, y1);
77      }
78    }
79
80    //Plot the lines
81    switch (<?= json_encode($orientation) ?>) {
82      case <?= json_encode($portrait) ?>:
83        useOffset = false;
84      // Drop through
85      case <?= json_encode($landscape) ?>:
86        for (var i = 2; i < nodes; i+=2) {
87          p0 = $("#sosa_" + i);
88          p1 = $("#sosa_" + (i+1));
89          // change line y position if within 10% of box top/bottom
90          addOffset = boxHeight / (p1.position().top - p0.position().top) > 0.9 ? extraOffsetY: 0;
91          if (<?= json_encode(I18N::direction() === 'rtl') ?>) {
92            drawLines(
93              ctx,
94              p0.position().left + p0.width(),
95              p0.position().top + (boxHeight / 2) + addOffset,
96              p0.position().left + p0.width() + extraOffsetX,
97              p1.position().top + (boxHeight / 2) - addOffset
98            );
99          } else {
100            drawLines(
101              ctx,
102              p0.position().left,
103              p0.position().top + (boxHeight / 2) + addOffset,
104              p0.position().left - extraOffsetX,
105              p1.position().top + (boxHeight / 2) - addOffset
106            );
107          }
108        }
109        break;
110      case <?= json_encode($oldest_at_top) ?>:
111        useOffset = false;
112      // Drop through
113      case <?= json_encode($oldest_at_bottom) ?>:
114        for (var i = 1; i < gen1Start; i++) {
115          p0 = $("#sosa_" + i);
116          p1 = $("#sosa_" + (i*2));
117          p2 = $("#sosa_" + (i*2+1));
118          addOffset = i*2 >= gen1Start ? extraOffsetX : 0;
119          var templateHeight = p0.children(".person_box_template").outerHeight(),
120              // bHeight taks account of offset when root person has a menu icon
121              bHeight = useOffset ? (p0.outerHeight() - templateHeight) + (templateHeight / 2) : templateHeight / 2;
122          drawLines(
123            ctx,
124            p1.position().left + (boxWidth / 2) + addOffset,
125            p1.position().top + boxHeight,
126            p2.position().left + (boxWidth / 2) - addOffset,
127            p0.position().top + bHeight
128          );
129        }
130        break;
131    }
132
133    // Set line styles & draw them
134    ctx.strokeStyle   = canvas.css("color");
135    ctx.lineWidth     = <?= json_encode(app()->make(ModuleThemeInterface::class)->parameter('line-width')) ?>;
136    ctx.shadowColor   = <?= json_encode(app()->make(ModuleThemeInterface::class)->parameter('shadow-color')) ?>;
137    ctx.shadowBlur    = <?= json_encode(app()->make(ModuleThemeInterface::class)->parameter('shadow-blur')) ?>;
138    ctx.shadowOffsetX = <?= json_encode(app()->make(ModuleThemeInterface::class)->parameter('shadow-offset-x')) ?>;
139    ctx.shadowOffsetY = <?= json_encode(app()->make(ModuleThemeInterface::class)->parameter('shadow-offset-y')) ?>;
140    ctx.stroke();
141  })();
142</script>
143