Skip to content

Commit

Permalink
add (limited) images to relship chart (#451)
Browse files Browse the repository at this point in the history
* add (limited) imaged to relship chart

* Prevent names from overflowing in presence of images

---------

Co-authored-by: David Straub <straub@protonmail.com>
  • Loading branch information
geostag and DavidMStraub authored Jun 30, 2024
1 parent 21452d2 commit 54c9304
Show file tree
Hide file tree
Showing 2 changed files with 69 additions and 10 deletions.
77 changes: 68 additions & 9 deletions src/charts/RelationshipChart.js
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,7 @@ class Relgraph {
this.persons[me] = {
handle: me,
profile: p.profile,
data: p,
}
if (p.gramps_id === this.rootPersonGrampsId) {
this.rootPerson = this.persons[me]
Expand Down Expand Up @@ -317,11 +318,26 @@ function clicked(event, d) {
})
)
}
function remasterChart(divhidden, targetsvg, graph, boxWidth, boxHeight) {
function remasterChart(
divhidden,
targetsvg,
graph,
boxWidth,
boxHeight,
imgPadding,
getImageUrl,
maxImages
) {
const gvchartx = divhidden.select('svg')
const nodedata = []
const imgRadius = (boxHeight - imgPadding * 2) / 2
const textPadding = d =>
d.imageUrl ? 2 * imgRadius + 2 * imgPadding : 2 * imgPadding
const boxWidthTotal = d =>
d.imageUrl ? boxWidth - 2 * imgRadius - 10 : boxWidth
gvchartx.selectAll('title').remove()
// based on graphviz created nodes build array containing node data to be bound to d3 nodes
let imageCount = 0
gvchartx.selectAll('.node').each(function () {

Check warning on line 341 in src/charts/RelationshipChart.js

View workflow job for this annotation

GitHub Actions / test

Unexpected unnamed function
const e = select(this)
const textElement = e.select('text')
Expand All @@ -331,11 +347,16 @@ function remasterChart(divhidden, targetsvg, graph, boxWidth, boxHeight) {
const found = c.match(/(?<handletype>family|person)_(?<handle>\S+)/)
if (found.groups.handletype === 'person') {
const d = graph.known(found.groups.handle)
const imageUrl = getImageUrl(d)
if (imageUrl) {
imageCount += 1
}
nodedata.push({
nodetype: d.profile.fake ? 'fake' : 'person',
xCoord: x - boxWidth / 2 + 4,
yCoord: y - boxHeight / 2,
profile: d.profile,
imageUrl: imageCount > maxImages ? '' : imageUrl,
handle: found.groups.handle,
})
} else if (found.groups.handletype === 'family') {
Expand Down Expand Up @@ -392,9 +413,11 @@ function remasterChart(divhidden, targetsvg, graph, boxWidth, boxHeight) {
.attr('font-weight', '500')
.attr('fill', 'rgba(0, 0, 0, 0.9)')
.attr('paint-order', 'stroke')
.attr('x', 20)
.attr('text-overflow', 'ellipsis')
.attr('overflow', 'hidden')
.attr('x', d => textPadding(d))
.attr('y', 25)
.text(d => clipString(`${d.profile.name_surname},`, boxWidth))
.text(d => clipString(`${d.profile.name_surname},`, boxWidthTotal(d)))

nodes
.filter(d => d.profile?.name_given && d.nodetype === 'person')
Expand All @@ -405,9 +428,9 @@ function remasterChart(divhidden, targetsvg, graph, boxWidth, boxHeight) {
.attr('paint-order', 'stroke')
.attr('text-overflow', 'ellipsis')
.attr('overflow', 'hidden')
.attr('x', 20)
.attr('x', d => textPadding(d))
.attr('y', 25 + 17)
.text(d => clipString(d.profile.name_given, boxWidth))
.text(d => clipString(d.profile.name_given, boxWidthTotal(d)))

nodes
.filter(d => d.profile?.birth?.date && d.nodetype === 'person')
Expand All @@ -416,9 +439,9 @@ function remasterChart(divhidden, targetsvg, graph, boxWidth, boxHeight) {
.attr('font-weight', '350')
.attr('fill', 'rgba(0, 0, 0, 0.9)')
.attr('paint-order', 'stroke')
.attr('x', 20)
.attr('x', d => textPadding(d))
.attr('y', 25 + 17 * 2)
.text(d => clipString(`*${d.profile.birth.date}`, boxWidth))
.text(d => clipString(`*${d.profile.birth.date}`, boxWidthTotal(d)))

nodes
.filter(d => d.profile?.death?.date && d.nodetype === 'person')
Expand All @@ -427,9 +450,39 @@ function remasterChart(divhidden, targetsvg, graph, boxWidth, boxHeight) {
.attr('font-weight', '350')
.attr('fill', 'rgba(0, 0, 0, 0.9)')
.attr('paint-order', 'stroke')
.attr('x', 20)
.attr('x', d => textPadding(d))
.attr('y', 25 + 17 * 3)
.text(d => clipString(`†${d.profile.death.date}`, boxWidth))
.text(d => clipString(`†${d.profile.death.date}`, boxWidthTotal(d)))

// images
nodes
.filter(d => d.imageUrl)
.append('circle')
.attr('r', imgRadius)
.attr('cy', imgRadius + imgPadding)
.attr('cx', imgRadius + imgPadding)
.attr('fill', d => `url(#imgpattern-${d.handle})`)

const defs = targetsvg.append('defs')
const imgPattern = defs
.selectAll('.imgpattern')
.data(nodedata)
.enter()
.filter(d => d.nodetype === 'person' && d.imageUrl)
.append('pattern')
.attr('id', d => `imgpattern-${d.handle}`)
.attr('height', 1)
.attr('width', 1)
.attr('x', '0')
.attr('y', '0')

imgPattern
.append('image')
.attr('x', 0)
.attr('y', 0)
.attr('height', 70)
.attr('width', 70)
.attr('xlink:href', d => d.imageUrl)

nodes
.filter(d => d.type === 'Married' && d.nodetype === 'family')
Expand Down Expand Up @@ -470,7 +523,10 @@ export function RelationshipChart(
bboxHeight = 150,
boxWidth = 190,
boxHeight = 90,
imgPadding = 10,
getImageUrl = null,
grampsId = 0,
maxImages = 50,
// orientation = 'LTR',
}
) {
Expand Down Expand Up @@ -498,6 +554,9 @@ export function RelationshipChart(
graph,
boxWidth,
boxHeight,
imgPadding,
getImageUrl,
maxImages,
grampsId
)
svg.attr('viewBox', [
Expand Down
2 changes: 1 addition & 1 deletion src/components/GrampsjsRelationshipChart.js
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ class GrampsjsRelationshipChart extends GrampsjsChartBase {
${RelationshipChart(this.data, {
nAnc: this.nAnc,
grampsId: this.grampsId,
getImageUrl: d => getImageUrl(d?.data?.person || {}, 200),
getImageUrl: d => getImageUrl(d?.data || {}, 200),
gapX: this.gapX,
bboxWidth: this.containerWidth,
bboxHeight: this.containerHeight,
Expand Down

0 comments on commit 54c9304

Please sign in to comment.