Predefined Templates
Modes
FamilyTree JS can be displayed in "dark" or "light" modes by settong the mode option:
light modedark mode
Templates
FamilyTree JS arrives with 2 predefined templates. You can change the template by setting the template option:
template: "hugo"
You can get the source code of any of the templates and change it. For example to change the size of the node shape, you need to change the size definition of the template.
tommyFamilyTree.templates.tommy = Object.assign({}, FamilyTree.templates.base); FamilyTree.templates.tommy.defs = `<style> .{randId} .bft-edit-form-header, .{randId} .bft-img-button{ background-color: #aeaeae; } .{randId}.male .bft-edit-form-header, .{randId}.male .bft-img-button{ background-color: #039BE5; } .{randId}.male div.bft-img-button:hover{ background-color: #F57C00; } .{randId}.female .bft-edit-form-header, .{randId}.female .bft-img-button{ background-color: #F57C00; } .{randId}.female div.bft-img-button:hover{ background-color: #039BE5; } </style>`; FamilyTree.templates.tommy.field_0 = `<text ${FamilyTree.attr.width}="230" style="font-size: 18px;font-weight:bold;" fill="#ffffff" x="10" y="90" text-anchor="start">{val}</text>`; FamilyTree.templates.tommy.field_1 = `<text ${FamilyTree.attr.width}="150" style="font-size: 14px;" fill="#ffffff" x="10" y="65" text-anchor="start">{val}</text>`; FamilyTree.templates.tommy.node = `<rect x="0" y="0" height="{h}" width="{w}" stroke-width="1" fill="#aeaeae" stroke="#aeaeae" rx="7" ry="7"></rect>`; FamilyTree.templates.tommy_male = Object.assign({}, FamilyTree.templates.tommy); FamilyTree.templates.tommy_male.node = `<rect x="0" y="0" height="{h}" width="{w}" stroke-width="1" fill="#039BE5" stroke="#aeaeae" rx="7" ry="7"></rect>`; FamilyTree.templates.tommy_female = Object.assign({}, FamilyTree.templates.tommy); FamilyTree.templates.tommy_female.node = `<rect x="0" y="0" height="{h}" width="{w}" stroke-width="1" fill="#F57C00" stroke="#aeaeae" rx="7" ry="7"></rect>`;
hugo
FamilyTree.templates.hugo = Object.assign({}, FamilyTree.templates.base); FamilyTree.templates.hugo.defs = `<clipPath id="hugo_img_0"><rect id="hugo_img_0_stroke" stroke-width="2" stroke="#fff" x="90" y="-5" rx="25" ry="25" width="70" height="70"></rect></clipPath> <linearGradient id="hugo_grad_female" x1="0%" y1="0%" x2="100%" y2="0%"> <stop offset="0%" style="stop-color:#FF8024;stop-opacity:1" /> <stop offset="100%" style="stop-color:#FF46A3;stop-opacity:1" /> </linearGradient> <linearGradient id="hugo_grad_male" x1="0%" y1="0%" x2="100%" y2="0%"> <stop offset="0%" style="stop-color:#00D3A5;stop-opacity:1" /> <stop offset="100%" style="stop-color:#00A7D4;stop-opacity:1" /> </linearGradient> <linearGradient id="hugo_grad" x1="0%" y1="0%" x2="100%" y2="0%"> <stop offset="0%" style="stop-color:#D0D0D0;stop-opacity:1" /> <stop offset="100%" style="stop-color:#909090;stop-opacity:1" /> </linearGradient> <g id="hugo_up"> <circle cx="12" cy="12" r="15" fill="transparent"></circle> ${FamilyTree.icon.ft(24,24,'#fff', 0, 0)} </g> <g id="hugo_node_menu" style="cursor:pointer;"> <rect x="0" y="0" fill="transparent" width="22" height="22"></rect> <circle cx="11" cy="4" r="2" fill="#ffffff"></circle><circle cx="11" cy="11" r="2" fill="#ffffff"></circle> <circle cx="11" cy="18" r="2" fill="#ffffff"></circle> </g> <style> .{randId} .bft-edit-form-header{ background: linear-gradient(90deg, #D0D0D0 0%, #909090 100%); } .{randId}.male .bft-edit-form-header{ background: linear-gradient(90deg, #00D3A5 0%, #00A7D4 100%); } .{randId}.female .bft-edit-form-header{ background: linear-gradient(90deg, #FF8024 0%, #FF46A3 100%); } .{randId} .bft-img-button{ background-color: #909090; } .{randId} .bft-img-button:hover{ background-color: #D0D0D0; } .{randId}.male .bft-img-button{ background-color: #00A7D4; } .{randId}.male .bft-img-button:hover{ background-color: #00D3A5; } .{randId}.female .bft-img-button{ background-color: #FF46A3; } .{randId}.female .bft-img-button:hover{ background-color: #FF8024; } </style>`; FamilyTree.templates.hugo.img_0 = '<use xlink:href="#hugo_img_0_stroke" /> <image preserveAspectRatio="xMidYMid slice" clip-path="url(#hugo_img_0)" xlink:href="{val}" x="90" y="-5" width="70" height="70"></image>'; FamilyTree.templates.hugo.field_0 = '<text ' + FamilyTree.attr.width + ' ="230" style="font-size: 18px;font-weight:bold;" fill="#ffffff" x="125" y="85" text-anchor="middle">{val}</text>'; FamilyTree.templates.hugo.field_1 = '<text ' + FamilyTree.attr.width + ' ="230" style="font-size: 14px;" fill="#ffffff" x="125" y="105" text-anchor="middle">{val}</text>'; FamilyTree.templates.hugo.node = '<rect x="0" y="0" height="{h}" width="{w}" stroke-width="1" fill=url(#hugo_grad) stroke="#aeaeae" rx="7" ry="7"></rect>'; FamilyTree.templates.hugo_male = Object.assign({}, FamilyTree.templates.hugo); FamilyTree.templates.hugo_male.node = '<rect x="0" y="0" height="{h}" width="{w}" stroke-width="1" fill=url(#hugo_grad_male) stroke="#aeaeae" rx="7" ry="7"></rect>'; FamilyTree.templates.hugo_female = Object.assign({}, FamilyTree.templates.hugo); FamilyTree.templates.hugo_female.node = '<rect x="0" y="0" height="{h}" width="{w}" stroke-width="1" fill=url(#hugo_grad_female) stroke="#aeaeae" rx="7" ry="7"></rect>'; FamilyTree.templates.hugo.up = '<use x="200" y="10" xlink:href="#hugo_up" />'; FamilyTree.templates.hugo.nodeMenuButton = `<use x="225" y="10" ${FamilyTree.attr.control_node_menu_id}="{id}" xlink:href="#hugo_node_menu" />`;
john
FamilyTree.templates.john = Object.assign({}, FamilyTree.templates.base); FamilyTree.templates.john.defs = `<style> .{randId} .bft-edit-form-header, .{randId} .bft-img-button{ background-color: #aeaeae; } .{randId}.male .bft-edit-form-header, .{randId}.male .bft-img-button{ background-color: #039BE5; } .{randId}.male div.bft-img-button:hover{ background-color: #F57C00; } .{randId}.female .bft-edit-form-header, .{randId}.female .bft-img-button{ background-color: #F57C00; } .{randId}.female div.bft-img-button:hover{ background-color: #039BE5; } </style> <clipPath id="john_img_0"><rect x="6" y="6" rx="54" ry="54" width="108" height="108"></rect></clipPath> ${FamilyTree.gradientCircleForDefs('circle', '#aeaeae', 60, 5)} ${FamilyTree.gradientCircleForDefs('male_circle', '#039BE5', 60, 5)} ${FamilyTree.gradientCircleForDefs('female_circle', '#F57C00', 60, 5)}`; FamilyTree.templates.john.field_0 = '<text ' + FamilyTree.attr.width + ' ="230" style="font-size: 16px;font-weight:bold;" fill="#aeaeae" x="60" y="135" text-anchor="middle">{val}</text>'; FamilyTree.templates.john.field_1 = '<text ' + FamilyTree.attr.width + ' ="150" style="font-size: 13px;" fill="#aeaeae" x="60" y="150" text-anchor="middle">{val}</text>'; FamilyTree.templates.john.node = '<use x="0" y="0" xlink:href="#circle" />'; FamilyTree.templates.john.img_0 = '<image preserveAspectRatio="xMidYMid slice" clip-path="url(#john_img_0)" xlink:href="{val}" x="6" y="6" width="108" height="108"></image>'; FamilyTree.templates.john.ripple = { radius: 60, color: "#e6e6e6", rect: null }; FamilyTree.templates.john.size = [120, 120] FamilyTree.templates.john_male = Object.assign({}, FamilyTree.templates.john); FamilyTree.templates.john_male.node += '<use x="0" y="0" xlink:href="#male_circle" />'; FamilyTree.templates.john_male.ripple = { radius: 60, color: "#039BE5", rect: null }; FamilyTree.templates.john_female = Object.assign({}, FamilyTree.templates.john); FamilyTree.templates.john_female.node += '<use x="0" y="0" xlink:href="#female_circle" />'; FamilyTree.templates.john_female.ripple = { radius: 60, color: "#F57C00", rect: null }; FamilyTree.templates.john.nodeMenuButton = `<use ${FamilyTree.attr.control_node_menu_id}="{id}" x="90" y="50" xlink:href="#base_node_menu" />`;
All templates are inherited form the base template. Here are defined all the other properties.
FamilyTree.templates.base = { defs: `<g transform="matrix(1,0,0,1,0,0)" id="dot"><circle class="ba-fill" cx="0" cy="0" r="5" stroke="#aeaeae" stroke-width="1"></circle></g> <g id="base_node_menu" style="cursor:pointer;"> <rect x="0" y="0" fill="transparent" width="22" height="22"></rect> <circle cx="4" cy="11" r="2" fill="#aeaeae"></circle> <circle cx="11" cy="11" r="2" fill="#aeaeae"></circle> <circle cx="18" cy="11" r="2" fill="#aeaeae"></circle> </g> <g style="cursor: pointer;" id="base_tree_menu"> <rect x="0" y="0" width="25" height="25" fill="transparent"></rect> ${FamilyTree.icon.addUser(25, 25, '#fff', 0, 0)} </g> <g style="cursor: pointer;" id="base_tree_menu_close"> <circle cx="12.5" cy="12.5" r="12" fill="#F57C00"></circle> ${FamilyTree.icon.close(25, 25, '#fff', 0, 0)} </g> <g id="base_up"> <circle cx="15" cy="15" r="15" fill="#fff" stroke="#aeaeae" stroke-width="1"></circle> ${FamilyTree.icon.ft(20,20,'#aeaeae', 5, 5)} </g> <clipPath id="base_img_0"> <rect id="base_img_0_stroke" stroke-width="3" stroke="#fff" x="170" y="-5" rx="25" ry="25" width="70" height="70"></rect> </clipPath>`, size: [250, 120], linkAdjuster: { fromX: 0, fromY: 0, toX: 0, toY: 0 }, ripple: { radius: 0, color: "#e6e6e6", rect: null }, expandCollapseSize: 0, svg: '<svg class="{randId} {template} {mode}" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" style="display:block;" width="{w}" height="{h}" viewBox="{viewBox}">{content}</svg>', link: '<path stroke-linejoin="round" stroke="#aeaeae" stroke-width="1px" fill="none" d="{rounded}" />', assistanseLink: '<path stroke-linejoin="round" stroke="#aeaeae" stroke-width="2px" fill="none" d="M{xa},{ya} {xb},{yb} {xc},{yc} {xd},{yd} L{xe},{ye}" />', pointer: '<g data-pointer="pointer" transform="matrix(0,0,0,0,100,100)"> <radialGradient id="pointerGradient"><stop stop-color="#ffffff" offset="0" /><stop stop-color="#C1C1C1" offset="1" /></radialGradient> <circle cx="16" cy="16" r="16" stroke-width="1" stroke="#acacac" fill="url(#pointerGradient)"></circle> </g>', node: '<rect x="0" y="0" height="{h}" width="{w}" stroke-width="1" stroke="#aeaeae" rx="7" ry="7"></rect>', menuButton: '<div style="position:absolute;right:{p}px;top:{p}px; width:40px;height:50px;cursor:pointer;" ' + FamilyTree.attr.control_export_menu + ' =""> <hr style="background-color: #7A7A7A; height: 3px; border: none;"> <hr style="background-color: #7A7A7A; height: 3px; border: none;"> <hr style="background-color: #7A7A7A; height: 3px; border: none;"> </div>', padding: [50, 20, 35, 20], nodeMenuButton: `<use ${FamilyTree.attr.control_node_menu_id}="{id}" x="220" y="95" xlink:href="#base_node_menu" />`, nodeTreeMenuButton: `<use ${'data-ctrl-n-t-menu-id'}="{id}" x="10" y="10" xlink:href="#base_tree_menu" />`, nodeTreeMenuCloseButton: `<use ${'data-ctrl-n-t-menu-c'}="" x="10" y="10" xlink:href="#base_tree_menu_close" />`, up: '<use x="110" y="-10" xlink:href="#base_up" />', img_0: '<use xlink:href="#base_img_0_stroke" /> <image preserveAspectRatio="xMidYMid slice" clip-path="url(#base_img_0)" xlink:href="{val}" x="170" y="-5" width="70" height="70"></image>', link_field_0: '<text text-anchor="middle" fill="#aeaeae" ' + FamilyTree.attr.width + ' ="290" x="0" y="0" style="font-size:10px;">{val}</text>'
We have also predefined templates for adding nodes using the NodeTreeMenu:
mother
FamilyTree.templates.mother = Object.assign({}, FamilyTree.templates.base); FamilyTree.templates.mother.up = ''; FamilyTree.templates.mother.node = '<rect x="0" y="0" height="{h}" width="{w}" style="fill:transparent;" stroke-width="1" stroke="#F57C00" rx="5" ry="5"></rect>' + '<text style="font-size: 18px;" fill="#F57C00" x="240" y="30" text-anchor="end">Add mother</text>' + FamilyTree.icon.mother(70, 70, '#F57C00', 10, 40);
father
FamilyTree.templates.father = Object.assign({}, FamilyTree.templates.mother); FamilyTree.templates.father.node = '<rect x="0" y="0" height="{h}" width="{w}" style="fill:transparent;height:{h}; width:{w};stroke-width:1;stroke:#039BE5;rx:5;ry:5;"></rect>' + '<text style="font-size: 18px;" fill="#039BE5" x="240" y="30" text-anchor="end">Add father</text>' + FamilyTree.icon.father(70, 70, '#039BE5', 10, 40);
partner
FamilyTree.templates.partner = Object.assign({}, FamilyTree.templates.mother); FamilyTree.templates.partner.node = '<rect x="0" y="0" height="{h}" width="{w}" style="fill:transparent;height:{h}; width:{w};stroke-width:1;stroke:#aeaeae;rx:5;ry:5;"></rect>' + '<text style="font-size: 18px;" fill="#aeaeae" x="240" y="30" text-anchor="end">Add partner</text>';
son
FamilyTree.templates.son = Object.assign({}, FamilyTree.templates.mother); FamilyTree.templates.son.node = '<rect x="0" y="0" height="{h}" width="{w}" style="fill:transparent;height:{h}; width:{w};stroke-width:1;stroke:#039BE5;rx:5;ry:5;"></rect>' + '<text style="font-size: 18px;" fill="#039BE5" x="240" y="30" text-anchor="end">Add son</text>' + FamilyTree.icon.son(70, 70, '#039BE5', 10, 40);
daughter
FamilyTree.templates.daughter = Object.assign({}, FamilyTree.templates.mother); FamilyTree.templates.daughter.node = '<rect x="0" y="0" height="{h}" width="{w}" style="fill:transparent;height:{h}; width:{w};stroke-width:1;stroke:#F57C00;rx:5;ry:5;"></rect>' + '<text style="font-size: 18px;" fill="#F57C00" x="240" y="30" text-anchor="end">Add daughter</text>' + FamilyTree.icon.daughter(70, 70, '#F57C00', 10, 40);
husband
FamilyTree.templates.husband = Object.assign({}, FamilyTree.templates.mother); FamilyTree.templates.husband.node = '<rect x="0" y="0" height="{h}" width="{w}" style="fill:transparent;height:{h}; width:{w};stroke-width:1;stroke:#039BE5;rx:5;ry:5;"></rect>' + '<text style="font-size: 18px;" fill="#039BE5" x="240" y="30" text-anchor="end">Add husband</text>' + FamilyTree.icon.husband(70, 70, '#039BE5', 10, 40);
wife
FamilyTree.templates.wife = Object.assign({}, FamilyTree.templates.mother); FamilyTree.templates.wife.node = '<rect x="0" y="0" height="{h}" width="{w}" style="fill:transparent;height:{h}; width:{w};stroke-width:1;stroke:#F57C00;rx:5;ry:5;"></rect>' + '<text style="font-size: 18px;" fill="#F57C00" x="240" y="30" text-anchor="end">Add wife</text>' + FamilyTree.icon.wife(70, 70, '#F57C00', 10, 40);
pet
FamilyTree.templates.pet = Object.assign({}, FamilyTree.templates.mother); FamilyTree.templates.pet.node = '<rect x="0" y="0" style="fill:transparent;height:{h}; width:{w};stroke-width:1;stroke:#F57C00;rx:5;ry:5;"></rect>' + '<text style="font-size: 18px;" fill="#F57C00" x="240" y="30" text-anchor="end">Add pet</text>' + FamilyTree.icon.teddy(70, 70, '#F57C00', 10, 40);