The Shrine of Anubis — An adventure in hieroglyphs and javascript

David Grophland
9 min readSep 9, 2020

--

In 2007 I decided to create an online shrine to the egyptian god Anubis as a birthday present for my wife, who is a practising khemetic (a follower of the ancient egyptian gods). The shrine was a place to make a voice offering (ḥtp-ḏỉ-nsw), a tradition whereby the common egyptian might partake of the costly offerings (of bread, beer, oxen, birds, alabaster, clothing, and every good and pure thing upon which a god lives — as the formula goes) that the king would give to the God in question, and pass them on to their deceased loved ones. In this way, offerings presented by family members could be seen as divinely mediated by the king.

On the Anubis Shrine you could make your own voice offerings by clicking on various possible offerings (each based on items mentioned in egyptian texts), which would then be displayed on the image of the shrine, along with an excerpt from the offering formula, both in English, and as hieroglyphs. Something a little like this:

A screenshot of the new shrine

The original site was created using the technologies of the day, a PHP backend, a flash animation allowing you to open the doors of the shrine, and animated GIFs for the various offerings you could give — such as incense, candles, or overflowing beer. The gift went down well, and anubis-shrine.net continued to provide its virtual religious services for the following decade and more.

Until late 2019, that is, when a disasterous server crash wiped the site from existence. In the wake of the crash I was distressed to find that I had no copy of it (the site was never under source control). The only thing remaining was a folder of images and a couple of photoshop files.

This could not stand, so this year I set out to build the site again. In the process I came across a number of coding tricks, some related to hieroglyphics, and some not, which might be of interest to others — hence this article.

Ressurecting the Site

Step one was to try and ressurect as much of the original site as possible, which I thought was rather appropriate for a shrine to the god of the dead. I was able to locate a copy of the original site through the internet archive, which let me download a copy of the papyrus-like background image, and remind me of the general layout. From this I was able to piece together most of the images, and view a copy of that original flash animation (which isn’t easy these days). Of course, since it was a server based site, all the original code remained lost.

I knew I didn’t want to use the same technologies for my new version. I switched from a server-side app using PHP to a client-side one using Vue, both for speed, and because I have to maintain some Vue at work, but had never actually created a project of my own with it. Flash was right out, of course, and I hoped to be able to replace the GIF animations with something better. At the same time I wanted to stay as close to the original feel and concept of the site as a whole. Breaking it down, I knew I had to tackle the following:

  • The animation of the opening doors (which had been flash)
  • The placing of items in the shrine
  • The animation of the items (which had been GIFs)
  • The hieroglyphics

Animation

Back in 2007, if you wanted animation, you used Flash. Flash welcome pages were all the rage, and the shrine was no exception. The landing page was a flash file showing two golden doors, which you could click to enter. Doing so slid the doors aside, then navigated to a second page with the shrine itself.

What had been difficult in 2007 turned out to be a breeze in 2020. I placed the doors in their own absoloutely positioned div, and wrapped it in a Vue transition element.

<transition name=”open” :duration=”2000">
<div id=”doors” v-if=”show_doors” v-on:click=”show_doors = false”>
<div class=”back”></div>
<div class=”door left”></div>
<div class=”door right”></div>
<div class=”shadow left”></div>
<div class=”shadow right”></div>
</div>
</transition>

Vue transition elements provide a way to animate elements entering or leaving the DOM. Vue automatically applies a series of classes to the transition element when the transition happens, such as v-leave, when the the element starts to leave the DOM, and v-leave-active, which is applied until the element finishes being removed. In this case I used some CSS transitions triggered by the open-leave-active class. e.g.

.open-leave-active .door.left {
animation: door_left 2s linear forwards;
}

Note that it is open-leave-active, rather than v-leave-active, because I named the transition ‘open’ in the element.

Vue is smart enough to know when a transition or animation on the root element ends, but in this case there are multiple child elements (left door, right door, background) being animated, and each animation has a different duration. In this case you can specify a :duration property on the transition element, as I’ve done here (Vue 2.2.0+ only).

UI

The core UI of the site, selecting offerings and adding them to the shrine, is a pretty simple piece of code, especially if you are familiar with Vue, so I won’t go into it in detail. Essentially, the shrine is split into three offering areas, which are absoloutely positioned divs.

offering areas

A matching object in Vue holds a list of all the offerings in each area, along with the maximum available width (in pixels) that the area can hold. Each offering, in turn, has a width (it varies from item to item) and an area it should be placed in. As you add offerings to an area, Vue tracks the total width used, and stops adding things when you run out of room. The same calculation is used to add a disabled class to offerings that will no longer fit in the shrine, again using a Vue method. In retrospect I could also have used a computed property for this.

some enabled and disabled offerings

A little digression about those item images. Players of my virtual pet game grophland.com might recognise some of these pictures. After creating the shrine back in 2007 I re-used the images for items in the game. Over the years, many of the items were then redrawn as the site style changed (for example the Nebes Cake is the original, the Saf Cake was a redraw). Re-creating the site, I used the updated images where they existed, so they went full circle.

When an item is added to the list for an area, it is displayed using a simple v-for loop:

<div id="shrine">
<div v-for="(area, name) in areas" :id="name" class="area">
<div v-for="item in area.items" class="offering" :style="item.style" :class="item.id"></div>
</div>
</div>

The item.style property is used to position the item inside the offering area with css custom properties:

offering.style = {
'--image': 'url('+offering.image+')',
'--width': offering.width + 'px',
'--height': offering.height + 'px'
};

Animated Items

Most of the offerings are static images, but some are animated. The candle flame flickers, the incense has smoke, and the beer drips froth. In 2007 these were animated GIFs, which (since they had transparent backgrounds) were terribly pixellated. The animated GIFs were gone, but the photoshop originals remained.

There are lots of ways to do animation, now, of course, including many dedicated JS libraries, but I wanted something lighter weight, and not so demanding on the browser, so I looked to CSS animations. CSS usually animates something continuously, but I wanted the equivalent of a frame-by-frame style, with each frame played in series. The CSS step() function allows this. It splits an animation into steps of equal length, and jumps directly to each step position without the usual interpolation.

The first step was to create a film-strip style image containing all of the frames for a given animation. This example is for the dripping beer:

The offering has this image as the background image. A css @keyframes rule then translates this background image along it’s length as follows:

@keyframes beer {
from { background-position-x : 0px; }
to { background-position-x :-793px; }
}

Normally this would slide the background image, but the steps() function makes this movement go frame to frame:

.area .offering.beer {
animation: beer 1500ms steps(13) infinite;
}

The only drawback of this technique is that there’s no way to make one ‘frame’ last longer than another, because all the steps will be equal. The only way to add a pause is to repeat the paused frame like I’ve done for the beer image.

The Hieroglyphics

The final challenge was to display the hieroglyphic translation of the voice offering you were making. Back in 2007 I just showed a GIF, the same GIF for each offering, surely in 2020 I could do better.

the effect we are trying to achieve

There are plenty of so-called hieroglyphic fonts floating around the web, but most just display 20–50 random hieroglyphs, or just use the basic single-letter (uniliteral) signs that you’ve probably seen printed on rulers, posters, and novelty tiles. By late antiquity the egyptians were using thousands of signs.

Gardiner’s sign list (compiled by Sir Alan Gardiner between 1927 and 1957, and published as part of Egyptian Grammar: Being an Introduction to the Study of Hieroglyphs) contains a little over 1000 signs, organised by categories and given letter codes. This is the most commonly used list, and contained all the signs I needed. Here’s an example:

Sign E16, jackal on a shrine

Part of Google Fonts, is something called the Noto Fonts Project. Noto (no-more-tofu) is an attempt to provide web fonts for every langauge and script system defined in Unicode, and it turns out that Unicode has an Egypitan Code Block that corresponds to Gardiner’s List, so naturally Noto has a font for it: Noto Sans Egyptian Hieroglyphs.

Of course, it’s not quite as simple as writing the offering formula in English and then setting the font to Noto Sans. In fact, using Noto to present the translations turned out to be a manual nightmare. I knew what signs I needed (you can find images of the offering formula all over the web), but I had to look up each one in Gardiner’s list (by eye) to get it’s sign number, then find that in the Unicode sign list to get the code point, and then turn that into an HTML entity to allow me to display it.

geting the html entity for sign O3

Still nothing is simple. It was common practice for hieroglyphs to be written in groups that alternate from vertical to horizontal, with signs adjusted in size and spacing as needed. The Unicode characters (and Noto’s version of them) try and reflect some of these practices by moving individual glyphs above and below the baseline, so that there is no real consistency about how characters line up.

To get around this I wrapped each character in a span, and put those spans in groups to reflect the orientations I needed.

You can see on this image how the horizontal lines are set below their baselines, so I changed the line heights of the stacked glyphs to compensate.

Conclusions

If you’ve stuck with this rambling discussion all the way to the end, you’ll be glad to know that anubis-shrine.net is now back and running (and in source control). If you’ve enjoyed this in-depth look, perhaps you’d like to go and make an offering (religious or otherwise, no faith is required), and try it out.

--

--