Elysium

Digital afterlife interactive design project


Interactive Website & Digital Afterlife Experience

Solo project | 2023

Tools: HTML, CSS, JavaScript, Three.js, Adobe After Effects, Adobe Illustrator, Midjourney.

Elysium: Cherishing Memories

Discover Elysium's journey of remembrance. This video takes you through Elysium web, showcasing how you can cherish and revisit life's precious moments with your loved ones. Witness the simplicity and serenity of remembering in the digital age.

极乐世界:珍惜回忆

探索极乐世界的纪念之旅。 该视频将带您浏览 Elysium 网站,展示如何与您所爱的人一起珍惜和重温生命中的珍贵时刻。 见证数字时代记忆的简单和宁静。

work cited:

“San Junipero.” Black Mirror, created by Charlie Brooker, season 3, episode 4, Netflix, 2016.

JVKE - golden hour (instrumental),Sep 16, 2022

Inspiration

The idea of an afterlife has been deeply entrenched in human history and cultures. Philosophers, scientists, theologians, and countless thinkers have pondered upon the idea of existence after death. As technology advanced, so did the boundaries of these thoughts. With the concept of Elysium, the inspiration isn't drawn merely from the realms of fantasy or spiritual beliefs but from the tangible advancements in artificial intelligence, quantum computing, and the digital frontier.


对于来世的想法深深植根于人类的历史和文化之中。哲学家、科学家、神学家以及无数思想家都曾深思死后的存在。随着技术的进步,这些想法的边界也在拓宽。伊甸园的概念不仅仅源于幻想或精神信仰,更基于人工智能、量子计算以及数字前沿的实实在在的进步。

A PESTEL Analysis on the Viability of Digital Afterlife Solutions

数字遗产解决方案的可行性PESTEL分析

  • 1.Data Rights and Legislation: Governments globally are focusing on data protection rights. The right to digital legacy can soon become an extension of this, allowing for the storage and use of personal digital imprints posthumously.

    2.Regulations on AI and VR: As nations become more tech-savvy, legislation will evolve to accommodate the growth of AI and VR technologies, ensuring that their usage respects ethical boundaries and consumer rights.

    1.数据权利与立法:全球政府正集中关注数据保护权。数字遗产的权利很可能会成为此权利的延伸,允许人们在去世后存储和使用个人的数字印记。

    2.人工智能和虚拟现实的规制:随着各国变得更懂技术,立法将发展以适应人工智能和虚拟现实技术的增长,确保其使用尊重伦理边界和消费者权利。

  • 1.Emerging Market: As the world continues to digitize, the economic potential for digital afterlife services is vast. People may be willing to pay for ensuring their digital continuity and creating a legacy.

    2.Potential Labor Shortage: The possibility of declining populations and labor shortages could stimulate demand for digital citizens who can continue to contribute to society.

    1.新兴市场:随着世界不断数字化,数字化后生活服务的经济潜力巨大。人们可能愿意支付费用来确保他们的数字延续性并创造遗产。

    2.潜在劳动力短缺:人口下降和劳动力短缺的可能性可能会刺激对能够继续为社会做出贡献的数字公民的需求。

  • 1.Changing Perceptions of Death: The contemporary view of death is shifting towards a more holistic understanding that includes digital continuity and legacy.

    2.Digital Era and Identity: The current generation's identity is closely tied with their digital presence, leading to a demand for services that ensure this identity doesn't simply vanish after death.

    1.死亡观念变化:当代对死亡的看法正在转变为包含数字延续性和遗产在内的更全面理解。

    2.数字时代与身份:当前一代的身份与他们的数字存在紧密相连,从而导致了一种服务的需求,确保这种身份在死后不会简单消失。

  • 1.AI and Quantum Computing Advancements: These technologies can recreate intricate digital personas, making the idea of conversing with a loved one posthumously a feasible reality.

    2.Mainstream VR: VR platforms can offer immersive experiences, allowing individuals to relive memories or interact with digital representations of their loved ones.

    1.人工智能与量子计算进步:这些技术可以重现复杂的数字化人格,使得与已故亲人对话成为一个可行的现实。

    2.主流虚拟现实:虚拟现实平台可以提供沉浸式体验,允许个人重温记忆或与其亲人的数字化表征互动。

  • 1.Sustainability of Digital Storage: With advancements in green technologies, storing vast amounts of data sustainably is becoming a reality, ensuring the digital legacy is environmentally friendly.

    2.E-remembrance Vs. Physical Monuments: Digital memorials and tributes could be seen as more sustainable than physical monuments, reducing material consumption and land use.

    1.数字存储的可持续性:随着绿色技术的进步,可持续地存储大量数据正在成为现实,确保数字遗产环保。

    2.电子纪念与实体纪念碑:数字纪念和致敬可能被视为比实体纪念碑更可持续的方式,减少物质消耗和土地使用。

  • 1.Digital Will and Testament: Legal systems might soon recognize digital wills that decide how one's online presence should be managed post-death.

    2.Ethical AI Use: Legislation ensuring that AI recreations of individuals respect the wishes and rights of the deceased will be crucial for services like Elysium.

    1.数字遗嘱:法律系统可能很快就会认可数字遗嘱,决定个人死后在线存在应如何被管理。

    2.人工智能的伦理使用:确保人工智能重现个体时尊重逝者的意愿和权利的立法将对像极乐这样的服务至关重要。

The Digital Self and the Evolution of Death

In today's world, we exist both in reality and the digital realm, with our social media posts and personal data forming a 'digital self' alongside our physical being. Elysium was born from this duality, pondering the continuation of our digital selves beyond physical cessation. As technology entwines with our existence, the concept of death itself is evolving. No longer just a physical end, it now encompasses a digital dimension, paving the way for a digital afterlife.

数字自我与死亡的进化
在当今世界,我们既存在于现实世界,也活跃在数字领域,我们的社交媒体动态和个人数据共同构成了我们的“数字自我”,与我们的肉体存在并行。Elysium的诞生正来源于这种二元性,它思考的是我们数字自我的延续,即使是在身体生命终止之后。随着技术与我们的生活越发交织在一起,死亡的概念本身也在演变。死亡不再仅仅是肉体的终结,现在它还包括了数字化的维度,为数字化的来世铺平了道路。

Elysium's Vision of Digital Citizenship:

Elysium envisions a future where physical demise is not an end but a transition to a new digital existence. Here, individuals become 'digital citizens' - interactive digital personas created from their memories and personal data. These entities do more than just preserve memory; they interact, learn, evolve, and contribute to the digital world. This approach addresses the potential challenges of declining populations and labor shortages by retaining and extending one's contributions beyond physical existence.

Elysium 的数字公民愿景:

Elysium展望的未来,身体的消逝不再是终结,而是向全新数字生存形态的过渡。在这里,人们将成为“数字公民”——由他们的记忆和个人数据构建的互动数字化身。这些数字实体不仅仅是记忆的存储;它们能够交互、学习、进化,并为数字世界做出贡献。这种方式应对了人口下降和劳动力短缺的潜在挑战,通过保留并延伸一个人在物理存在之外的贡献。

A New Chapter in Human Legacy

Elysium is not just a digital memorial but a bridge connecting past, present, and future. It represents the human spirit's quest to transcend boundaries, moving from mere record-keeping to creating digital legacies that actively participate in the future. Elysium is about building a world where memories and legacies don't just survive but thrive, redefining the very essence of our existence in an increasingly digital age.

人类遗产的新篇章

Elysium 不仅仅是一个数字纪念馆,还是一座连接过去、现在和未来的桥梁。它代表着人类精神对超越界限的追求,从单纯的记录到创造积极参与未来的数字遗产。极乐世界 "是要建立一个世界,在这个世界里,记忆和遗产不仅能够存活,还能茁壮成长,重新定义我们在日益数字化的时代中存在的本质。

Research process - mind map

Research process - mind map

Company

Company

  • At Elysium, we embrace the profound desire to be remembered. Our mission utilizes the forefront of technology to enable individuals to eternally preserve their life experiences in the digital domain, allowing for an enduring impact beyond the physical life.

    核心使命

    在极乐世界,我们崇尚被人铭记的深刻愿望。我们的使命是利用最前沿的技术,使个人能够在数字领域永久保存他们的人生经历,从而产生超越物质生活的持久影响。

  • The Elysium logo, inspired by the Möbius strip, is a symbol of life's unending narrative. Its circular form signifies an everlasting journey, mirroring the seamless transition from the physical world to digital immortality. This emblem represents our dedication to maintaining the continuity of human stories.

    Logo设计

    极乐世界徽标的设计灵感来自莫比乌斯带,象征着生命的永恒。它的圆形象征着永恒的旅程,反映了从物理世界到数字永生的无缝过渡。这个徽标代表着我们致力于保持人类故事的连续性。

Elysium Company

"Step into 2030, where Elysium is not just a company but an industry reshaping our understanding of life, memories, and digital existence. Rooted in the present, our current offerings ensure that every significant life moment is captured, curated, and celebrated. Yet, our vision stretches far beyond, into a future where the boundaries between life and digital afterlife blur, where memories aren't just remembered but relived, and where every individual has the chance to continue their journey in the digital realm. Welcome to Elysium, where our mission today seeds the digital realities of tomorrow."

极乐世界公司

"走进 2030 年,Elysium 不仅仅是一家公司,更是一个行业,它将重塑我们对生活、记忆和数字存在的理解。植根于当下,我们目前提供的产品可确保捕捉、策划和庆祝生命中的每一个重要时刻。然而,我们的愿景远不止于此,在未来,生命与数字人生之间的界限将变得模糊,记忆将不仅仅是被铭记,而是被重温,每个人都有机会在数字领域继续他们的旅程。欢迎来到极乐世界,在这里,我们今天的使命孕育着明天的数字现实。

  • Elysium offers a meticulously crafted digital environment for preserving life's key moments. This platform allows users to capture, access, and interact with memories, creating a bridge between past experiences and current remembrances.

    数字体验

    Elysium 提供精心打造的数字环境,用于保存生活中的重要时刻。该平台允许用户捕捉、访问记忆并与之互动,在过去的经历和现在的回忆之间架起一座桥梁。

  • Elysium's financial structure is rooted in a subscription model for data collection and maintenance of digital personas. Beyond this, we diversify our revenue through partnerships and integrations with digital platforms, adding value with unique content and experiences. Additionally, Elysium taps into digital content creation, where these personas can inspire or contribute to various media and virtual projects. Our tiered service offerings cater to a range of client needs and budgets, ensuring a sustainable and innovative approach to digital legacy management.

    财务模式

    Elysium 的财务结构以订阅模式为基础,用于收集数据和维护数字角色。除此以外,我们还通过与数字平台的合作和整合,实现收入的多元化,通过独特的内容和体验来增加价值。此外,Elysium 还涉足数字内容创作,这些角色可以激发或促进各种媒体和虚拟项目。我们的分层服务可以满足不同客户的需求和预算,确保以可持续和创新的方式进行数字遗产管理。

Service Blueprint:

Current (2030) Plan:

  • Data Collection: Gather memories, experiences, and personal data from users.

  • Memory Curation: Process and curate the data into navigable 'Life Nodes'.

  • Digital Immortalization: Create digital personas for users based on their collected data, enabling interaction posthumously.

  • User Engagement: Allow loved ones to engage with these personas, celebrating memories and reliving shared experiences.

服务蓝图:

当前(2030 年)计划:

  • 数据收集: 收集用户的记忆、经历和个人数据。

  • 记忆整理: 将数据加工整理成可浏览的 "生活节点"。

  • 数字不朽化: 根据收集到的数据为用户创建数字角色,以便在死后进行互动。

  • 用户参与: 让亲人与这些角色互动,庆祝回忆,重温共同经历。

Service Blueprint:

Future Plan:

  • Advanced AI Interaction: Empower the digital personas with advanced AI capabilities for more profound, realistic interactions.

  • Digital Legacy Creation: Allow digital personas to generate content, contribute to the digital world, and fulfill legacy aspirations.

  • Expanding Digital Citizenship: As digital citizens, these personas continue to add value, with some proceeds channeled back for data maintenance.

服务蓝图:

未来计划:

  • 高级人工智能互动: 利用先进的人工智能功能,增强数字角色的能力,实现更深刻、更逼真的互动。

  • 数字遗产创造: 让数字角色生成内容,为数字世界做出贡献,实现传承愿望。

  • 扩展数字公民身份: 作为数字公民,这些 "角色 "不断增值,并将部分收益用于数据维护。

Interactive experience

Interactive experience

Narrative Scenarios for Elysium's Service Experience - two characters

Elysium服务体验的叙事场景——两个角色

Character One: Eliza Sullivan

Eliza Sullivan, born March 5, 1980, in South Carolina, was raised by a hardworking single mother. Her love for literature, sparked in school, led her to excel as her high school's valedictorian. She pursued English Literature at the University, graduating in 2002. Returning to her hometown, Eliza taught literature at her former school and wrote mystery novels in her spare time. Married in 2004 and a mother of two, she faced a challenging breast cancer diagnosis in 2019. Despite her illness, she continued writing until her passing in 2030 at age 50.

角色一:伊丽莎·沙利文

伊丽莎·沙利文 (Eliza Sullivan) 1980 年 3 月 5 日出生于南卡罗来纳州,由一位勤奋的单亲母亲抚养长大。 她在学校时就激发了对文学的热爱,这使她成为了高中的告别演说者。 她在大学主修英国文学,于 2002 年毕业。回到家乡后,伊丽莎在以前的学校教授文学,并在业余时间写悬疑小说。 她于 2004 年结婚,是两个孩子的母亲,2019 年被诊断出患有乳腺癌。尽管患病,她仍继续写作,直到 2030 年去世,享年 50 岁。

Character Two: Diana Mitchell

Diana Mitchell, born July 16, 1980, grew up alongside Eliza in South Carolina. They shared a strong bond, rooted in their single-parent upbringing. Excelling academically, Diana graduated from University in 2002 with a Political Science degree and then from Law School in 2005. She quickly rose to partner at a top law firm by 2015. Despite her career demands, Diana's friendship with Eliza remained a constant. After Eliza's death in 2030, Diana honored her legacy by publishing her novels, which gained widespread acclaim and were adapted into films.

角色二:戴安娜·米切尔

戴安娜·米切尔出生于 1980 年 7 月 16 日,与伊丽莎一起在南卡罗来纳州长大。 他们有着深厚的感情,这源于他们的单亲成长。 戴安娜在学业上表现出色,于 2002 年从大学毕业,获得政治学学位,然后于 2005 年从法学院毕业。到 2015 年,她很快晋升为一家顶级律师事务所的合伙人。尽管她有职业要求,但戴安娜与伊丽莎的友谊始终如一。 2030 年伊丽莎去世后,戴安娜出版了小说,以纪念她的遗产,这些小说获得了广泛好评并被改编成电影。

Memorial Moments

Visual concept - Web design

Elysium's website combines circular designs, symbolizing life's continuous journey, with a tranquil black, white, and blue color palette. It features three interconnected views – Road, Over, and Post – each offering unique perspectives on life’s moments against the timeless backdrop of the clock, representing the passage of time. This minimalist approach ensures a focus on cherished memories, creating a respectful, supportive environment for users to connect with their loved ones' narratives.

视觉概念-网页设计


网站以黑、白和蓝的宁静色彩搭配,采用循环的圆形设计,象征着生命的持续旅程。网站特设三个视角——“路途”、“俯瞰”与“帖子”,各展现生命中瞬间的独特视点,并以时钟的恒久流转为背景,隐喻时间的推移。这种设计手法旨在突出珍贵的记忆,为用户提供一个温馨的空间,让他们与所爱之人的生命故事产生共鸣。

Web development in progress

Web development in progress

Web development in progress

Road View

The Road View is an interactive circular path reflecting life's progression. Dragging the path uncovers each pivotal memory. Images emerge into focus, facilitating an active journey through time. This design mirrors our personal recollection process, where each rotation surfaces a new memory, making the experience of revisiting the past more engaging and vivid.


路途视角是一个代表生活旅程的互动圆形路径。你可以拖动路径,一一展开每个重要的回忆。随着图像逐步聚焦,它带领你活跃地穿越时光。这样的设计模仿了我们回忆的过程:每旋转一次,就浮现出一段新的记忆,让对过去的回顾变得更加生动有趣。

  • <!DOCTYPE html>

    <html lang="en">

    <head>

    <meta charset="UTF-8">

    <meta name="viewport" content="width=device-width, initial-scale=1.0">

    <title>Elysium-road View</title>

    <link rel="stylesheet" href="../../part 2/roadview.css">

    <link rel="stylesheet" href="../../part 2/button.css">

    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css">

    <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/js/bootstrap.min.js"></script>

    <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/js/bootstrap.bundle.min.js"></script>

    <link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">

    <script src="https://code.jquery.com/jquery-3.3.1.js"></script>

    <script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/2.0.2/TweenMax.min.js"></script>

    </head>

    <body>

    <div class="wrapper">

    <div class="menu-btn">

    <button type="button"><i class="material-icons">menu</i></button>

    </div>

    <div class="menu">

    <div class="row">

    <div class="col-lg overlay hidden">

    <h1>Elysium</h1>

    <div class="nav">

    <ul>

    <li><div class="logo"></div></li>

    <li><a href="../../part 1/relevant.html">Home</a></li>

    <li><a href="../../part 2/roadview.html">Road view</a></li>

    <li><a href="../../part 2/overview.html">Over view</a></li>

    <li><a href="../../part 2/postview.html">Post view</a></li>

    <li><a href="../../part 2/about.html">About</a></li>

    </ul>

    </div>

    </div>

    </div>

    </div>

    </div>

    <div id="roadview-container">

    <div class="enlarged-image-container"></div>

    <div class="information-container"></div>

    </div>

    <script type="text/javascript">

    var t1 = new TimelineMax({paused: true});

    t1.to(".overlay", 1, {

    opacity: 1,

    ease: Expo.easeInOut

    });

    t1.staggerFrom(".menu ul li", 0.8, {y: 60, opacity: 0, ease: Expo.easeOut}, 0.1);

    t1.reverse();

    $(document).on("click", ".menu-btn", function() {

    t1.reversed(!t1.reversed());

    if (t1.reversed()){

    $(".overlay").addClass("hidden");

    $("body").css("overflow", "auto");

    } else {

    $(".overlay").removeClass("hidden");

    $("body").css("overflow", "hidden");

    }

    });

    </script>

    <script type="module" src="roadview.js"></script>

    </body>

    </html>

  • import * as THREE from 'https://cdnjs.cloudflare.com/ajax/libs/three.js/r132/three.module.js';

    // Create a scene

    var scene = new THREE.Scene();

    // Create a camera

    var camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);

    camera.position.set(0, 0, 0);

    // Create a renderer

    var renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true });

    renderer.setSize(window.innerWidth, window.innerHeight);

    renderer.setClearColor(0xffffff, 1);

    document.getElementById('roadview-container').appendChild(renderer.domElement);

    // Update renderer size when the window is resized

    window.addEventListener('resize', function () {

    camera.aspect = window.innerWidth / window.innerHeight;

    camera.updateProjectionMatrix();

    renderer.setSize(window.innerWidth, window.innerHeight);

    });

    // Define the road parameters

    var roadRadius = 10;

    var roadSegments = 360;

    var roadWidth = 8;

    var laneWidth = 2;

    var shoulderWidth = (roadWidth - laneWidth * 2) / 2;

    // Define the road points

    var roadPoints = [];

    for (var i = 0; i <= roadSegments; i++) {

    var angle = (i / roadSegments) * Math.PI * 2;

    // Outer shoulder point

    var x = Math.cos(angle) * (roadRadius + shoulderWidth);

    var z = Math.sin(angle) * (roadRadius + shoulderWidth);

    var point = new THREE.Vector3(x, 0, z);

    roadPoints.push(point);

    // Outer lane point

    x = Math.cos(angle) * (roadRadius + shoulderWidth - laneWidth);

    z = Math.sin(angle) * (roadRadius + shoulderWidth - laneWidth);

    point = new THREE.Vector3(x, 0, z);

    roadPoints.push(point);

    // Inner lane point

    x = Math.cos(angle) * (roadRadius - shoulderWidth + laneWidth);

    z = Math.sin(angle) * (roadRadius - shoulderWidth + laneWidth);

    point = new THREE.Vector3(x, 0, z);

    roadPoints.push(point);

    // Inner shoulder point

    x = Math.cos(angle) * (roadRadius - shoulderWidth);

    z = Math.sin(angle) * (roadRadius - shoulderWidth);

    point = new THREE.Vector3(x, 0, z);

    roadPoints.push(point);

    }

    // Create the road geometry

    var roadGeometry = new THREE.BufferGeometry().setFromPoints(roadPoints);

    // Create the road material

    var roadMaterial = new THREE.LineDashedMaterial({

    color: 0x000000,

    linewidth: 1,

    dashSize: 0.1,

    gapSize: 0.1,

    });

    // Create the road mesh

    var road = new THREE.LineSegments(roadGeometry, roadMaterial);

    scene.add(road);

    // Animation variables

    var targetX = Math.cos(Math.PI / 4) * roadRadius;

    var targetY = 5 - Math.sin(Math.PI / 4) * 5;

    var targetZ = roadRadius + 5 - Math.sin(Math.PI / 4) * 5;

    var animationProgress = 0;

    // Load the images from the user story folder

    var loader = new THREE.TextureLoader();

    var texturePromises = [];

    var imageNames = [

    "Childhood",

    "Teenager",

    "Highschool",

    "University-1",

    "Marriage",

    "Family life-1",

    "Restart-1",

    "ill-1",

    "Friend-1",

    "Book cover"

    ];

    var images = [];

    var imageCount = imageNames.length;

    for (var i = 0; i < imageCount; i++) {

    var texturePromise = new Promise((resolve, reject) => {

    loader.load(`../../part 2/User story/${i + 1}/${imageNames[i]}.png`, resolve, undefined, reject);

    });

    texturePromises.push(texturePromise);

    }

    Promise.all(texturePromises)

    .then((textures) => {

    for (var i = 0; i < imageCount; i++) {

    // Create an image container element

    var imageContainer = document.createElement('div');

    imageContainer.classList.add('image-container');

    imageContainer.style.position = 'absolute';

    imageContainer.style.width = '300px';

    imageContainer.style.height = 'auto';

    imageContainer.style.transformOrigin = 'center';

    imageContainer.style.transformStyle = 'preserve-3d';

    imageContainer.style.transition = 'transform 0.3s ease-in-out';

    imageContainer.style.opacity = '0';

    // Create an image element

    var image = document.createElement('img');

    image.src = textures[i].image.src;

    image.style.width = '100%';

    image.style.height = '100%';

    image.style.objectFit = 'contain';

    // Create a text intro element

    var textIntro = document.createElement('div');

    textIntro.textContent = imageNames[i];

    textIntro.style.position = 'absolute';

    textIntro.style.top = '10px';

    textIntro.style.left = '10px';

    textIntro.style.color = '#ffffff';

    textIntro.style.fontFamily = 'Arial, sans-serif';

    textIntro.style.fontSize = '14px';

    textIntro.style.opacity = '0';

    textIntro.style.transition = 'opacity 0.3s ease-in-out';

    // Add event listener to image container

    imageContainer.addEventListener('click', function () {

    if (this.style.transform === 'scale(1.0)') {

    this.style.transform = 'scale(1.5)';

    textIntro.style.opacity = '1';

    } else {

    this.style.transform = 'scale(1.0)';

    textIntro.style.opacity = '0';

    }

    });

    // Append image and text intro to image container

    imageContainer.appendChild(image);

    imageContainer.appendChild(textIntro);

    // Append image container to the roadview container

    document.getElementById('roadview-container').appendChild(imageContainer);

    images.push(imageContainer);

    }

    })

    .catch((error) => {

    console.error('Error loading textures:', error);

    });

    // Add interactivity with mouse or touch events

    var isUserInteracting = false;

    var mouse = new THREE.Vector2();

    function onPointerDown(event) {

    event.preventDefault();

    isUserInteracting = true;

    if (event.touches) {

    mouse.x = (event.touches[0].clientX / window.innerWidth) * 2 - 1;

    mouse.y = -(event.touches[0].clientY / window.innerHeight) * 2 + 1;

    } else {

    mouse.x = (event.clientX / window.innerWidth) * 2 - 1;

    mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;

    }

    }

    function onPointerMove(event) {

    if (isUserInteracting) {

    if (event.touches) {

    mouse.x = (event.touches[0].clientX / window.innerWidth) * 2 - 1;

    mouse.y = -(event.touches[0].clientY / window.innerHeight) * 2 + 1;

    } else {

    mouse.x = (event.clientX / window.innerWidth) * 2 - 1;

    mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;

    }

    // Update the total rotation based on mouse movement

    var currentRotation = Math.atan2(camera.position.x, camera.position.z);

    var previousRotation = Math.atan2(camera.position.x - mouse.x, camera.position.z - mouse.y);

    // Calculate the difference in rotation

    var rotationDelta = previousRotation - currentRotation;

    var rotationSpeed = 0.001;

    totalRotation -= rotationDelta * rotationSpeed;

    // Adjust the total rotation angle

    var rotationSensitivity = 0.005;

    var rotationSpeed = 0.01;

    // Update the total rotation based on mouse movement and rotation speed

    totalRotation -= rotationDelta * rotationSensitivity * rotationSpeed;

    // Update the image index based on rotation direction

    if (rotationDelta > 0) {

    // Rotating from right to left (anticlockwise)

    imageIndex = (imageIndex + 1) % imageCount;

    } else {

    // Rotating from left to right (clockwise)

    imageIndex = (imageIndex - 1 + imageCount) % imageCount;

    }

    // Reset the image opacity

    for (var i = 0; i < imageCount; i++) {

    if (i === imageIndex) {

    images[i].style.opacity = '1';

    } else {

    images[i].style.opacity = '0';

    }

    }

    clearTimeout(imageTimeout);

    imageTimeout = setTimeout(showNextImage, imageDuration);

    }

    }

    function onPointerUp() {

    isUserInteracting = false;

    }

    function onScroll(event) {

    // Update camera position based on scroll

    var delta = Math.max(-1, Math.min(1, event.wheelDelta || -event.detail));

    camera.position.y += delta * 0.1;

    // Check if the viewer has interacted before showing the images

    if (viewerInteracted) {

    clearTimeout(imageTimeout);

    imageTimeout = setTimeout(showNextImage, imageDuration);

    }

    }

    document.addEventListener('mousedown', onPointerDown, { passive: false });

    document.addEventListener('mousemove', onPointerMove, { passive: false });

    document.addEventListener('mouseup', onPointerUp, { passive: false });

    document.addEventListener('touchstart', onPointerDown, { passive: false });

    document.addEventListener('touchmove', onPointerMove, { passive: false });

    document.addEventListener('touchend', onPointerUp, { passive: false });

    document.addEventListener('wheel', onScroll, { passive: false });

    // Animation and Image Visibility

    var imageIndex = imageCount - 1;

    var imageTimeout = null;

    var imageDuration = 10000;

    var viewerInteracted = false;

    // Constants for rotation threshold and total rotation angle

    var rotationThreshold = (Math.PI * 2) / (imageCount * 4);

    var totalRotation = 0;

    function showNextImage() {

    if (images.length === 0) return;

    images[imageIndex].style.opacity = '0';

    // Calculate the current image index based on total rotation

    var normalizedRotation = totalRotation < 0 ? totalRotation % (-2 * Math.PI) + 2 * Math.PI : totalRotation % (2 * Math.PI);

    imageIndex = Math.floor(normalizedRotation / rotationThreshold);

    images[imageIndex].style.opacity = '1';

    if (isUserInteracting) {

    clearTimeout(imageTimeout);

    imageTimeout = setTimeout(showNextImage, getTransitionDuration());

    } else {

    clearTimeout(imageTimeout);

    }

    }

    function getTransitionDuration() {

    var rotationSpeed = Math.abs(rotationDelta);

    // Adjust the transition duration based on the rotation speed

    var minDuration = 1000;

    var maxDuration = 5000;

    // Calculate the transition duration based on the rotation speed

    var transitionDuration = mapValue(rotationSpeed, 0, Math.PI / 4, maxDuration, minDuration);

    // Adjust the transition duration to ensure a minimum duration for each image

    var minImageDuration = 2000;

    var imageDuration = imageDuration / imageCount;

    transitionDuration = Math.max(transitionDuration, minImageDuration, imageDuration);

    return transitionDuration;

    }

    function mapValue(value, inMin, inMax, outMin, outMax) {

    return ((value - inMin) * (outMax - outMin)) / (inMax - inMin) + outMin;

    }

    function rotateToNextImage() {

    if (isUserInteracting) {

    showNextImage();

    }

    }

    // Disable image visibility initially

    function hideImages() {

    for (var i = 0; i < images.length; i++) {

    images[i].style.opacity = '0';

    }

    }

    hideImages();

    // Variables for interactive behavior

    var viewerStarted = false;

    // Add event listener to detect viewer interaction

    document.addEventListener('mousedown', function () {

    viewerStarted = true;

    });

    document.addEventListener('mousemove', function () {

    if (!viewerInteracted && viewerStarted) {

    viewerInteracted = true;

    startImageTransition();

    }

    });

    document.addEventListener('mouseup', function () {

    viewerStarted = false;

    });

    document.addEventListener('touchstart', function () {

    viewerStarted = true;

    });

    document.addEventListener('touchmove', function () {

    if (!viewerInteracted && viewerStarted) {

    viewerInteracted = true;

    startImageTransition();

    }

    });

    document.addEventListener('touchend', function () {

    viewerStarted = false;

    });

    // Start the image transition after viewer interaction

    function startImageTransition() {

    clearTimeout(imageTimeout);

    imageTimeout = setTimeout(showNextImage, imageDuration);

    }

    animate();

    // Start the image transition after a delay

    setTimeout(function () {

    if (viewerInteracted) {

    startImageTransition();

    }

    }, 5000);

    function positionImages() {

    var centerX = targetX;

    var centerY = targetY;

    var centerZ = targetZ;

    var distance = 1000;

    var offsetY = -125;

    var offsetX = -115;

    var lastImageScale = 0.9;

    for (var i = 0; i < imageCount; i++) {

    var angle = (i / imageCount) * Math.PI * 2;

    var x = Math.cos(angle) * roadRadius + centerX + offsetX;

    var y = centerY + offsetY;

    var z = Math.sin(angle) * roadRadius + centerZ;

    var imageContainer = images[i];

    imageContainer.style.position = 'absolute';

    imageContainer.style.left = `calc(50% + ${x}px - 50px)`;

    imageContainer.style.zIndex = 1000 - i;

    if (i === imageCount - 1) {

    // Adjust the position and scale for the last image

    var lastImageOffsetY = -200;

    imageContainer.style.top = `calc(50% + ${y + lastImageOffsetY}px - 50px)`;

    imageContainer.style.transform = `translate3d(0, 0, ${distance}px) scale(${lastImageScale})`;

    } else {

    // Keep the position and scale the same for the other images

    var otherImageScale = 2;

    imageContainer.style.top = `calc(50% + ${y}px - 50px)`;

    imageContainer.style.transform = `translate3d(0, 0, ${distance}px) scale(${otherImageScale})`;

    }

    }

    }

    function animate() {

    requestAnimationFrame(animate);

    // Animation

    if (animationProgress < 1) {

    animationProgress += 0.0005;

    // Interpolate camera position

    camera.position.x = (1 - animationProgress) * 0 + animationProgress * targetX;

    camera.position.y = (1 - animationProgress) * 100 + animationProgress * targetY;

    camera.position.z = (1 - animationProgress) * -200 + animationProgress * targetZ;

    camera.lookAt(scene.position);

    } else {

    // Enable user interaction when animation ends

    if (isUserInteracting) {

    // Rotate the camera based on mouse position

    camera.position.x = Math.sin(mouse.x * Math.PI * 2) * (roadRadius + 1);

    camera.position.z = Math.cos(mouse.x * Math.PI * 2) * (roadRadius + 1);

    camera.lookAt(scene.position);

    } else {

    // Position the images at the center of the annulus

    positionImages();

    }

    }

    setTimeout(function() {

    renderer.render(scene, camera);

    }, 100);

    }

    // Remove the automatic image transition

    clearTimeout(imageTimeout);

    // Start the image transition only after viewer interaction

    document.addEventListener('click', function () {

    if (!viewerInteracted) {

    viewerInteracted = true;

    startImageTransition();

    }

    });

    animate();

  • html, body {

    margin: 0;

    padding: 0;

    overflow: hidden;

    background-color: #F2F2F2;

    }

    #roadview-container {

    position: fixed;

    top: 0;

    left: 0;

    width: 100vw;

    height: 100vh;

    z-index: 0;

    }

    #roadview-container .image-container {

    position: absolute;

    width: 300px;

    height: auto;

    transform-origin: center;

    transform-style: preserve-3d;

    transition: transform 0.3s ease-in-out;

    opacity: 0;

    z-index: 0;

    }

    #roadview-container .image-container img {

    width: 100%;

    height: 100%;

    object-fit: contain;

    }

    .enlarged-image-container {

    position: absolute;

    top: 50%;

    left: 50%;

    transform: translate(-50%, -50%);

    width: 80%;

    height: 80%;

    background-size: contain;

    background-position: center;

    background-repeat: no-repeat;

    display: none;

    z-index: 1;

    }

    .information-container {

    position: absolute;

    top: 50%;

    left: 50%;

    transform: translate(-50%, -50%);

    text-align: center;

    width: 300px;

    z-index: 1;

    }

    .menu-btn {

    padding-right: 25.5px;

    }

Over View

Transitioning to the Over View, I envisioned a bird's eye perspective of the same path. This top-down view offers a comprehensive overview, showcasing all the pivotal points along the life journey. Hovering over these points reveals the associated images, providing a broader context to the life story being explored. This view serves as a reflective tool, allowing users to see the breadth of a life’s experiences at a glance, emphasizing the interconnectedness of different life events and how they shape an individual's narrative.

当切换到俯瞰视角时,我想象中的是同一路径的鸟瞰图。这个从上而下的视角提供了一个全面的概览,展示了生命旅程中所有的关键点。悬停在这些点上会显示相关的图像,为正在探索的生命故事提供了更广阔的背景。这个视角是一个反思工具,允许用户一瞥就能看到一个人生经历的宽度,强调不同生活事件的互联性以及它们如何塑造个人的故事。

  • <!DOCTYPE html>

    <html lang="en">

    <head>

    <meta charset="UTF-8">

    <meta name="viewport" content="width=device-width, initial-scale=1.0">

    <title>Elysium-overview</title>

    <link rel="stylesheet" href="overview.css">

    <link rel="stylesheet" href="../../part 2/button.css">

    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css">

    <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/js/bootstrap.min.js"></script>

    <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/js/bootstrap.bundle.min.js"></script>

    <link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">

    <script src="https://code.jquery.com/jquery-3.3.1.js"></script>

    <script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/2.0.2/TweenMax.min.js"></script>

    </head>

    <body>

    <div class="wrapper">

    <div class="menu-btn">

    <button type="button"><i class="material-icons">menu</i></button>

    </div>

    <div class="menu">

    <div class="row">

    <div class="col-lg overlay hidden">

    <h1>Elysium</h1>

    <div class="nav">

    <ul>

    <li><div class="logo"></div></li>

    <li><a href="../../part 1/relevant.html">Home</a></li>

    <li><a href="../../part 2/roadview.html">Road view</a></li>

    <li><a href="../../part 2/overview.html">Over view</a></li>

    <li><a href="../../part 2/postview.html">Post view</a></li>

    <li><a href="../../part 2/about.html">About</a></li>

    </ul>

    </div>

    </div>

    </div>

    </div>

    </div>

    <div id="overview-container">

    <div id="hover-container" style="display: none; position: absolute;">

    <img id="hover-image" src="" alt="Image" style="width: 100px; height: auto;">

    <p id="hover-text" style="color: black; font-size: 14px;"></p>

    </div>

    </div>

    <div id="large-image-container"></div>

    <script type="text/javascript">

    var t1 = new TimelineMax({paused: true});

    t1.to(".overlay", 1, {

    opacity: 1,

    ease: Expo.easeInOut

    });

    t1.staggerFrom(".menu ul li", 0.8, {y: 60, opacity: 0, ease: Expo.easeOut}, 0.1);

    t1.reverse();

    $(document).on("click", ".menu-btn", function() {

    t1.reversed(!t1.reversed());

    if (t1.reversed()){

    $(".overlay").addClass("hidden");

    $("body").css("overflow", "auto");

    } else {

    $(".overlay").removeClass("hidden");

    $("body").css("overflow", "hidden");

    }

    });

    </script>

    <script src="https://cdnjs.cloudflare.com/ajax/libs/tween.js/18.6.4/tween.umd.js"></script>

    <script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r132/three.min.js"></script>

    <script type="module" src="overview.js"></script>

    </body>

    </html>

  • import * as THREE from 'https://cdnjs.cloudflare.com/ajax/libs/three.js/r132/three.module.js';

    // Create a scene

    var scene = new THREE.Scene();

    // Create a camera

    var camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);

    camera.position.set(0, 500, 0);

    camera.lookAt(scene.position);

    // Create a renderer

    var renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true });

    renderer.setSize(window.innerWidth, window.innerHeight);

    renderer.setClearColor(0xffffff, 1);

    document.getElementById('overview-container').appendChild(renderer.domElement);

    // Define the road parameters

    var roadRadius = 200;

    var roadSegments = 360;

    var laneWidth = 20;

    var shoulderWidth = 20;

    // Define the road points

    var roadPoints = [];

    for (var i = 0; i <= roadSegments; i++) {

    var angle = (i / roadSegments) * Math.PI * 2;

    // Outer shoulder point

    var x = Math.cos(angle) * (roadRadius + shoulderWidth);

    var y = Math.sin(angle) * (roadRadius + shoulderWidth);

    var point = new THREE.Vector3(x, 0, y);

    roadPoints.push(point);

    // Outer lane point

    x = Math.cos(angle) * (roadRadius + shoulderWidth - laneWidth);

    y = Math.sin(angle) * (roadRadius + shoulderWidth - laneWidth);

    point = new THREE.Vector3(x, 0, y);

    roadPoints.push(point);

    // Inner lane point

    x = Math.cos(angle) * (roadRadius - shoulderWidth + laneWidth);

    y = Math.sin(angle) * (roadRadius - shoulderWidth + laneWidth);

    point = new THREE.Vector3(x, 0, y);

    roadPoints.push(point);

    // Inner shoulder point

    x = Math.cos(angle) * (roadRadius - shoulderWidth);

    y = Math.sin(angle) * (roadRadius - shoulderWidth);

    point = new THREE.Vector3(x, 0, y);

    roadPoints.push(point);

    }

    // Create the road geometry

    var roadGeometry = new THREE.BufferGeometry().setFromPoints(roadPoints);

    // Create the road material

    var roadMaterial = new THREE.LineBasicMaterial({ color: 0x000000, transparent: true, opacity: 0 });

    // Create the road mesh

    var road = new THREE.Line(roadGeometry, roadMaterial);

    scene.add(road);

    // Fade in the road

    var roadOpacityTween = new TWEEN.Tween(roadMaterial)

    .to({ opacity: 1 }, 4000)

    .onUpdate(function () {

    roadMaterial.needsUpdate = true;

    });

    // Define the image parameters

    var imageCount = 10;

    var imageRadius = roadRadius + 50;

    // Load the images

    var loader = new THREE.TextureLoader();

    var imagePromises = [];

    var imageNames = [

    'Childhood.png',

    'Teenager.png',

    'Highschool.png',

    'University-1.png',

    'Marriage.png',

    'Family life-1.png',

    'Restart-1.png',

    'ill-1.png',

    'Friend-1.png',

    'Book cover.png'

    ];

    for (var i = 0; i < imageCount; i++) {

    var imagePromise = new Promise((resolve, reject) => {

    loader.load(`../../part 2/User story/${i + 1}/${imageNames[i]}`, resolve, undefined, reject);

    });

    imagePromises.push(imagePromise);

    }

    Promise.all(imagePromises)

    .then((textures) => {

    for (var i = 0; i < imageCount; i++) {

    var angle = (i / imageCount) * Math.PI * 2;

    // Calculate image position on the circle

    var x = Math.cos(angle) * imageRadius;

    var y = Math.sin(angle) * imageRadius;

    // Create a container for dot and image

    var container = document.createElement('div');

    container.classList.add('dot-container');

    // Create a waving dot element

    var dot = document.createElement('div');

    dot.classList.add('waving-dot');

    dot.style.left = `calc(50% + ${x}px)`;

    dot.style.top = `calc(50% + ${y}px)`;

    // Create a new scope for the event listeners

    (function (index) {

    // Add mouseover event listener to the dot

    dot.addEventListener('mouseover', function (event) {

    showHoverImage(index, event);

    });

    // Add mouseout event listener to the dot

    dot.addEventListener('mouseout', function () {

    hideHoverImage();

    });

    // Add click event listener to the dot

    dot.addEventListener('click', function () {

    showImage(index);

    });

    })(i);

    // Append the dot to the container

    container.appendChild(dot);

    // Append the container to the overview container

    document.getElementById('overview-container').appendChild(container);

    // Create an image container element

    var imageContainer = document.createElement('div');

    imageContainer.classList.add('image-container');

    // Create an image element

    var image = document.createElement('img');

    image.src = `../../part 2/User story/${i + 1}/${imageNames[i]}`;

    // Append the image to the image container

    imageContainer.appendChild(image);

    // Append the image container to the overview container

    document.getElementById('overview-container').appendChild(imageContainer);

    }

    // Start the road fade-in animation after the dots have been created

    roadOpacityTween.start();

    })

    .catch((error) => {

    console.error('Error loading images:', error);

    });

    // Function to show the hover image and text

    function showHoverImage(index, event) {

    // Get the hover container and image elements

    var hoverContainer = document.getElementById('hover-container');

    var hoverImage = document.getElementById('hover-image');

    // Set the source of the hover image to the image corresponding to the index

    hoverImage.src = `../../part 2/User story/${index + 1}/${imageNames[index]}`;

    // Add a load event listener to the hover image

    hoverImage.addEventListener('load', function () {

    // Set the position of the hover container to the position of the mouse cursor

    // Subtract half the width and height of the image to center the image on the cursor

    hoverContainer.style.left = `${event.clientX - hoverImage.offsetWidth / 2}px`;

    hoverContainer.style.top = `${event.clientY - hoverImage.offsetHeight / 2}px`;

    // Show the hover container

    hoverContainer.style.display = 'block';

    });

    }

    // Function to hide the hover image and text

    function hideHoverImage() {

    // Get the hover container element

    var hoverContainer = document.getElementById('hover-container');

    // Hide the hover container

    hoverContainer.style.display = 'none';

    }

    // Function to show the image with text

    function showImage(index) {

    // Get the corresponding image container by index

    var imageContainers = document.getElementsByClassName('image-container');

    var imageContainer = imageContainers[index];

    // Hide all image containers

    for (var i = 0; i < imageContainers.length; i++) {

    imageContainers[i].classList.remove('show');

    }

    // Show the selected image container

    imageContainer.classList.add('show');

    }

    // Manual rotation of the road

    var rotationSpeed = 0.001;

    function animate() {

    requestAnimationFrame(animate);

    // Rotate the road

    road.rotation.y += rotationSpeed;

    // Update tween animations

    TWEEN.update();

    renderer.render(scene, camera);

    }

    animate();

  • body {

    overflow: hidden;

    }

    #overview-container {

    position: relative;

    width: 100vw;

    height: 100vh;

    overflow: hidden;

    background-color: #ffffff;

    }

    .waving-dot {

    position: absolute;

    width: 10px;

    height: 10px;

    background-color: lightblue;

    border-radius: 50%;

    opacity: 0.7;

    animation: waving 2s infinite ease-in-out;

    }

    @keyframes waving {

    0% {

    transform: translateY(-2px);

    }

    50% {

    transform: translateY(2px);

    }

    100% {

    transform: translateY(-2px);

    }

    }

    .image-container {

    position: absolute;

    width: 300px;

    height: auto;

    transform-origin: center;

    transform-style: preserve-3d;

    transition: transform 0.3s ease-in-out, opacity 0.3s ease-in-out;

    opacity: 0;

    }

    .image-container.show {

    opacity: 1;

    transform: scale(1.5);

    transition: transform 0.3s ease-in-out, opacity 0.3s ease-in-out;

    }

    .image-container img {

    width: 100%;

    height: 100%;

    object-fit: contain;

    }

    .image-container .text-intro {

    position: absolute;

    top: 10px;

    left: 10px;

    color: #ffffff;

    font-family: Arial, sans-serif;

    font-size: 14px;

    opacity: 0;

    transition: opacity 0.3s ease-in-out;

    }

    .fade-in {

    opacity: 0;

    transition: opacity 2s;

    }

    .show-road {

    opacity: 1;

    }

    #hover-container {

    position: absolute;

    pointer-events: none;

    z-index: 200;

    }

    .hover-image {

    width: 240px;

    height: 240px;

    object-fit: contain;

    }

    .menu-btn {

    padding-right: 25.5px;

    }

Post View

In the Post View, users encounter a simple, scrollable sequence of images laid out in a circular format. This design fosters a meditative interaction, guiding users along a flowing narrative of memories. It’s a quieter, more reflective way to engage, offering a steady stream of moments for thoughtful remembrance.


在帖子视图中,用户会看到一个简洁的、可滚动的图像序列,呈现在一个圆形的布局中。这种设计鼓励了一种冥想式的互动,引导用户沿着一条流动的记忆叙事线前进。这是一种更为静谧、深思的互动方式,提供了一连串平静的时刻,供用户缓慢地回忆与思考。

  • <!DOCTYPE html>

    <html lang="en">

    <head>

    <meta charset="UTF-8">

    <meta http-equiv="X-UA-Compatible" content="IE=edge">

    <meta name="viewport" content="width=device-width, initial-scale=1.0">

    <title>Elysium-post view</title>

    <link rel="stylesheet" href="../../part 2/button.css">

    <link rel="stylesheet" href="../../part 2/postview.css">

    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css">

    <link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">

    <script src="https://unpkg.com/gsap@3/dist/gsap.min.js"></script>

    <script src="https://unpkg.com/gsap@3/dist/ScrollTrigger.min.js"></script>

    <script src="https://unpkg.com/gsap@3/dist/MotionPathPlugin.min.js"></script>

    <script src="https://assets.codepen.io/16327/Flip.min.js"></script>

    <script src="https://code.jquery.com/jquery-3.3.1.js"></script>

    </head>

    <body>

    <div class="wrapper">

    <div class="menu-btn">

    <button type="button"><i class="material-icons">menu</i></button>

    </div>

    <div class="menu">

    <div class="row">

    <div class="col-lg overlay hidden">

    <h1>Elysium</h1>

    <div class="nav">

    <ul>

    <li><div class="logo"></div></li>

    <li><a href="../../part 1/relevant.html" target="_parent">Home</a></li>

    <li><a href="../../part 2/roadview.html" target="_parent">Road view</a></li>

    <li><a href="../../part 2/overview.html" target="_parent">Over view</a></li>

    <li><a href="../../part 2/postview.html" target="_parent">Post view</a></li>

    <li><a href="../../part 2/about.html" target="_parent">About</a></li>

    </ul>

    </div>

    </div>

    </div>

    </div>

    </div>

    <div class="header">

    <h1>

    Eliza Sullivan's, <br />

    life Moments

    </h1>

    </div>

    <section class="slider-section">

    <div class="wheel">

    <div class="wheel__card">

    <img src="../../part 2/User story/1/Childhood.png" alt="Childhood">

    </div>

    <div class="wheel__card">

    <img src="../../part 2/User story/2/Teenager.png" alt="Teenager">

    </div>

    <div class="wheel__card">

    <img src="../../part 2/User story/3/Highschool.png" alt="Highschool">

    </div>

    <div class="wheel__card">

    <img src="../../part 2/User story/4/University-1.png" alt="University-1">

    </div>

    <div class="wheel__card">

    <img src="../../part 2/User story/5/Marriage.png" alt="Marriage">

    </div>

    <div class="wheel__card">

    <img src="../../part 2/User story/6/Family life-1.png" alt="Family life-1">

    </div>

    <div class="wheel__card">

    <img src="../../part 2/User story/7/Restart-1.png" alt="Restart-1">

    </div>

    <div class="wheel__card">

    <img src="../../part 2/User story/8/ill-1.png" alt="ill-1">

    </div>

    <div class="wheel__card">

    <img src="../../part 2/User story/9/Friend-1.png" alt="Friend-1">

    </div>

    <div class="wheel__card">

    <img src="../../part 2/User story/10/Book cover.png" alt="Book cover">

    </div>

    </section>

    <div class="scroll-down">Scroll to view</div>

    <div class="scroll-down-icon">

    <img

    src="https://storage.googleapis.com/studio-design-asset-files/projects/BXaxK3jMq7/s-61x9_2c6bd15e-43e5-4ebf-bf39-a6ff23fb93dd.svg"

    alt=""

    />

    </div>

    <script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/2.0.2/TweenMax.min.js"></script>

    <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/js/bootstrap.min.js"></script>

    <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/js/bootstrap.bundle.min.js"></script>

    <script>

    var t1 = new TimelineMax({ paused: true });

    t1.to(".overlay", 1, {

    opacity: 1,

    ease: Expo.easeInOut

    });

    t1.staggerFrom(".menu ul li", 0.8, { y: 60, opacity: 0, ease: Expo.easeOut }, 0.1);

    t1.reverse();

    $(document).on("click", ".menu-btn", function () {

    t1.reversed(!t1.reversed());

    if (t1.reversed()) {

    $(".overlay").addClass("hidden");

    $("body").css("overflow", "auto");

    } else {

    $(".overlay").removeClass("hidden");

    $("body").css("overflow", "hidden");

    }

    });

    </script>

    <script>

    gsap.registerPlugin("ScrollTrigger");

    let wheel = document.querySelector(".wheel");

    let images = gsap.utils.toArray(".wheel__card");

    function setup() {

    let radius = wheel.offsetWidth / 2;

    let center = wheel.offsetWidth / 2;

    let total = images.length;

    let slice = (2 * Math.PI) / total;

    images.forEach((item, i) => {

    let angle = i * slice;

    let x = center + radius * Math.sin(angle);

    let y = center - radius * Math.cos(angle);

    gsap.set(item, {

    rotation: angle + "_rad",

    xPercent: -50,

    yPercent: -50,

    x: x,

    y: y,

    });

    });

    }

    gsap.to(".wheel", {

    rotate: () => -360,

    ease: "none",

    duration: images.length,

    scrollTrigger: {

    start: 0,

    end: "max",

    scrub: 1,

    snap: 1 / images.length,

    invalidateOnRefresh: true,

    },

    });

    setup();

    window.addEventListener("resize", setup);

    </script>

    </body>

    </html>

  • // Get the button and images container elements

    const button = document.querySelector("button");

    const imagesContainer = document.querySelector(".images");

    // Toggle class on button click

    button.addEventListener("click", () => {

    imagesContainer.classList.toggle("show-all");

    });

    // Add waving effect to the images

    const images = document.querySelectorAll(".img");

    images.forEach((image) => {

    image.addEventListener("mouseover", () => {

    image.classList.add("waving");

    });

    image.addEventListener("mouseout", () => {

    image.classList.remove("waving");

    });

    });

  • body {

    padding: 0;

    margin: 0;

    height: 600vh;

    width: 100vw;

    background: #ffffff;

    color: #000;

    scrollbar-width: thin;

    scrollbar-color: transparent transparent;

    }

    body::-webkit-scrollbar {

    width: 6px;

    }

    body::-webkit-scrollbar-track {

    background: transparent;

    }

    body::-webkit-scrollbar-thumb {

    background: transparent;

    }

    .header {

    position: fixed;

    top: 0;

    left: 0;

    width: 100%;

    height: 55vh;

    display: flex;

    align-items: center;

    justify-content: center;

    cursor: pointer;

    }

    .header h1 {

    font-size: 5.5vw;

    font-family: "Neue World Ultralight";

    font-weight: lighter;

    text-align: center;

    }

    .slider-section {

    height: 22vh;

    bottom: 0;

    position: fixed;

    width: 100%;

    }

    .wheel {

    position: absolute;

    top: -55%;

    left: 47%;

    transform: translateX(-50%);

    display: flex;

    align-items: center;

    justify-content: center;

    width: 300vw;

    height: 300vw;

    max-width: 2000px;

    max-height: 2000px;

    }

    .wheel__card {

    position: absolute;

    top: 0;

    left: 0;

    width: 6%;

    max-width: 200px;

    aspect-ratio: 1 / 1;

    cursor: pointer;

    }

    img {

    width: 100%;

    pointer-events: none;

    z-index: 999;

    cursor: pointer;

    }

    .wheel__card:not(.special-image) img {

    width: 200%;

    height: 125%;

    object-fit: cover;

    object-position: center center;

    }

    .scroll-down-icon {

    position: fixed;

    top: 4em;

    right: 2em;

    transform: rotate(90deg);

    }

    .scroll-down-icon img {

    width: 50px;

    }

    .scroll-down {

    font-family: "Neue World Ultralight";

    position: fixed;

    top: 3em;

    left: 2em;

    color: #000;

    font-weight: 400;

    text-transform: uppercase;

    font-size: 20px;

    overflow: visible;

    }

    .menu-btn {

    padding-right: 25.5px;

    }

Loading - check the programming

  • <!DOCTYPE html>

    <html>

    <head>

    <title>Elysium-loading Page</title>

    <style>

    body {

    margin: 0;

    padding: 0;

    display: flex;

    justify-content: center;

    align-items: center;

    height: 100vh;

    background: linear-gradient(45deg, #4F96EC, #FFFFFF);

    color: #000000;

    font-family: Arial, sans-serif;

    font-size: 3em;

    }

    #counter {

    position: relative;

    display: flex;

    align-items: center;

    justify-content: center;

    }

    #counterNumber {

    position: absolute;

    z-index: 2;

    }

    .circle {

    width: 200px;

    height: 200px;

    border-radius: 50%;

    stroke: #000;

    fill: transparent;

    stroke-width: 1;

    stroke-dasharray: 629;

    stroke-dashoffset: 629;

    animation: draw 5800ms linear forwards;

    animation-iteration-count: 1;

    transition: opacity 1s;

    }

    @keyframes draw {

    from {

    stroke-dashoffset: 629;

    }

    to {

    stroke-dashoffset: 0;

    }

    }

    </style>

    </head>

    <body>

    <div id="counter">

    <div id="counterNumber">100</div>

    <svg class="circle" viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">

    <circle cx="50" cy="50" r="49"></circle>

    </svg>

    </div>

    <script>

    var counterNumber = document.getElementById('counterNumber');

    var circle = document.querySelector('.circle');

    var count = 100;

    var countdown = setInterval(function() {

    count--;

    counterNumber.innerText = count;

    if(count <= 0) {

    clearInterval(countdown);

    counterNumber.style.color = "transparent";

    circle.style.opacity = 0;

    setTimeout(function() {

    window.location.href = 'homepage.html';

    }, 1000);

    }

    }, 25);

    </script>

    </body>

    </html>

Other Pages

Homepage - check the programming

  • <!DOCTYPE html>

    <html>

    <head>

    <title>Elysium-entrance</title>

    <style>

    body {

    margin: 0;

    overflow: hidden;

    background-color: #ffffff;

    display: flex;

    flex-direction: column;

    justify-content: center;

    align-items: center;

    height: 100vh;

    }

    #name {

    font-family: 'Lora', serif;

    font-size: 5em;

    color: rgba(0, 0, 0, 0);

    opacity: 0;

    animation: fade-in 4s forwards;

    text-align: center;

    margin-bottom: 50px;

    }

    @keyframes fade-in {

    from {

    color: rgba(0, 0, 0, 0);

    opacity: 0;

    }

    to {

    color: rgba(0, 0, 0, 1);

    opacity: 1;

    }

    }

    #buttons {

    display: flex;

    justify-content: center;

    align-items: center;

    opacity: 0;

    animation: fade-in 4s forwards;

    }

    .button {

    font-family: 'Lora', serif;

    font-size: 2em;

    color: #000000;

    background-color: transparent;

    border: none;

    border-radius: 0;

    padding: 10px 20px;

    margin: 10px;

    cursor: pointer;

    transition: background-color 0.3s, color 0.3s;

    text-decoration: none;

    border: 1px solid #000000;

    display: inline-block;

    }

    .button:hover {

    background-color: transparent;

    color: #000000;

    }

    #particles {

    width: 100%;

    height: 100vh;

    position: absolute;

    top: 0;

    left: 0;

    z-index: -1;

    }

    </style>

    <script src="https://threejs.org/build/three.js"></script>

    </head>

    <body>

    <div id="particles"></div>

    <div id="name">Elysium</div>

    <div id="buttons">

    <a href="relevant.html" class="button">Explore</a>

    <a href="relevant.html" class="button">Relevant</a>

    </div>

    <script>

    var scene = new THREE.Scene();

    var camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);

    var renderer = new THREE.WebGLRenderer({ alpha: true });

    renderer.setSize(window.innerWidth, window.innerHeight);

    document.getElementById('particles').appendChild(renderer.domElement);

    var geometry = new THREE.BufferGeometry();

    var vertices = [];

    var colors = [];

    var color = new THREE.Color();

    for (var i = 0; i < 20000; i++) {

    var x = THREE.MathUtils.randFloatSpread(2000);

    var y = THREE.MathUtils.randFloatSpread(2000);

    var z = THREE.MathUtils.randFloatSpread(2000);

    vertices.push(x, y, z);

    var hue = (x + 1000) / 2000;

    if (Math.random() < 0.8) {

    color.setHSL(hue, 0.7, 0.5);

    } else {

    color.setRGB(0, 0, 0);

    }

    colors.push(color.r, color.g, color.b);

    }

    geometry.setAttribute('position', new THREE.Float32BufferAttribute(vertices, 3));

    geometry.setAttribute('color', new THREE.Float32BufferAttribute(colors, 3));

    var material = new THREE.PointsMaterial({ size: 3, vertexColors: true, transparent: true, opacity: 0.6 });

    var particles = new THREE.Points(geometry, material);

    scene.add(particles);

    camera.position.z = 500;

    var mouseX = 0,

    mouseY = 0;

    var windowHalfX = window.innerWidth / 2;

    var windowHalfY = window.innerHeight / 2;

    document.addEventListener('mousemove', onDocumentMouseMove, false);

    function onDocumentMouseMove(event) {

    mouseX = (event.clientX - windowHalfX) / 500;

    mouseY = (event.clientY - windowHalfY) / 500;

    }

    var animate = function () {

    requestAnimationFrame(animate);

    particles.rotation.x += 0.0015 * mouseY;

    particles.rotation.y += 0.0015 * mouseX;

    renderer.render(scene, camera);

    };

    animate();

    </script>

    </body>

    </html>

Index - check the programming

  • <!DOCTYPE html>

    <html lang="en">

    <head>

    <meta charset="UTF-8" />

    <meta http-equiv="X-UA-Compatible" content="IE=edge" />

    <meta name="viewport" content="width=device-width, initial-scale=1.0" />

    <title>Elysium-home page</title>

    <link rel="stylesheet" href="../../part 1/relevant.css">

    <style>

    .menu__item-content {

    display: none;

    }

    .menu__item-content.active {

    display: block;

    position: absolute;

    top: 100%;

    left: 0;

    width: 100%;

    background-color: white;

    padding: 20px;

    box-shadow: 0px 2px 4px rgba(0, 0, 0, 0.1);

    }

    </style>

    <script src="https://unpkg.com/gsap@3/dist/gsap.min.js"></script>

    </head>

    <body>

    <div class="container">

    <nav class="menu">

    <div class="menu__item" id="roadviewMenuItem">

    <div class="menu__item-image_wrapper">

    <div class="menu__item-image_inner">

    <video class="menu__item-image" src="../../part 2/video/roadview.mp4" muted loop></video>

    </div>

    </div>

    <a class="menu__item-text" href="../../part 2/roadview.html">

    <span class="menu__item-innertext">Road view /</span>

    </a>

    <div class="menu__item-content" id="roadviewContent"></div>

    </div>

    <div class="menu__item">

    <div class="menu__item-image_wrapper">

    <div class="menu__item-image_inner">

    <video class="menu__item-image" src="../../part 2/video/overview.mp4" muted loop></video>

    </div>

    </div>

    <a class="menu__item-text" href="../../part 2/overview.html">

    <span class="menu__item-innertext">Over view</span>

    </a>

    <div class="menu__item-content" id="overviewContent"></div>

    </div>

    <br />

    <div class="menu__item">

    <div class="menu__item-image_wrapper">

    <div class="menu__item-image_inner">

    <video class="menu__item-image" src="../../part 2/video/postview.mp4" muted loop></video>

    </div>

    </div>

    <a class="menu__item-text" href="../../part 2/postview.html">

    <span class="menu__item-innertext">Post view /</span>

    </a>

    <div class="menu__item-content" id="postviewContent"></div>

    </div>

    <div class="menu__item">

    <div class="menu__item-image_wrapper">

    <div class="menu__item-image_inner">

    <video class="menu__item-image" src="../../part 2/video/about.mp4" muted loop></video>

    </div>

    </div>

    <a class="menu__item-text" href="../../part 2/about.html">

    <span class="menu__item-innertext">&nbsp;About</span>

    </a>

    <div class="menu__item-content" id="aboutContent"></div>

    </div>

    </nav>

    </div>

    <script src="relevant.js"></script>

    <script>

    function showSection(sectionId) {

    var sections = document.getElementsByClassName('menu__item-content');

    for (var i = 0; i < sections.length; i++) {

    sections[i].classList.remove('active');

    }

    var selectedSection = document.getElementById(sectionId + 'Content');

    selectedSection.classList.add('active');

    var menuButtons = document.querySelectorAll('.menu__item-text');

    for (var i = 0; i < menuButtons.length; i++) {

    menuButtons[i].style.color = '#a7a7a7';

    }

    var activeButton = document.querySelector('.menu__item-text[href="../../part 2/' + sectionId + '.html"]');

    activeButton.style.color = '#000000';

    }

    var menuItems = document.querySelectorAll('.menu__item');

    menuItems.forEach(function (item) {

    var itemText = item.querySelector('.menu__item-text');

    var sectionId = itemText.getAttribute('href').replace('.html', '').replace('../../part 2/', '');

    item.addEventListener('mouseenter', function () {

    itemText.style.color = '#000000';

    item.querySelector('.menu__item-image').play();

    });

    item.addEventListener('mouseleave', function () {

    itemText.style.color = '#a7a7a7';

    item.querySelector('.menu__item-image').pause();

    });

    item.addEventListener('click', function (event) {

    event.preventDefault();

    window.location.href = itemText.getAttribute('href');

    });

    });

    </script>

    </body>

    </html>

  • const { gsap } = window;

    gsap.timeline()

    .set(".menu", { autoAlpha: 1 })

    .from(".menu__item-innertext", {

    delay: 1,

    duration: 0.85,

    stagger: 0.095,

    skewY: gsap.utils.wrap([-8, 8]),

    ease: "expo.out",

    })

    .set(".menu", { pointerEvents: "all" });

    gsap.defaults({

    duration: 0.55,

    ease: "expo.out",

    });

    const menuItems = document.querySelectorAll(".menu__item");

    menuItems.forEach((item) => {

    const videoWrapper = item.querySelector(".menu__item-image_wrapper");

    const videoWrapperBounds = videoWrapper.getBoundingClientRect();

    let itemBounds = item.getBoundingClientRect();

    const onMouseEnter = () => {

    gsap.set(videoWrapper, {

    scale: 0.8,

    });

    gsap.to(videoWrapper, { opacity: 1, scale: 1 });

    };

    const onMouseLeave = () => {

    gsap.to(videoWrapper, {

    opacity: 0,

    scale: 0.2,

    });

    };

    const onMouseMove = ({ x, y }) => {

    let yOffset = itemBounds.top / videoWrapperBounds.height;

    yOffset = gsap.utils.mapRange(0, 1.5, -150, 150, yOffset);

    gsap.to(videoWrapper, {

    duration: 1.25,

    });

    };

    item.addEventListener("mouseenter", onMouseEnter);

    item.addEventListener("mouseleave", onMouseLeave);

    item.addEventListener("mousemove", onMouseMove);

    window.addEventListener("resize", () => {

    itemBounds = item.getBoundingClientRect();

    });

    });

About - check the programming

  • <!DOCTYPE html>

    <html lang="en">

    <head>

    <meta charset="UTF-8">

    <title>Elysium-about</title>

    <link rel="stylesheet" href="../../part 2/button.css">

    <link rel="stylesheet" href="../../part 2/about.css">

    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css">

    <link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">

    </head>

    <body>

    <div class="wrapper">

    <div class="menu-btn">

    <button type="button"><i class="material-icons">menu</i></button>

    </div>

    <div class="menu">

    <div class="row">

    <div class="col-lg overlay hidden">

    <h1>Elysium</h1>

    <div class="nav">

    <ul>

    <li><div class="logo"></div></li>

    <li><a href="../../part 1/relevant.html" target="_parent">Home</a></li>

    <li><a href="../../part 2/roadview.html" target="_parent">Road view</a></li>

    <li><a href="../../part 2/overview.html" target="_parent">Over view</a></li>

    <li><a href="../../part 2/postview.html" target="_parent">Post view</a></li>

    <li><a href="../../part 2/about.html" target="_parent">About</a></li>

    </ul>

    </div>

    </div>

    </div>

    </div>

    </div>

    <div class="interactive-notice">Try drawing on the screen</div>

    <div class="custom-container">

    <div class="col"></div>

    <div class="col">

    <div>

    <p>

    Welcome to Elysium, a revolutionary platform offering a unique <br />

    e-memorial service that preserves and celebrates the lives of <br />

    your departed loved ones. At Elysium, we utilize comprehensive <br />

    data provided by you to craft bespoke life stories and create <br />

    digital avatars that offer an interactive experience, allowing <br />

    the memory of In the future, Elysium aspires to offer the ability <br />

    for individuals to plan ahead, uploading their life's journey and <br />

    essence, thereby transforming into digital citizens after death.<br />

    These digital citizens will not only continue to interact with <br />

    the world through their virtual presence but also contribute <br />

    economically, with their digital creations generating value that <br />

    can be shared with their chosen beneficiaries.Join us in our <br />

    journey of redefining remembrance and envisioning an enduring <br />

    digital life beyond the mortal realm. At Elysium, we believe in a<br />

    future where death is not an end, but a transition to a new form of <br />

    existence.<br />

    </p>

    <br />

    <p><u>Service</u></p>

    <p>E-Memorials</p>

    <p>Life Story Curation</p>

    <p>Interactive Digital Avatars</p>

    <p>Online Remembrance Space</p>

    </p>

    <br />

    <p><u>Future</u></p>

    <p>End-of-life Digital Transition Planning</p>

    <p>Posthumous Digital Citizenship</p>

    <p>Digital Legacy Continuation</p>

    <p>Economic Activity from Digital Citizens</p>

    <p>Legacy Distribution Management</p>

    </div>

    </div>

    </div>

    </div>

    <canvas id="draw"></canvas>

    <div class="interactive-notice">Try drawing on the screen</div>

    <script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/2.0.2/TweenMax.min.js"></script>

    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>

    <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/js/bootstrap.min.js"></script>

    <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/js/bootstrap.bundle.min.js"></script>

    <script>

    var t1 = new TimelineMax({ paused: true });

    t1.to(".overlay", 1, {

    opacity: 1,

    ease: Expo.easeInOut

    });

    t1.staggerFrom(".menu ul li", 0.8, { y: 60, opacity: 0, ease: Expo.easeOut }, 0.1);

    t1.reverse();

    $(document).on("click", ".menu-btn", function () {

    t1.reversed(!t1.reversed());

    if (t1.reversed()) {

    $(".overlay").addClass("hidden");

    $("body").css("overflow", "auto");

    } else {

    $(".overlay").removeClass("hidden");

    $("body").css("overflow", "hidden");

    }

    });

    </script>

    <script>

    const canvas = document.querySelector("canvas");

    const ctx = canvas.getContext("2d");

    canvas.width = window.innerWidth;

    canvas.height = window.innerHeight;

    ctx.lineJoin = "round";

    ctx.lineCap = "round";

    ctx.lineWidth = 100;

    let isDrawing = false;

    let lastX = 0;

    let lastY = 0;

    let hue = 170;

    let saturation = 40;

    let lightness = 85;

    let direction = true;

    function draw(e) {

    if (!isDrawing) return;

    ctx.strokeStyle = `hsl(${hue}, ${saturation}%, ${lightness}%)`;

    ctx.beginPath();

    ctx.moveTo(lastX, lastY);

    ctx.lineTo(e.offsetX, e.offsetY);

    ctx.stroke();

    [lastX, lastY] = [e.offsetX, e.offsetY];

    if (direction) {

    hue++;

    saturation++;

    lightness--;

    if(hue > 250 || saturation > 100 || lightness < 45) {

    direction = !direction;

    }

    } else {

    hue--;

    saturation--;

    lightness++;

    if(hue < 170 || saturation < 40 || lightness > 85) {

    direction = !direction;

    }

    }

    }

    function clearCanvas() {

    ctx.clearRect(0, 0, canvas.width, canvas.height);

    }

    canvas.addEventListener("mousedown", (e) => {

    isDrawing = true;

    [lastX, lastY] = [e.offsetX, e.offsetY];

    });

    canvas.addEventListener("mousemove", draw);

    canvas.addEventListener("mouseup", () => {

    isDrawing = false;

    clearCanvas();

    });

    canvas.addEventListener("mouseout", () => {

    isDrawing = false;

    clearCanvas();

    });

    </script>

    </body>

    </html>

  • var t1 = new TimelineMax({ paused: true });

    t1.to(".overlay", 1, {

    opacity: 1,

    ease: Expo.easeInOut

    });

    t1.staggerFrom(".menu ul li", 0.8, { y: 60, opacity: 0, ease: Expo.easeOut }, 0.1);

    t1.reverse();

    $(document).on("click", ".menu-btn", function () {

    t1.reversed(!t1.reversed());

    if (t1.reversed()) {

    $(".overlay").addClass("hidden");

    $("body").css("overflow", "auto");

    } else {

    $(".overlay").removeClass("hidden");

    $("body").css("overflow", "hidden");

    }

    });

    function setupNavigation() {

    var menuBtn = document.querySelector(".menu-btn");

    var overlay = document.querySelector(".overlay");

    menuBtn.addEventListener("click", function () {

    t1.reversed(!t1.reversed());

    if (t1.reversed()) {

    overlay.classList.add("hidden");

    document.body.style.overflow = "auto";

    } else {

    overlay.classList.remove("hidden");

    document.body.style.overflow = "hidden";

    }

    });

    }

  • * {

    margin: 0;

    padding: 0;

    box-sizing: border-box;

    }

    html,

    body {

    font-family: "Neue World Ultralight";

    overflow-x: hidden;

    }

    canvas {

    position: absolute;

    top: 0;

    left: 0;

    width: 100vw;

    height: 100vh;

    }

    .custom-container {

    position: relative;

    z-index: 1;

    pointer-events: none;

    width: 100%;

    height: 100%;

    display: flex;

    }

    p {

    pointer-events: none;

    font-weight: 500;

    font-size: 14.5px;

    line-height: 1.15;

    margin-left: 190px;

    }

    .col {

    width: 50%;

    padding: 2em;

    display: flex;

    flex-direction: column;

    justify-content: space-between;

    }

    .col canvas {

    mix-blend-mode: difference;

    filter: grayscale(100%) brightness(2);

    }

    .interactive-notice {

    position: absolute;

    top: 30px;

    left: 30px;

    font-size: 1.25em;

    color: rgb(0, 0, 0);

    padding: 10px;

    border-radius: 5px;

    z-index: 2;

    }

    .menu-btn {

    padding-right: 25.5px;

    }

Navigation - check the programming

  • <!DOCTYPE html>

    <html lang="en">

    <head>

    <meta charset="UTF-8">

    <title>Elysium-navigation</title>

    <link rel="stylesheet" href="../../part 2/button.css">

    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css">

    <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/js/bootstrap.min.js"></script>

    <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/js/bootstrap.bundle.min.js"></script>

    <link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">

    <script src="https://code.jquery.com/jquery-3.3.1.js"></script>

    <script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/2.0.2/TweenMax.min.js"></script>

    </head>

    <body>

    <div class="wrapper">

    <div class="menu-btn">

    <button type="button"><i class="material-icons">menu</i></button>

    </div>

    <div class="menu">

    <div class="row">

    <div class="col-lg overlay hidden">

    <h1>Elysium</h1>

    <div class="nav">

    <ul>

    <li><div class="logo"></div></li>

    <li><a href="../../part 1/relevant.html" target="_parent">Home</a></li>

    <li><a href="../../part 2/roadview.html" target="_parent">Road view</a></li>

    <li><a href="../../part 2/overview.html" target="_parent">Over view</a></li>

    <li><a href="../../part 2/postview.html" target="_parent">Post view</a></li>

    <li><a href="../../part 2/about.html" target="_parent">About</a></li>

    </ul>

    </div>

    </div>

    </div>

    </div>

    </div>

    <script type="text/javascript">

    var t1 = new TimelineMax({paused: true});

    t1.to(".overlay", 1, {

    opacity: 1,

    ease: Expo.easeInOut

    });

    t1.staggerFrom(".menu ul li", 0.8, {y: 60, opacity: 0, ease: Expo.easeOut}, 0.1);

    t1.reverse();

    $(document).on("click", ".menu-btn", function() {

    t1.reversed(!t1.reversed());

    if (t1.reversed()){

    $(".overlay").addClass("hidden");

    $("body").css("overflow", "auto");

    } else {

    $(".overlay").removeClass("hidden");

    $("body").css("overflow", "hidden");

    }

    });

    </script>

    </body>

    </html>

  • document.addEventListener("DOMContentLoaded", function() {

    var cssFile = document.createElement("link");

    cssFile.rel = "stylesheet";

    cssFile.href = "../../part 2/button.css";

    document.head.appendChild(cssFile);

    var t1 = new TimelineMax({ paused: true });

    t1.to(".overlay", 1, {

    opacity: 1,

    ease: Expo.easeInOut

    });

    t1.staggerFrom(".menu ul li", 0.8, { y: 60, opacity: 0, ease: Expo.easeOut }, 0.1);

    t1.reverse();

    document.addEventListener("click", function(event) {

    if (event.target.closest(".menu-btn")) {

    t1.reversed(!t1.reversed());

    var overlay = document.querySelector(".overlay");

    var body = document.body;

    if (t1.reversed()) {

    overlay.classList.add("hidden");

    body.style.overflow = "auto";

    } else {

    overlay.classList.remove("hidden");

    body.style.overflow = "hidden";

    }

    }

    });

    });

  • .overlay:before {

    animation: grain 1s steps(10) infinite;

    content: "";

    height: 300%;

    left: -50%;

    opacity: 0;

    position: fixed;

    top: -110%;

    width: 300%;

    }

    @keyframes grain {

    0%, 100% { transform: translate(0, 0); }

    10% { transform: translate(-5%, -10%); }

    20% { transform: translate(-15%, 5%); }

    30% { transform: translate(7%, -25%); }

    40% { transform: translate(-5%, 25%); }

    50% { transform: translate(-15%, 10%); }

    60% { transform: translate(15%, 0%); }

    70% { transform: translate(0%, 15%); }

    80% { transform: translate(3%, 35%); }

    90% { transform: translate(-10%, 10%); }

    }

    html, body {

    margin: 0;

    padding: 0;

    width: 100%;

    height: 100vh;

    }

    body {

    background: 50% 50%;

    background-size: cover;

    }

    .hidden {

    display: none;

    }

    .menu-btn {

    position: fixed;

    margin: 1.2em;

    bottom: 20px;

    left: 50%;

    transform: translateX(-50%);

    z-index: 10001;

    }

    button {

    border: none;

    background: none;

    }

    button:focus {

    outline: none !important;

    }

    i {

    outline: none;

    padding: 0.8em;

    color: #000000;

    background: rgba(225, 225, 225, 0.5);

    border-radius: 50%;

    }

    .row, .col-lg {

    margin: 0 !important;

    padding: 0 !important;

    }

    .col-lg {

    height: 100vh;

    }

    .col-lg.overlay {

    position: fixed;

    top: 0;

    left: 0;

    width: 100%;

    height: 100vh;

    z-index: 10000;

    opacity: 0;

    background: rgb(205, 215, 255);

    }

    .overlay h1 {

    position: absolute;

    top: 50%;

    left: 50%;

    transform: translate(-50%, -50%);

    font-size: 280px;

    font-family: Poppins;

    font-weight: 800;

    color: #ffffff;

    }

    ul {

    position: absolute;

    top: 42%;

    left: 50%;

    transform: translate(-50%, -50%);

    list-style: none;

    margin: 0;

    padding: 0;

    }

    .logo {

    width: 140px;

    height: 40px;

    }

    li {

    padding-top: 40px;

    font-family: Poppins;

    font-size: 24px;

    font-weight: 300;

    text-transform: uppercase;

    text-align: center;

    color: #000000;

    }

    @media(max-width: 900px) {

    ul {

    top: 46%;

    }

    li {

    padding-top: 40px;

    }

    .overlay h1 {

    font-size: 140px;

    }

    }

Elysium: Reflections and Vision

In designing Elysium, I explored how memories, emotions, and technology intertwine. This project is more than memory preservation; it's about extending life's essence into the digital realm, offering comfort and reshaping our view of existence and the afterlife.

My experience with Elysium has been deeply personal, intertwining life, death, and digital realities. It highlighted how technology is more than tools – it's a gateway to the depths of our humanity. From platform development to user experience design, Elysium exemplifies technology's role in our intimate life narratives.

Looking forward, Elysium's current version is just a beginning. Its potential spans digital memorials, VR memory experiences, and collaborative ventures in sectors like healthcare. Imagining a future where Elysium evolves into a digital nation, it could offer a space for departed souls to be represented and for the living to reconnect. Advanced AI and quantum computing might enable digital personas to more accurately reflect individual nuances, pushing the frontiers of life, memory, and digital existence. What we see now is just the start of a path brimming with innovation and endless possibilities.

极乐世界:反思与愿景


在设计Elysium时,我探索了记忆、情感与技术之间的交织。这个项目不仅仅是关于记忆的保存,更是关于将生命的本质延伸到数字领域,提供慰藉,并重塑我们对存在和来世的看法。

我的Elysium体验是深度个人化的,它将生命、死亡和数字现实交织在一起。它突显出技术不仅仅是工具——它是通往我们人性深处的门户。从平台开发到用户体验设计,Elysium代表了技术在我们私密生活叙事中的角色。

展望未来,Elysium目前的版本只是个开始。它的潜力横跨数字纪念碑、VR记忆体验和在医疗保健等领域的合作项目。想象一个未来,Elysium演变成一个数字化的国度,它能够为离世的灵魂提供代表空间,也为生者提供重联的场所。先进的人工智能和量子计算可能会使数字化人物能更准确地反映个人细微差别,推动生命、记忆和数字存在的边界。我们现在看到的,只是充满创新和无限可能的路径的起点。