Created
February 1, 2024 10:03
-
-
Save leegee/3ea08703ebf4333ebe4a89500a37d0da to your computer and use it in GitHub Desktop.
Kabbalah tree after Luria
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<!-- still working on the paths, etc --> | |
<html> | |
<head> | |
<meta name="viewport" content="width=device-width, initial-scale=1"> | |
<meta http-equiv="X-UA-Compatible" content="IE=edge"> | |
<meta name="theme-color" content="#000000"> | |
<style> | |
html * { | |
box-sizing: border-box; | |
--clr-subtle-bg: #000; | |
--clr-bg: #222; | |
--clr-fg: whitesmoke; | |
--clr-fg-hilight: white; | |
--clr-border: #FFF5; | |
border-radius: 0.3em; | |
} | |
body { | |
background-color: black; | |
display: flex; | |
justify-content: center; | |
align-items: center; | |
height: 100vh; | |
width: 100vw; | |
margin: 0; | |
padding: 0; | |
overflow: visible; | |
border: 10pt solid var(--clr-subtle-bg); | |
} | |
svg { | |
z-index: 1; | |
border: none; | |
width: 100%; | |
height: 100%; | |
font-size: normal; | |
border: 1px dotted #FFF3; | |
} | |
svg * { | |
font-size: 1rem; | |
} | |
.sephira-group { | |
transition: transform 0.2s; | |
transform-box: fill-box; | |
display: block; | |
transform-origin: center center; | |
transition-delay: 0.15s; | |
} | |
.sephira-group:hover { | |
cursor: zoom-in; | |
transform: scale(1); | |
transition-delay: 0.1s; | |
} | |
.sephira-group:hover .bg { | |
fill: black; | |
} | |
.sephira-group.severity, | |
.sephira-group.mercy { | |
transform: scale(0.7); | |
} | |
.sephira-group.severity:hover, | |
.sephira-group.mercy:hover { | |
transform: scale(1); | |
} | |
.sephira-group .bg { | |
fill: transparent; | |
} | |
.sephira-group:hover .bg { | |
fill: black; | |
} | |
.sephira-group.einsof { | |
transform: translateY(-2rem); | |
} | |
.sephira-group.einsof foreignObject { | |
transform: translateY(-1rem); | |
} | |
.sephira-group.einsof .title { | |
font-size: 32pt; | |
opacity: 0.8; | |
} | |
.sephira-group.einsof .desc * { | |
font-size: 10pt !important; | |
padding: 0 !important; | |
margin: 0 !important; | |
} | |
.sephira-group.severity .order, | |
.sephira-group.mercy .order { | |
display: none; | |
} | |
.sephira-group.severity .title, | |
.sephira-group.mercy .title { | |
font-size: normal; | |
opacity: 0.7; | |
} | |
.sephira-group.severity .desc, | |
.sephira-group.mercy .desc { | |
transform: translateY(-0.2rem); | |
opacity: 0.4; | |
} | |
.sephira { | |
text-anchor: middle; | |
alignment-baseline: middle; | |
stroke: black; | |
stroke-width: 1px; | |
} | |
.order, | |
.title, | |
.desc { | |
text-anchor: middle; | |
alignment-baseline: middle; | |
fill: var(--clr-fg-hilight); | |
} | |
.desc { | |
fill: var(--clr-fg); | |
stroke: var(--clr-fg); | |
} | |
.order { | |
font-size: small; | |
transform: translateY(-1px); | |
fill: var(--clr-fg-hilight); | |
stroke: var(--clr-bg); | |
stroke-width: 0.5px; | |
opacity: 0.5; | |
} | |
:hover .order { | |
opacity: 1; | |
} | |
.title { | |
font-size: xx-large; | |
font-weight: bold; | |
stroke: black; | |
} | |
.foreignObjectRoot { | |
margin: 0; | |
padding: 0; | |
width: 100%; | |
height: 100%; | |
display: flex; | |
align-items: center; | |
font-family: Helvetica; | |
font-size: 10pt; | |
font-weight: lighter; | |
opacity: 70%; | |
color: var(--clr-fg); | |
flex-direction: column; | |
justify-content: flex-start; | |
} | |
.foreignObjectRoot p, | |
.foreignObjectRoot ul { | |
padding: 0; | |
margin: 0.4em 0 0.6em; | |
list-style: none; | |
text-align: center; | |
font-size: 50%; | |
} | |
.line-letter-path, | |
.text-path { | |
opacity: 33%; | |
transition: transform 0.2s; | |
transform-box: fill-box; | |
display: block; | |
transform-origin: center center; | |
text-anchor: middle; | |
alignment-baseline: middle; | |
} | |
.sephirot-outter-text-path { | |
stroke: none; | |
fill: var(--clr-fg); | |
opacity: 50%; | |
font-family: Helvetica; | |
font-size: x-small; | |
font-weight: lighter; | |
letter-spacing: -1px; | |
word-spacing: 0.7px; | |
transition: transform 0.2s; | |
transform-box: fill-box; | |
display: block; | |
transform-origin: center center; | |
text-anchor: middle; | |
alignment-baseline: before-edge; | |
} | |
.line-letter-path { | |
stroke-width: 1.3em; | |
} | |
.text-path { | |
fill: var(--clr-fg); | |
stroke: var(--clr-fg); | |
font-size: x-small; | |
} | |
.text-path-path:hover, | |
.line-letter-path:hover { | |
opacity: 1; | |
} | |
#pardes { | |
z-index: 1; | |
margin-right: 2em; | |
padding: 1em; | |
list-style: none; | |
font-size: 12pt; | |
background: var(--clr-subtle-bg); | |
opacity: 0.8; | |
transition: all 0.6s; | |
} | |
#pardes:hover { | |
opacity: 1; | |
} | |
#pardes div { | |
padding: 0.5rem; | |
margin: 0.5rem; | |
border: 1pt solid gray; | |
box-shadow: 0 0 4pt 4pt #6664; | |
opacity: 0.6; | |
transition: all 0.6s; | |
} | |
#pardes div:hover { | |
box-shadow: 0 0 4pt 4pt #6666; | |
opacity: 1; | |
transition: all 0.6s; | |
cursor: pointer; | |
} | |
/* Highlight only the pardes key selected on the body element */ | |
body.pardes-peshat #peshat, | |
body.pardes-remez #remez, | |
body.pardes-derash #derash, | |
body.pardes-sod #sod { | |
opacity: 0.9 !important; | |
} | |
#pardes dt { | |
letter-spacing: 200%; | |
font-variant: small-caps; | |
color: var(--clr-fg); | |
display: flex; | |
justify-content: space-between; | |
align-items: center; | |
} | |
#pardes dt [lang=en] { | |
font-weight: normal; | |
float: left; | |
} | |
#pardes dt [lang=he] { | |
font-weight: bold; | |
float: right; | |
font-size: 4vh; | |
} | |
#pardes dd { | |
color: var(--clr-fg); | |
font-weight: light; | |
letter-spacing: normal; | |
padding: 0; | |
margin: 0.3em 0 1em; | |
} | |
#detail { | |
z-index: 100; | |
position: fixed; | |
top: 0; | |
left: 0; | |
width: 95vw; | |
height: 95vh; | |
padding: 2.5vh 2.5vw; | |
margin: 2.5vh 2.5vw; | |
border: 1pt solid #FFF6; | |
background-color: black; | |
color: var(--clr-fg); | |
font-size: large; | |
display: flex; | |
align-items: center; | |
justify-content: center; | |
flex-direction: column; | |
display: none; | |
} | |
#detail * { | |
margin: 0; | |
padding: 0; | |
} | |
#detail.active { | |
display: flex; | |
} | |
#detail #Order { | |
font-size: 12pt; | |
width: 10em; | |
height: 2em; | |
display: flex; | |
align-items: center; | |
justify-content: center; | |
padding-bottom: 33pt; | |
border-bottom: 1px solid var(--clr-border); | |
position: relative; | |
top: -2em; | |
} | |
#detail #Hebrew { | |
font-size: 15vh; | |
margin-bottom: 0.3em; | |
} | |
#detail #Translit { | |
font-size: 5vh; | |
} | |
#detail #English { | |
font-size: 2.5vh; | |
font-style: italic; | |
opacity: 0.7; | |
} | |
#detail #Attr { | |
font-size: 200%; | |
margin: 2em 0; | |
} | |
#detail #Attr ul { | |
list-style-position: inside; | |
list-style-type: none; | |
display: flex; | |
flex-direction: row; | |
justify-content: center; | |
align-items: center; | |
width: 100%; | |
} | |
#detail #Attr li { | |
display: inline; | |
text-transform: capitalize; | |
} | |
#detail #Attr li:not(:first-child)::before { | |
content: "\2022"; | |
margin-left: 1em; | |
margin-right: 1em; | |
} | |
#detail #Letter { | |
font-size: 5vh; | |
} | |
#detail #LetterName { | |
opacity: 0.5; | |
font-size: 2.5vh; | |
font-style: italic; | |
} | |
#detail #close-detail { | |
font-size: 10pt; | |
font-family: Helvetica, sans-serif; | |
text-transform: capitalize; | |
margin-top: 66pt; | |
border-top: 1px solid var(--clr-border); | |
padding: 33pt; | |
cursor: pointer; | |
opacity: 0.5; | |
} | |
#detail #close-detail:before { | |
margin-right: 0.5em; | |
content: '◀'; | |
} | |
#detail #close-detail span { | |
padding: 1em; | |
display: inline-block; | |
} | |
#detail #close-detail:hover { | |
opacity: 1; | |
background-color: #FFF2; | |
border: 1px solid #FFF2; | |
} | |
/** For the pardesh: | |
* CSS classes for each element .pardes-peshat, .pardes-*. | |
* Dynamic CSS clasa applied to the body: .pardes-peshat, .pardes-*. | |
* CCS rule engaged when body.class='pardes.*' | |
*/ | |
body>.pardes-peshat, | |
body>.pardes-remez, | |
body>.pardes-deresh, | |
body>.pardes-sod { | |
display: none; | |
} | |
body.pardes-peshat .pardes-peshat, | |
body.pardes-remez .pardes-remez, | |
body.pardes-deresh .pardes-deresh, | |
body.pardes-sod .pardes-sod { | |
display: block; | |
} | |
</style> | |
</head> | |
<body> | |
<template id="detail-template"> | |
<p id="Order"></p> | |
<h2 id="Hebrew"></h2> | |
<p id="Translit"></p> | |
<p id="English"></p> | |
<p id="Attr"></p> | |
<p id="Letter"></p> | |
<p id="LetterName"></p> | |
<a id="close-detail">BACK TO THE TREE</a> | |
</template> | |
<svg xmlns="http://www.w3.org/2000/svg" width="100%" height="100%" viewBox="-250 -100 500 1000" id="svg"> | |
<defs> | |
<radialGradient id="gradient-Keter"> | |
<stop offset="30%" style="stop-color:white; stop-opacity:1" /> | |
<stop offset="100%" style="stop-color:whitesmoke; stop-opacity:1" /> | |
</radialGradient> | |
<radialGradient id="gradient-Chokhmah"> | |
<stop offset="30%" style="stop-color:hsl(40, 1%, 56%); stop-opacity:1" /> | |
<stop offset="100%" style="stop-color:hsl(40, 1%, 46%); stop-opacity:1" /> | |
</radialGradient> | |
<radialGradient id="gradient-Binah"> | |
<stop offset="30%" style="stop-color:black; stop-opacity:1" /> | |
<stop offset="100%" style="stop-color:#333; stop-opacity:1" /> | |
</radialGradient> | |
<radialGradient id="gradient-Chesed"> | |
<stop offset="30%" style="stop-color:hsl(209, 43%, 55%); stop-opacity:1" /> | |
<stop offset="100%" style="stop-color:hsl(209, 33%, 45%); stop-opacity:1" /> | |
</radialGradient> | |
<radialGradient id="gradient-Geburah"> | |
<stop offset="30%" style="stop-color:hsl(5, 57%, 59%); stop-opacity:1" /> | |
<stop offset="100%" style="stop-color:hsl(5, 47%, 49%); stop-opacity:1" /> | |
</radialGradient> | |
<radialGradient id="gradient-Tiferet"> | |
<stop offset="30%" style="stop-color:hsl(60, 100%, 50%); stop-opacity:1" /> | |
<stop offset="100%" style="stop-color:hsl(60, 100%, 40%); stop-opacity:1" /> | |
</radialGradient> | |
<radialGradient id="gradient-Netzach"> | |
<stop offset="30%" style="stop-color:hsl(124, 26%, 52%); stop-opacity:1" /> | |
<stop offset="100%" style="stop-color:hsl(124, 26%, 42%); stop-opacity:1" /> | |
</radialGradient> | |
<radialGradient id="gradient-Hod"> | |
<stop offset="30%" style="stop-color:hsl(33, 74%, 63%); stop-opacity:1" /> | |
<stop offset="100%" style="stop-color:hsl(33, 64%, 53%); stop-opacity:1" /> | |
</radialGradient> | |
<radialGradient id="gradient-Yesod"> | |
<stop offset="30%" style="stop-color:hsl(260, 28%, 59%); stop-opacity:1" /> | |
<stop offset="100%" style="stop-color:hsl(260, 28%, 49%); stop-opacity:1" /> | |
</radialGradient> | |
<radialGradient id="gradient-Malkhut"> | |
<stop offset="40%" style="stop-color:yellow; stop-opacity:1" /> | |
<stop offset="85%" style="stop-color:green; stop-opacity:1" /> | |
<stop offset="90%" style="stop-color:black; stop-opacity:1" /> | |
<stop offset="95%" style="stop-color:red; stop-opacity:1" /> | |
</radialGradient> | |
<filter id="drop-shadow"> | |
<feGaussianBlur in="SourceAlpha" stdDeviation="4" /> | |
<feOffset dx="0" dy="4" result="offsetblur" /> | |
<feFlood flood-color="rgba(0, 0, 0, 0.2)" /> | |
<feComposite in2="offsetblur" operator="in" /> | |
<feMerge> | |
<feMergeNode /> | |
<feMergeNode in="SourceGraphic" /> | |
</feMerge> | |
</filter> | |
</defs> | |
</svg> | |
<aside id="detail"></aside> | |
<aside> | |
<menu id="pardes" alt='פרד"ס'> | |
<div id="peshat"> | |
<dt><span lang="en">Peshat</span><span lang="he">פְּשָׁט</span></dt> | |
<dd>"surface" ("straight"); the literal, direct meaning.</dd> | |
</div> | |
<div id="remez"> | |
<dt><span lang="en">Remez</span><span lang="he">רֶמֶז</span></dt> | |
<dd>"hints" ("deep"); allegorically hidden or symbolic meaning.</dd> | |
</div> | |
<div id="derash"> | |
<dt><span lang="en">Derash</span><span lang="he">דְּרַשׁ</span></dt> | |
<dd>from Hebrew darash, "inquire" ("seek"); the comparative meaning, as given through | |
textual analysis of similar occurrences, aka Midrashic.</dd> | |
</div> | |
<div id="sod"> | |
<dt><span lang="en">Sod</span><span lang="he">סוֹד</span></dt> | |
<dd>"secret" ("mystery"); the esoteric/mystical meaning, | |
as given through inspiration or revelation. </dd> | |
</div> | |
</menu> | |
</aside> | |
<script> | |
const templateEl = document.getElementById( 'detail-template' ); | |
const detailEl = document.getElementById( 'detail' ); | |
const RADIUS = 36; | |
const RADIUS_SMALLER = 30; | |
const X_PAD = 100; | |
const Y_PAD = 100; | |
let __currentPardes; | |
function showDetail ( sephiraData, _e ) { | |
const clone = document.importNode( templateEl.content, true ); | |
for ( let attrName in sephiraData ) { | |
const el = clone.getElementById( attrName ); | |
if ( el ) { | |
if ( typeof sephiraData[ attrName ] === 'string' || typeof sephiraData[ attrName ] === 'number' ) { | |
el.textContent = sephiraData[ attrName ]; | |
} | |
else if ( sephiraData[ attrName ] instanceof Array ) { | |
el.innerHTML = '<ul>' + ( | |
sephiraData[ attrName ].map( _ => { return `<li>${ _ }</li>` } ).join( '' ) | |
) + '</ul>'; | |
} | |
} | |
} | |
document.body.addEventListener( 'keydown', ( e ) => escClosesDetail( e, detailEl ) ); | |
clone.querySelector( '#close-detail' ).addEventListener( 'click', () => { | |
closeDetail( detailEl ); | |
document.removeEventListener( 'keydown', ( e ) => escClosesDetail( e, detailEl ) ); | |
} ); | |
clone.querySelector( '#Hebrew' ).style.filter = 'url("#gradient-' + sephiraData.Translit + '")'; | |
closeDetail( detailEl ); | |
detailEl.appendChild( clone ); | |
detailEl.classList.add( 'active' ); | |
} | |
function escClosesDetail ( e, detailEl ) { | |
if ( e.key === 'Esc' || e.key === 'Escape' ) { | |
closeDetail( detailEl ); | |
} | |
} | |
function closeDetail ( detailEl ) { | |
detailEl.classList.remove( 'active' ); | |
detailEl.innerHTML = ''; | |
} | |
function foreignObject ( { id, xhtml, klass, x, y, width, height } ) { | |
const foreignObject = document.createElementNS( 'http://www.w3.org/2000/svg', 'foreignObject' ); | |
foreignObject.id = id; | |
foreignObject.setAttribute( 'x', x ); | |
foreignObject.setAttribute( 'y', y ); | |
foreignObject.setAttribute( 'width', width ); | |
foreignObject.setAttribute( 'height', height ); | |
const body = document.createElementNS( 'http://www.w3.org/1999/xhtml', 'div' ); | |
body.setAttribute( 'xmlns', 'http://www.w3.org/1999/xhtml' ); | |
body.setAttribute( 'class', klass + ' ' + 'foreignObjectRoot' ); | |
body.innerHTML = xhtml; | |
foreignObject.appendChild( body ); | |
return foreignObject; | |
} | |
function setPardes ( newPardes ) { | |
if ( __currentPardes ) { | |
document.body.classList.remove( __currentPardes ); | |
} | |
__currentPardes = 'pardes-' + newPardes.toLowerCase(); | |
document.body.classList.add( __currentPardes ); | |
} | |
function addLines ( svgRootNode ) { | |
// Paths between sephira: | |
let lineCount = 0; | |
for ( const connection of connections ) { | |
const fromPosition = fromTreeOfLife( connection.from ).Position; | |
const toPosition = fromTreeOfLife( connection.to ).Position; | |
const lineId = `line${ ++lineCount }`; | |
// Create a line element | |
const lineNode = document.createElementNS( 'http://www.w3.org/2000/svg', 'path' ); | |
lineNode.setAttribute( 'id', lineId ); | |
lineNode.setAttribute( 'class', 'line-letter-path' ); | |
lineNode.setAttribute( 'd', ` | |
M ${ fromPosition.x() },${ fromPosition.y() } | |
L ${ toPosition.x() },${ toPosition.y() } | |
` ); | |
lineNode.setAttribute( 'stroke', connection.Color ); | |
lineNode.setAttribute( 'fill', connection.Color ); | |
svgRootNode.appendChild( lineNode ); | |
// Create a textPath element to label the line | |
const textPathNode = document.createElementNS( 'http://www.w3.org/2000/svg', 'textPath' ); | |
textPathNode.setAttribute( 'xlink:href', `#${ lineId }` ); | |
textPathNode.setAttribute( 'class', 'text-path' ); | |
textPathNode.textContent = connection.Letter; | |
// Create a text element and append the textPath | |
const textNode = document.createElementNS( 'http://www.w3.org/2000/svg', 'text' ); | |
textNode.setAttribute( 'dx', '400%' ); | |
textNode.appendChild( textPathNode ); | |
svgRootNode.appendChild( textNode ); | |
} | |
} | |
function addSephirot ( svgRootNode ) { | |
// Render sephirot | |
let circleLines = 0; | |
for ( const sephira in treeOfLife ) { | |
const sephiraData = treeOfLife[ sephira ]; | |
const cx = sephiraData.Position.x(); | |
const cy = sephiraData.Position.y(); | |
const circleId = 'circle-' + ( ++circleLines ); | |
// Create a <g> to group all sephirot | |
const sephiraGroup = document.createElementNS( 'http://www.w3.org/2000/svg', 'g' ); | |
sephiraGroup.setAttribute( 'class', 'sephira-group ' + ( sephira.toLowerCase() ) ); | |
sephiraGroup.addEventListener( 'click', ( e ) => showDetail( sephiraData, e ) ); | |
svgRootNode.appendChild( sephiraGroup ); | |
// Create the sephira sphere and append it to the <g> element | |
const path = document.createElementNS( 'http://www.w3.org/2000/svg', 'path' ); | |
path.setAttribute( 'id', circleId ); | |
path.setAttribute( "d", ` | |
M ${ cx },${ cy - RADIUS_SMALLER } | |
A ${ RADIUS_SMALLER },${ RADIUS_SMALLER } 0 1,0 ${ cx },${ cy + RADIUS_SMALLER } | |
A ${ RADIUS_SMALLER },${ RADIUS_SMALLER } 0 1,0 ${ cx },${ cy - RADIUS_SMALLER } | |
`); | |
path.setAttribute( 'stroke', sephiraData.Translit ); | |
path.setAttribute( 'fill', `url(#gradient-${ sephiraData.Translit })` ); | |
path.setAttribute( 'filter', 'url(#drop-shadow)' ); | |
path.setAttribute( 'class', 'sephira' ); | |
sephiraGroup.appendChild( path ); | |
// Put the Number at the top of the sphere | |
const number = document.createElementNS( 'http://www.w3.org/2000/svg', 'text' ); | |
number.setAttribute( 'class', 'order' ); | |
number.setAttribute( 'x', sephiraData.Position.x() ); | |
number.setAttribute( 'y', sephiraData.Position.y() - ( RADIUS / 1.9 ) ); | |
number.textContent = `${ sephiraData.Order }`; | |
sephiraGroup.appendChild( number ); | |
// Create a title text and append it to the <g> element | |
const title = document.createElementNS( 'http://www.w3.org/2000/svg', 'text' ); | |
title.setAttribute( 'class', 'title' ); | |
title.setAttribute( 'x', sephiraData.Position.x() ); | |
title.setAttribute( 'y', sephiraData.Position.y() ); | |
title.setAttribute( 'filter', 'url(#drop-shadow)' ); | |
title.textContent = `${ sephiraData.Hebrew }`; | |
sephiraGroup.appendChild( title ); | |
// Create a description text and append it to the <g> element | |
// const desc = document.createElementNS( 'http://www.w3.org/2000/svg', 'text' ); | |
// desc.setAttribute( 'class', 'desc' ); | |
// desc.setAttribute( 'x', sephiraData.Position.x() ); | |
// desc.setAttribute( 'y', sephiraData.Position.y() + ( RADIUS + 15 ) ); | |
// desc.textContent = `${ sephiraData.Translit } (${ sephiraData.English }) · ${ sephiraData.Letter }`; | |
// sephiraGroup.appendChild( desc ); | |
// Pardes | |
for ( let pardes of [ 'peshat', 'remez', 'derash', 'sod' ] ) { | |
const xhtml = `<ul><li>${ sephiraData.Translit } (${ sephiraData.English })</li><li>${ sephiraData.Letter }</li>`; | |
sephiraGroup.appendChild( | |
foreignObject( { | |
x: sephiraData.Position.x() - ( RADIUS * 2.5 ), | |
y: sephiraData.Position.y() + ( RADIUS / 0.9 ), | |
width: RADIUS * 5, | |
height: RADIUS * 2, | |
klass: 'desc pardes-' + pardes, | |
xhtml: xhtml | |
} ) | |
); | |
} | |
// TextPath: wrap some text around the same path as the circle: @see associated CSS | |
const textPathNode = document.createElementNS( 'http://www.w3.org/2000/svg', 'textPath' ); | |
textPathNode.setAttribute( 'href', `#${ circleId }` ); | |
textPathNode.setAttribute( 'class', 'sephirot-outter-text-path' ); | |
textPathNode.setAttribute( 'startOffset', '50%' ); | |
textPathNode.textContent = sephiraData.Attr.join( ' ' ); | |
// Create a text element and append to the textPath created above | |
const textNode = document.createElementNS( 'http://www.w3.org/2000/svg', 'text' ); | |
textNode.appendChild( textPathNode ); | |
sephiraGroup.appendChild( textNode ); | |
// Get the bounding box (size) of the <g> element | |
const bbox = sephiraGroup.getBBox(); | |
// and create a <rect> element to match the size | |
if ( !sephiraData.noBg ) { | |
const rect = document.createElementNS( 'http://www.w3.org/2000/svg', 'rect' ); | |
rect.setAttribute( 'x', bbox.x - ( RADIUS / 2 ) ); | |
rect.setAttribute( 'y', bbox.y - ( RADIUS / 2 ) ); | |
rect.setAttribute( 'width', bbox.width + ( RADIUS * 2 ) ); | |
rect.setAttribute( 'height', bbox.height + ( RADIUS * 2 ) ); | |
rect.setAttribute( 'class', 'bg' ); | |
// Insert the <rect> as the first child of the <g> element | |
sephiraGroup.insertBefore( rect, sephiraGroup.firstChild ); | |
} | |
} | |
} | |
function addPardes ( pardes ) { | |
setPardes( 'peshat' ); | |
document.getElementById( 'pardes' ).addEventListener( 'click', ( e ) => { | |
setPardes( String( | |
e.target.id || e.target.parentElement.id || e.target.parentElement.parentElement.id | |
).toLowerCase() ); | |
} ); | |
} | |
function createSvg () { | |
const svg = document.getElementById( 'svg' ); | |
const svgRootNode = document.createElementNS( 'http://www.w3.org/2000/svg', 'g' ); | |
svg.appendChild( svgRootNode ); | |
return svgRootNode; | |
} | |
const fromTreeOfLife = sephiraTranslitName => treeOfLife[ sephiraTranslitName ]; | |
const treeOfLife = { | |
EinSof: { | |
Order: 0, | |
Hebrew: 'אֵין סוֹף אוֹר', | |
Translit: 'Ohr Ein Sof, Ein Sof, Ein', | |
English: 'Limitless Light, Limitless, Nothing', | |
Letter: ' ', | |
LetterName: ' ', | |
Attr: [], | |
Position: { | |
x: () => 0, | |
y: () => -1 * RADIUS, | |
}, | |
}, | |
Keter: { | |
Order: 1, | |
Hebrew: 'כֶּתֶר', | |
Translit: 'Keter', | |
English: 'Crown', | |
Letter: 'א', | |
LetterName: 'Aleph', | |
Attr: [ 'crown', 'aura', 'yechidah' ], | |
Position: { | |
x: () => fromTreeOfLife( 'EinSof' ).Position.x(), | |
y: () => fromTreeOfLife( 'EinSof' ).Position.y() + Y_PAD, | |
}, | |
}, | |
Mercy: { | |
noBg: true, | |
Order: 1, | |
Hebrew: 'יָכִין', | |
Translit: 'Yakin', | |
English: 'Mercy', | |
Letter: '', | |
LetterName: '', | |
Attr: [ '' ], | |
Position: { | |
x: () => fromTreeOfLife( 'Keter' ).Position.x() + ( 1.6 * X_PAD ), | |
y: () => fromTreeOfLife( 'Keter' ).Position.y(), | |
}, | |
}, | |
Severity: { | |
noBg: true, | |
Order: 1, | |
Hebrew: 'בועז', | |
Translit: 'Boaz', | |
English: 'Severity', | |
Letter: '', | |
LetterName: '', | |
Attr: [ '' ], | |
Position: { | |
x: () => fromTreeOfLife( 'Keter' ).Position.x() - ( 1.6 * X_PAD ), | |
y: () => fromTreeOfLife( 'Keter' ).Position.y(), | |
}, | |
}, | |
Chokhmah: { | |
Order: 2, | |
Hebrew: 'חָכְמָה', | |
Translit: 'Chokhmah', | |
English: 'Wisdom', | |
Letter: 'ב', | |
LetterName: 'Bet', | |
Attr: [ 'wisdom', 'face of the hashem', 'chiam' ], | |
Position: { | |
x: () => fromTreeOfLife( 'Keter' ).Position.x() + X_PAD, | |
y: () => fromTreeOfLife( 'Keter' ).Position.y() + Y_PAD, | |
}, | |
}, | |
Binah: { | |
Order: 2, | |
Hebrew: 'בִּינָה', | |
Translit: 'Binah', | |
English: 'Understanding', | |
Letter: 'ג', | |
LetterName: 'Gimel', | |
Color: 'black', | |
Attr: [ 'understanding', 'mother', 'neschamah' ], | |
Position: { | |
x: () => fromTreeOfLife( 'Keter' ).Position.x() - X_PAD, | |
y: () => fromTreeOfLife( 'Keter' ).Position.y() + Y_PAD, | |
}, | |
}, | |
Chesed: { | |
Order: 4, | |
Hebrew: 'חֶסֶד', | |
Translit: 'Chesed', | |
English: 'Kindness', | |
Letter: 'ד', | |
LetterName: 'Dalet', | |
Color: 'turquoise', | |
Attr: [ 'hashem mercy', 'majesty', 'vision of love' ], | |
Position: { | |
x: () => fromTreeOfLife( 'Chokhmah' ).Position.x(), | |
y: () => fromTreeOfLife( 'Chokhmah' ).Position.y() + ( Y_PAD * 1.5 ), | |
}, | |
}, | |
Geburah: { | |
Order: 5, | |
Hebrew: 'גְּבוּרָה', | |
Translit: 'Geburah', | |
English: 'Severity', | |
Letter: 'ה', | |
LetterName: 'Hey', | |
Color: 'hsl(39, 71%, 48%)', | |
Attr: [ 'strength', 'vision of power', 'force' ], | |
Position: { | |
x: () => fromTreeOfLife( 'Binah' ).Position.x(), | |
y: () => fromTreeOfLife( 'Binah' ).Position.y() + ( Y_PAD * 1.5 ), | |
}, | |
}, | |
Tiferet: { | |
Order: 6, | |
Hebrew: 'תִּפְאֶרֶת', | |
Translit: 'Tiferet', | |
English: 'Beauty', | |
Letter: 'ו', | |
LetterName: 'Vav', | |
Attr: [ 'beauty', 'harmony', 'breath' ], | |
Position: { | |
x: () => fromTreeOfLife( 'Keter' ).Position.x(), | |
y: () => fromTreeOfLife( 'Chesed' ).Position.y() + Y_PAD, | |
}, | |
}, | |
Netzach: { | |
Order: 7, | |
Hebrew: 'נֵצַח', | |
Translit: 'Netzach', | |
English: 'Eternity', | |
Letter: 'ז', | |
LetterName: 'Zayin', | |
Color: 'hsl(120, 85%, 39%)', | |
Attr: [ 'victory', 'eternity', 'triumph' ], | |
Position: { | |
x: () => fromTreeOfLife( 'Tiferet' ).Position.x() + X_PAD, | |
y: () => fromTreeOfLife( 'Tiferet' ).Position.y() + Y_PAD, | |
}, | |
}, | |
Hod: { | |
Order: 8, | |
Hebrew: 'הוֹד', | |
Translit: 'Hod', | |
English: 'Glory', | |
Letter: 'ח', | |
LetterName: 'Chet', | |
Color: 'hsl(51, 100%, 50%)', | |
Attr: [ 'images of hashem', 'truthfulness', 'splendor' ], | |
Position: { | |
x: () => fromTreeOfLife( 'Tiferet' ).Position.x() - X_PAD, | |
y: () => fromTreeOfLife( 'Tiferet' ).Position.y() + Y_PAD, | |
}, | |
}, | |
Yesod: { | |
Order: 9, | |
Hebrew: 'יְסוֹד', | |
Translit: 'Yesod', | |
English: 'Foundation', | |
Letter: 'ט', | |
LetterName: 'Tet', | |
Color: 'purple', | |
Attr: [ 'foundation', 'astral light', 'nepesch' ], | |
Position: { | |
x: () => fromTreeOfLife( 'Keter' ).Position.x(), | |
y: () => fromTreeOfLife( 'Hod' ).Position.y() + Y_PAD, | |
}, | |
}, | |
Malkhut: { | |
Order: 10, | |
Hebrew: 'מַלְכוּת', | |
Translit: 'Malkhut', | |
English: 'Kingdom', | |
Letter: 'י', | |
LetterName: 'Yod', | |
Color: 'white', | |
Attr: [ 'kingdom', 'mystic circle', 'guph!' ], | |
Position: { | |
x: () => fromTreeOfLife( 'Keter' ).Position.x(), | |
y: () => fromTreeOfLife( 'Yesod' ).Position.y() + ( Y_PAD * 1.2 ), | |
}, | |
}, | |
}; | |
const connections = [ | |
{ | |
from: 'Keter', | |
to: 'Chokhmah', | |
LetterName: 'Aleph', | |
Color: '#0000FF', | |
Letter: 'א', | |
}, | |
{ | |
from: 'Keter', | |
to: 'Binah', | |
LetterName: 'Bet', | |
Color: '#0000FF', | |
Letter: 'ב', | |
}, | |
{ | |
from: 'Chokhmah', | |
to: 'Chesed', | |
LetterName: 'Vav', | |
Color: '#0000FF', | |
Letter: 'ו', | |
}, | |
{ | |
from: 'Chokhmah', | |
to: 'Binah', | |
LetterName: 'Dalet', | |
Color: '#0000FF', | |
Letter: 'ד', | |
}, | |
{ | |
from: 'Geburah', | |
to: 'Hod', | |
LetterName: 'Mem', | |
Color: '#0000FF', | |
Letter: 'מ', | |
}, | |
{ | |
from: 'Chesed', | |
to: 'Geburah', | |
LetterName: 'Tet', | |
Color: '#0000FF', | |
Letter: 'ט', | |
}, | |
{ | |
from: 'Chesed', | |
to: 'Netzach', | |
LetterName: 'Kaf', | |
Color: '#0000FF', | |
Letter: 'כ', | |
}, | |
{ | |
from: 'Geburah', | |
to: 'Tiferet', | |
LetterName: 'Yod', | |
Color: '#0000FF', | |
Letter: 'י', | |
}, | |
{ | |
from: 'Chesed', | |
to: 'Tiferet', | |
LetterName: 'Lamed', | |
Color: '#0000FF', | |
Letter: 'ל', | |
}, | |
{ | |
from: 'Tiferet', | |
to: 'Netzach', | |
LetterName: 'Nun', | |
Color: '#0000FF', | |
Letter: 'נ', | |
}, | |
{ | |
from: 'Tiferet', | |
to: 'Hod', | |
LetterName: 'Ayin', | |
Color: '#0000FF', | |
Letter: 'ע', | |
}, | |
{ | |
from: 'Netzach', | |
to: 'Hod', | |
LetterName: 'Peh', | |
Color: '#0000FF', | |
Letter: 'פ', | |
}, | |
{ | |
from: 'Netzach', | |
to: 'Yesod', | |
LetterName: 'Tzadi', | |
Color: '#0000FF', | |
Letter: 'צ', | |
}, | |
{ | |
from: 'Hod', | |
to: 'Yesod', | |
LetterName: 'Resh', | |
Color: '#0000FF', | |
Letter: 'ר', | |
}, | |
{ | |
from: 'Yesod', | |
to: 'Malkhut', | |
LetterName: 'Tav', | |
Color: '#0000FF', | |
Letter: 'ת', | |
}, | |
{ | |
from: 'Binah', | |
to: 'Geburah', | |
LetterName: 'Chet', | |
Color: '#0000FF', | |
Letter: 'ח', | |
}, | |
]; | |
const svgRootNode = createSvg(); | |
addLines( svgRootNode ); | |
addSephirot( svgRootNode ); | |
addPardes( 'peshat' ); | |
</script> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment