<!DOCTYPE html>
<html lang="vulnerability">
<head>
<meta charset="UTF-8">
<meta name = "viewport" content = "width = device-width, initial-scale = 1.0">
<meta name = "keywords" content = "HTML, CSS, JavaScript">
<meta name = "description" content = "a love poem">
<meta name = "author" content = "the source of eternal love">
<title>The Delivery</title>
<style>
/*by hand*/
* {
margin: 0;
padding: 0;
box-sizing: border-box;
/*Characters: you, me*/
/*my*/
body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%);
min-height: 100vh;
position: relative;
overflow-x: hidden;
}
/*trembling*/
/*Setting:*/
.titleContent-wrapper {
position: relative;
z-index: 10;
max-width: 1200px;
margin: 0 auto;
padding: 40px 20px;
}
.titleHeader {
text-align: center;
margin-bottom: 40px;
}
.titleHeader h1 {
font-size: 2.5em;
color: #2c3e50;
font-weight: 300;
letter-spacing: 2px;
margin-bottom: 10px;
text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.1);
}
.card {
background: rgba(255, 255, 255, 0.10);
border-radius: 16px;
padding: 30px;
margin-bottom: 30px;
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.10);
backdrop-filter: blur(.5px);
}
/*Plot:*/
.signHere {
display: flex;
flex-direction: column;
align-items: center;
gap: 20px;
}
/*Motif:*/
.button-group {
display: flex;
gap: 15px;
}
button {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
border: none;
padding: 12px 30px;
border-radius: 25px;
font-size: 16px;
font-weight: 500;
cursor: pointer;
transition: all 0.3s ease;
box-shadow: 0 4px 15px rgba(102, 126, 234, 0.4);
}
button:hover {
transform: translateY(-2px);
box-shadow: 0 6px 20px rgba(102, 126, 234, 0.6);
}
button:active {
transform: translateY(0);
}
/*Themes:*/
/*something to treasure*/
.image-container {
margin-top: 20px;
text-align: center;
}
.image-container img {
max-width: 200px;
border-radius: 12px;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.01);
transition: transform 0.3s ease;
}
.image-container img:hover {
transform: scale(1.05);
}
/*a total vibe*/
.choices-section {
margin-top: 30px;
align-items: center;
display: flex;
flex-direction: column;
}
.choices-section h2 {
color: #2c3e50;
font-size: 1.8em;
font-weight: 400;
margin-bottom: 25px;
text-align: center;
}
.choice-item {
background: rgba(255, 255, 255, .2);
padding: 20px;
border-radius: 12px;
margin-bottom: 15px;
display: flex;
align-items: center;
justify-content: space-between;
transition: all 0.3s ease;
}
.choice-item:hover {
background: rgba(255, 255, 255, 0.5);
transform: translateX(5px);
}
.choice-text {
font-size: 1.1em;
color: #34495e;
align-items: center;
}
/*a long-term commitment*/
.response-text {
font-size: 1.1em;
color: #667eea;
font-weight: 500;
font-style: italic;
align-items: center;
}
.axiom {
background: #2c3e50;
color: #ecf0f1;
padding: 20px;
border-radius: 12px;
font-family: 'Courier New', monospace;
font-size: 1em;
line-height: 1.8;
margin-top: 30px;
box-shadow: inset 0 2px 8px rgba(0, 0, 0, 0.3);
}
/*a place where anything is possible*/
.canvas-container {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 1;
pointer-events: none;
}
.canvas-title {
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
color: rgba(44, 66, 88, 0.4);
font-size: 1.2em;
font-weight: 300;
letter-spacing: 3px;
text-shadow: 0 0 20px rgba(255, 255, 255, 0.8);
z-index: 5;
pointer-events: none;
}
canvas {
display: block;
width: 100%;
height: 100%;
}
/*where everything seems to fit*/
@media (max-width: 768px) {
.titleHeader h1 {
font-size: 1.8em;
}
.button-group {
flex-direction: column;
}
button {
width: 100%;
}
.choice-item {
flex-direction: column;
gap: 15px;
text-align: center;
}
}
</style>
</head>
<!--Storyline:-->
<body>
<!--palying in the background, where there is no beginning or end, in space and time-->
<div class="canvas-container">
<div class="canvas-title">the Love here is infinite</div>
<canvas id="canvas"></canvas>
</div>
<!--a main request-->
<div class="titleContent-wrapper">
<div class="titleHeader">
<!--albeit a bit clumsy-->
<h1>The Delivery</h1>
</div>
<!--the face-->
<div class="card">
<!--says, please-->
<div class="signHere">
<div class="button-group">
<button onclick="changeImage('policy')">Policy</button>
<button onclick="changeImage('open')">Open</button>
</div>
<div class="image-container">
<!--to have and to hold, till death do us part-->
<img id="myImage"
src="https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQkYRdrvg_ylfhamyg0bmKPeq6HE4xQaARx4A&s"
alt="Delivery Image">
</div>
</div>
</div>
<!--the face-->
<div class="card">
<!--a patient reflection-->
<div class="choices-section">
<h2>Having seen the contents</h2>
<div class="choice-item">
<span class="choice-text" id="possibility1">You may choose to <button onclick="runFunction()">Run</button></span>
</div>
<!--or-->
<div class="choice-item">
<span class="choice-text" id="possibility2">You may choose to <button onclick="stayFunction()">Stay</button></span>
</div>
</div>
<!--a prayer-->
<div class="axiom">
let x = you;<br>
let y = me;<br>
let sum = you + me + ∞;
</div>
</div>
</div>
<!-- rendering dynamical systems in a dynamic language-->
<script>
// no refunds, only exchanges; sine here
function changeImage(type) {
const img = document.getElementById('myImage');
if (type === 'policy') {
img.src = 'https://i.ebayimg.com/images/g/q~UAAeSwhRhoXsD0/s-l300.jpg';
} else if (type === 'open') {
img.src = 'https://tse2.mm.bing.net/th/id/OIP.Jrt2WxsH2XXWEH44qYc3SgHaE7?rs=1&pid=ImgDetMain&o=7&rm=3';
}
}
// your heart knows this —
function runFunction() {
document.getElementById("possibility1").innerHTML =
'<span class="response-text">Я жду тебя с распростёртыми руками</span>';
}
function stayFunction() {
document.getElementById("possibility2").innerHTML =
'<span class="response-text">I am waiting for you with open arms</span>';
}
// in a space of pure potential
const canvas = document.getElementById('canvas');
const lex = canvas.getContext('2d');
// i have a job for you
function resizeCanvas() {
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
}
resizeCanvas();
window.addEventListener('resize', resizeCanvas);
let centerX = canvas.width / 2;
let centerY = canvas.height / 2;
// establishing natural parameters and laying our foundations
const g = 0.2;
const L = 150;
const damping = 1;
let theta = Math.PI / 3;
let omega = 0;
let time = 0;
function toCanvasX(th) {
const scale = Math.min(canvas.width, canvas.height) * 0.35;
return canvas.width / 2 + th * scale / Math.PI;
}
function toCanvasY(om) {
const maxOmega = 3;
const scale = Math.min(canvas.width, canvas.height) * 0.35;
return canvas.height / 2 - om * scale / maxOmega;
}
// we're going places
function acceleration(th) {
return -(g / L) * Math.sin(th) * 100;
}
function getVelocity(th, om) {
const dtheta_dt = om;
const domega_dt = -(g / L) * Math.sin(th) * 100;
return { dtheta: dtheta_dt, domega: domega_dt };
}
// caught in a spectrum of possibilities
function getColor(th, om, alpha = 1) {
const hue = (th * 60 + om * 30 + time * 0.005) % 360;
const saturation = 80 + Math.sin(time * 0.0001) * 20;
const lightness = 60 + Math.sin(time * 0.0002) * 10;
return `hsla(${hue}, ${saturation}%, ${lightness}%, ${alpha})`;
}
// our magnitude and direction are stored efficiently
function drawFlowingVectors() {
centerX = canvas.width / 2;
centerY = canvas.height / 2;
const gridSize = 80;
const sphereRadius = Math.min(canvas.width, canvas.height) * 0.4;
for (let i = 0; i < canvas.width; i += gridSize) {
for (let j = 0; j < canvas.height; j += gridSize) {
const distFromCenter = Math.sqrt((i - centerX) ** 2 + (j - centerY) ** 2);
if (distFromCenter > sphereRadius) continue;
const scale = Math.min(canvas.width, canvas.height) * 0.35;
const th = ((i - centerX) / scale) * Math.PI;
const om = -((j - centerY) / scale) * 3;
const vel = getVelocity(th, om);
const dx = vel.dtheta * 3;
const dy = -vel.domega * 3;
const mag = Math.sqrt(dx * dx + dy * dy);
if (mag < 0.1) continue;
const pendulumX = toCanvasX(theta);
const pendulumY = toCanvasY(omega);
const distToPendulum = Math.sqrt((i - pendulumX) ** 2 + (j - pendulumY) ** 2);
const proximityEffect = Math.exp(-distToPendulum / 150);
const flowSpeed = 0.10;
const flowPhase = (time * flowSpeed + i * 0.01 + j * 0.01) % 1.0;
const flowOffset = flowPhase * 1.5;
const angle = Math.atan2(dy, dx);
const curvatureAmount = (distFromCenter / sphereRadius) * 0.3;
const angleToCenter = Math.atan2(j - centerY, i - centerX);
const curvedAngle = angle + Math.sin(angleToCenter) * curvatureAmount;
const x = i + Math.cos(curvedAngle) * flowOffset * 20;
const y = j + Math.sin(curvedAngle) * flowOffset * 20;
const flowFade = Math.pow(Math.sin(flowPhase * Math.PI), 0.5);
const edgeFade = 1 - Math.pow(distFromCenter / sphereRadius, 3);
const alpha = (0.4 + proximityEffect * 0.5) * edgeFade * flowFade;
if (alpha < 0.05) continue;
lex.save();
lex.translate(x, y);
lex.rotate(curvedAngle);
lex.fillStyle = getColor(th, om, alpha);
lex.font = `${8 + proximityEffect * 4}px Arial`;
lex.textAlign = 'center';
lex.textBaseline = 'middle';
if (proximityEffect > 0.1) {
lex.shadowBlur = proximityEffect * 50;
lex.shadowColor = getColor(th, om, alpha * 0.2);
}
const text = 'Love';
const charSpacing = 0.08;
const radius = 202;
for (let c = 0; c < text.length; c++) {
const charAngle = (c - text.length / 2) * charSpacing;
const charX = Math.sin(charAngle) * radius;
const charY = -Math.cos(charAngle) * radius + radius;
lex.save();
lex.translate(charX, charY);
lex.rotate(charAngle);
lex.fillText(text[c], 0, 0);
lex.restore();
}
lex.shadowBlur = 0;
lex.restore();
}
}
}
// anchored to our Azimuthal Zero
function drawAxes() {
centerX = canvas.width / 2;
centerY = canvas.height / 2;
const sphereRadius = Math.min(canvas.width, canvas.height) * 0.4;
const outerGlow = lex.createRadialGradient(centerX, centerY, sphereRadius - 20, centerX, centerY, sphereRadius + 20);
outerGlow.addColorStop(0, 'rgba(255, 255, 255, 0.1)');
outerGlow.addColorStop(0.5, 'rgba(255, 255, 255, 0.05)');
outerGlow.addColorStop(1, 'rgba(255, 255, 255, 0)');
lex.fillStyle = outerGlow;
lex.beginPath();
lex.arc(centerX, centerY, sphereRadius + 20, 0, Math.PI * 2);
lex.fill();
lex.strokeStyle = 'rgba(255, 255, 255, 0.3)';
lex.lineWidth = 2;
lex.beginPath();
lex.arc(centerX, centerY, sphereRadius, 0, Math.PI * 2);
lex.stroke();
lex.strokeStyle = 'rgba(255, 255, 255, 0.2)';
lex.lineWidth = 1;
lex.beginPath();
lex.arc(centerX, centerY, sphereRadius - 5, 0, Math.PI * 2);
lex.stroke();
lex.strokeStyle = 'rgba(255, 255, 255, 0.2)';
lex.lineWidth = 1;
lex.beginPath();
lex.moveTo(centerX - sphereRadius, centerY);
lex.lineTo(centerX + sphereRadius, centerY);
lex.stroke();
lex.beginPath();
lex.moveTo(centerX, centerY - sphereRadius);
lex.lineTo(centerX, centerY + sphereRadius);
lex.stroke();
lex.fillStyle = 'rgba(255, 255, 255, 0.4)';
lex.font = '14px Arial';
lex.textAlign = 'center';
lex.shadowBlur = 10;
lex.shadowColor = 'rgba(255, 255, 255, 0.3)';
lex.fillText('θ', centerX + sphereRadius - 30, centerY - 10);
lex.fillText('ω', centerX + 20, centerY - sphereRadius + 30);
lex.shadowBlur = 0;
}
// we overcome —
function update() {
const acc = acceleration(theta);
omega += acc;
omega *= damping;
theta += omega;
time += 0.1;
}
// we imagine and create —
function draw() {
lex.fillStyle = 'rgba(0, 0, 0, 0)';
lex.fillRect(0, 0, canvas.width, canvas.height);
drawAxes();
drawFlowingVectors();
}
// we inspire and bring to life —
function animate() {
update();
draw();
requestAnimationFrame(animate);
}
// we fetch; we
animate();
</script>
</body>
</html>
<html lang="vulnerability">
<head>
<meta charset="UTF-8">
<meta name = "viewport" content = "width = device-width, initial-scale = 1.0">
<meta name = "keywords" content = "HTML, CSS, JavaScript">
<meta name = "description" content = "a love poem">
<meta name = "author" content = "the source of eternal love">
<title>The Delivery</title>
<style>
/*by hand*/
* {
margin: 0;
padding: 0;
box-sizing: border-box;
/*Characters: you, me*/
/*my*/
body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%);
min-height: 100vh;
position: relative;
overflow-x: hidden;
}
/*trembling*/
/*Setting:*/
.titleContent-wrapper {
position: relative;
z-index: 10;
max-width: 1200px;
margin: 0 auto;
padding: 40px 20px;
}
.titleHeader {
text-align: center;
margin-bottom: 40px;
}
.titleHeader h1 {
font-size: 2.5em;
color: #2c3e50;
font-weight: 300;
letter-spacing: 2px;
margin-bottom: 10px;
text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.1);
}
.card {
background: rgba(255, 255, 255, 0.10);
border-radius: 16px;
padding: 30px;
margin-bottom: 30px;
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.10);
backdrop-filter: blur(.5px);
}
/*Plot:*/
.signHere {
display: flex;
flex-direction: column;
align-items: center;
gap: 20px;
}
/*Motif:*/
.button-group {
display: flex;
gap: 15px;
}
button {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
border: none;
padding: 12px 30px;
border-radius: 25px;
font-size: 16px;
font-weight: 500;
cursor: pointer;
transition: all 0.3s ease;
box-shadow: 0 4px 15px rgba(102, 126, 234, 0.4);
}
button:hover {
transform: translateY(-2px);
box-shadow: 0 6px 20px rgba(102, 126, 234, 0.6);
}
button:active {
transform: translateY(0);
}
/*Themes:*/
/*something to treasure*/
.image-container {
margin-top: 20px;
text-align: center;
}
.image-container img {
max-width: 200px;
border-radius: 12px;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.01);
transition: transform 0.3s ease;
}
.image-container img:hover {
transform: scale(1.05);
}
/*a total vibe*/
.choices-section {
margin-top: 30px;
align-items: center;
display: flex;
flex-direction: column;
}
.choices-section h2 {
color: #2c3e50;
font-size: 1.8em;
font-weight: 400;
margin-bottom: 25px;
text-align: center;
}
.choice-item {
background: rgba(255, 255, 255, .2);
padding: 20px;
border-radius: 12px;
margin-bottom: 15px;
display: flex;
align-items: center;
justify-content: space-between;
transition: all 0.3s ease;
}
.choice-item:hover {
background: rgba(255, 255, 255, 0.5);
transform: translateX(5px);
}
.choice-text {
font-size: 1.1em;
color: #34495e;
align-items: center;
}
/*a long-term commitment*/
.response-text {
font-size: 1.1em;
color: #667eea;
font-weight: 500;
font-style: italic;
align-items: center;
}
.axiom {
background: #2c3e50;
color: #ecf0f1;
padding: 20px;
border-radius: 12px;
font-family: 'Courier New', monospace;
font-size: 1em;
line-height: 1.8;
margin-top: 30px;
box-shadow: inset 0 2px 8px rgba(0, 0, 0, 0.3);
}
/*a place where anything is possible*/
.canvas-container {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 1;
pointer-events: none;
}
.canvas-title {
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
color: rgba(44, 66, 88, 0.4);
font-size: 1.2em;
font-weight: 300;
letter-spacing: 3px;
text-shadow: 0 0 20px rgba(255, 255, 255, 0.8);
z-index: 5;
pointer-events: none;
}
canvas {
display: block;
width: 100%;
height: 100%;
}
/*where everything seems to fit*/
@media (max-width: 768px) {
.titleHeader h1 {
font-size: 1.8em;
}
.button-group {
flex-direction: column;
}
button {
width: 100%;
}
.choice-item {
flex-direction: column;
gap: 15px;
text-align: center;
}
}
</style>
</head>
<!--Storyline:-->
<body>
<!--palying in the background, where there is no beginning or end, in space and time-->
<div class="canvas-container">
<div class="canvas-title">the Love here is infinite</div>
<canvas id="canvas"></canvas>
</div>
<!--a main request-->
<div class="titleContent-wrapper">
<div class="titleHeader">
<!--albeit a bit clumsy-->
<h1>The Delivery</h1>
</div>
<!--the face-->
<div class="card">
<!--says, please-->
<div class="signHere">
<div class="button-group">
<button onclick="changeImage('policy')">Policy</button>
<button onclick="changeImage('open')">Open</button>
</div>
<div class="image-container">
<!--to have and to hold, till death do us part-->
<img id="myImage"
src="https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQkYRdrvg_ylfhamyg0bmKPeq6HE4xQaARx4A&s"
alt="Delivery Image">
</div>
</div>
</div>
<!--the face-->
<div class="card">
<!--a patient reflection-->
<div class="choices-section">
<h2>Having seen the contents</h2>
<div class="choice-item">
<span class="choice-text" id="possibility1">You may choose to <button onclick="runFunction()">Run</button></span>
</div>
<!--or-->
<div class="choice-item">
<span class="choice-text" id="possibility2">You may choose to <button onclick="stayFunction()">Stay</button></span>
</div>
</div>
<!--a prayer-->
<div class="axiom">
let x = you;<br>
let y = me;<br>
let sum = you + me + ∞;
</div>
</div>
</div>
<!-- rendering dynamical systems in a dynamic language-->
<script>
// no refunds, only exchanges; sine here
function changeImage(type) {
const img = document.getElementById('myImage');
if (type === 'policy') {
img.src = 'https://i.ebayimg.com/images/g/q~UAAeSwhRhoXsD0/s-l300.jpg';
} else if (type === 'open') {
img.src = 'https://tse2.mm.bing.net/th/id/OIP.Jrt2WxsH2XXWEH44qYc3SgHaE7?rs=1&pid=ImgDetMain&o=7&rm=3';
}
}
// your heart knows this —
function runFunction() {
document.getElementById("possibility1").innerHTML =
'<span class="response-text">Я жду тебя с распростёртыми руками</span>';
}
function stayFunction() {
document.getElementById("possibility2").innerHTML =
'<span class="response-text">I am waiting for you with open arms</span>';
}
// in a space of pure potential
const canvas = document.getElementById('canvas');
const lex = canvas.getContext('2d');
// i have a job for you
function resizeCanvas() {
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
}
resizeCanvas();
window.addEventListener('resize', resizeCanvas);
let centerX = canvas.width / 2;
let centerY = canvas.height / 2;
// establishing natural parameters and laying our foundations
const g = 0.2;
const L = 150;
const damping = 1;
let theta = Math.PI / 3;
let omega = 0;
let time = 0;
function toCanvasX(th) {
const scale = Math.min(canvas.width, canvas.height) * 0.35;
return canvas.width / 2 + th * scale / Math.PI;
}
function toCanvasY(om) {
const maxOmega = 3;
const scale = Math.min(canvas.width, canvas.height) * 0.35;
return canvas.height / 2 - om * scale / maxOmega;
}
// we're going places
function acceleration(th) {
return -(g / L) * Math.sin(th) * 100;
}
function getVelocity(th, om) {
const dtheta_dt = om;
const domega_dt = -(g / L) * Math.sin(th) * 100;
return { dtheta: dtheta_dt, domega: domega_dt };
}
// caught in a spectrum of possibilities
function getColor(th, om, alpha = 1) {
const hue = (th * 60 + om * 30 + time * 0.005) % 360;
const saturation = 80 + Math.sin(time * 0.0001) * 20;
const lightness = 60 + Math.sin(time * 0.0002) * 10;
return `hsla(${hue}, ${saturation}%, ${lightness}%, ${alpha})`;
}
// our magnitude and direction are stored efficiently
function drawFlowingVectors() {
centerX = canvas.width / 2;
centerY = canvas.height / 2;
const gridSize = 80;
const sphereRadius = Math.min(canvas.width, canvas.height) * 0.4;
for (let i = 0; i < canvas.width; i += gridSize) {
for (let j = 0; j < canvas.height; j += gridSize) {
const distFromCenter = Math.sqrt((i - centerX) ** 2 + (j - centerY) ** 2);
if (distFromCenter > sphereRadius) continue;
const scale = Math.min(canvas.width, canvas.height) * 0.35;
const th = ((i - centerX) / scale) * Math.PI;
const om = -((j - centerY) / scale) * 3;
const vel = getVelocity(th, om);
const dx = vel.dtheta * 3;
const dy = -vel.domega * 3;
const mag = Math.sqrt(dx * dx + dy * dy);
if (mag < 0.1) continue;
const pendulumX = toCanvasX(theta);
const pendulumY = toCanvasY(omega);
const distToPendulum = Math.sqrt((i - pendulumX) ** 2 + (j - pendulumY) ** 2);
const proximityEffect = Math.exp(-distToPendulum / 150);
const flowSpeed = 0.10;
const flowPhase = (time * flowSpeed + i * 0.01 + j * 0.01) % 1.0;
const flowOffset = flowPhase * 1.5;
const angle = Math.atan2(dy, dx);
const curvatureAmount = (distFromCenter / sphereRadius) * 0.3;
const angleToCenter = Math.atan2(j - centerY, i - centerX);
const curvedAngle = angle + Math.sin(angleToCenter) * curvatureAmount;
const x = i + Math.cos(curvedAngle) * flowOffset * 20;
const y = j + Math.sin(curvedAngle) * flowOffset * 20;
const flowFade = Math.pow(Math.sin(flowPhase * Math.PI), 0.5);
const edgeFade = 1 - Math.pow(distFromCenter / sphereRadius, 3);
const alpha = (0.4 + proximityEffect * 0.5) * edgeFade * flowFade;
if (alpha < 0.05) continue;
lex.save();
lex.translate(x, y);
lex.rotate(curvedAngle);
lex.fillStyle = getColor(th, om, alpha);
lex.font = `${8 + proximityEffect * 4}px Arial`;
lex.textAlign = 'center';
lex.textBaseline = 'middle';
if (proximityEffect > 0.1) {
lex.shadowBlur = proximityEffect * 50;
lex.shadowColor = getColor(th, om, alpha * 0.2);
}
const text = 'Love';
const charSpacing = 0.08;
const radius = 202;
for (let c = 0; c < text.length; c++) {
const charAngle = (c - text.length / 2) * charSpacing;
const charX = Math.sin(charAngle) * radius;
const charY = -Math.cos(charAngle) * radius + radius;
lex.save();
lex.translate(charX, charY);
lex.rotate(charAngle);
lex.fillText(text[c], 0, 0);
lex.restore();
}
lex.shadowBlur = 0;
lex.restore();
}
}
}
// anchored to our Azimuthal Zero
function drawAxes() {
centerX = canvas.width / 2;
centerY = canvas.height / 2;
const sphereRadius = Math.min(canvas.width, canvas.height) * 0.4;
const outerGlow = lex.createRadialGradient(centerX, centerY, sphereRadius - 20, centerX, centerY, sphereRadius + 20);
outerGlow.addColorStop(0, 'rgba(255, 255, 255, 0.1)');
outerGlow.addColorStop(0.5, 'rgba(255, 255, 255, 0.05)');
outerGlow.addColorStop(1, 'rgba(255, 255, 255, 0)');
lex.fillStyle = outerGlow;
lex.beginPath();
lex.arc(centerX, centerY, sphereRadius + 20, 0, Math.PI * 2);
lex.fill();
lex.strokeStyle = 'rgba(255, 255, 255, 0.3)';
lex.lineWidth = 2;
lex.beginPath();
lex.arc(centerX, centerY, sphereRadius, 0, Math.PI * 2);
lex.stroke();
lex.strokeStyle = 'rgba(255, 255, 255, 0.2)';
lex.lineWidth = 1;
lex.beginPath();
lex.arc(centerX, centerY, sphereRadius - 5, 0, Math.PI * 2);
lex.stroke();
lex.strokeStyle = 'rgba(255, 255, 255, 0.2)';
lex.lineWidth = 1;
lex.beginPath();
lex.moveTo(centerX - sphereRadius, centerY);
lex.lineTo(centerX + sphereRadius, centerY);
lex.stroke();
lex.beginPath();
lex.moveTo(centerX, centerY - sphereRadius);
lex.lineTo(centerX, centerY + sphereRadius);
lex.stroke();
lex.fillStyle = 'rgba(255, 255, 255, 0.4)';
lex.font = '14px Arial';
lex.textAlign = 'center';
lex.shadowBlur = 10;
lex.shadowColor = 'rgba(255, 255, 255, 0.3)';
lex.fillText('θ', centerX + sphereRadius - 30, centerY - 10);
lex.fillText('ω', centerX + 20, centerY - sphereRadius + 30);
lex.shadowBlur = 0;
}
// we overcome —
function update() {
const acc = acceleration(theta);
omega += acc;
omega *= damping;
theta += omega;
time += 0.1;
}
// we imagine and create —
function draw() {
lex.fillStyle = 'rgba(0, 0, 0, 0)';
lex.fillRect(0, 0, canvas.width, canvas.height);
drawAxes();
drawFlowingVectors();
}
// we inspire and bring to life —
function animate() {
update();
draw();
requestAnimationFrame(animate);
}
// we fetch; we
animate();
</script>
</body>
</html>