solid canvas prototpye
This commit is contained in:
@@ -1,94 +0,0 @@
|
|||||||
class DownloadsPanel extends Shadow {
|
|
||||||
render() {
|
|
||||||
ZStack(() => {
|
|
||||||
input("", "60vw")
|
|
||||||
.backgroundColor("var(--accent3)")
|
|
||||||
.color("var(--accent)")
|
|
||||||
.border("none")
|
|
||||||
.borderTop("1px solid var(--accent)")
|
|
||||||
.borderBottom("1px solid var(--accent)")
|
|
||||||
.outline("0.5px solid black")
|
|
||||||
.borderRadius(7, px)
|
|
||||||
.transition("padding .2s")
|
|
||||||
.padding(0.5, em)
|
|
||||||
.position("absolute")
|
|
||||||
.x(50, vw).y(7, em)
|
|
||||||
.transform("translate(-50%, -50%)")
|
|
||||||
.onInput(() => {
|
|
||||||
console.log('typing')
|
|
||||||
})
|
|
||||||
.onFocus(function (focusing) {
|
|
||||||
if(focusing) {
|
|
||||||
this.style.padding = "1em"
|
|
||||||
this.style.borderColor = "var(--darkred)"
|
|
||||||
} else {
|
|
||||||
this.style.padding = "0.5em"
|
|
||||||
this.style.borderColor = "var(--accent)"
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
// VStack(() => {
|
|
||||||
// const json = this.getJSONData()
|
|
||||||
|
|
||||||
// p(json.length + " Entries")
|
|
||||||
// .marginBottom(2, em)
|
|
||||||
|
|
||||||
// // Split into two alternating columns
|
|
||||||
// const left = []
|
|
||||||
// const right = []
|
|
||||||
|
|
||||||
// for (let i = 0; i < 200; i++) {
|
|
||||||
// if (i % 2 === 0) {
|
|
||||||
// left.push(json[i])
|
|
||||||
// } else {
|
|
||||||
// right.push(json[i])
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// console.log(left)
|
|
||||||
// HStack(() => {
|
|
||||||
// // LEFT COLUMN
|
|
||||||
// VStack(() => {
|
|
||||||
// for (let item of left) {
|
|
||||||
// p(item.name)
|
|
||||||
// .marginLeft(0, em)
|
|
||||||
// .marginBottom(0.1, em)
|
|
||||||
// }
|
|
||||||
// })
|
|
||||||
|
|
||||||
// // RIGHT COLUMN
|
|
||||||
// VStack(() => {
|
|
||||||
// for (let item of right) {
|
|
||||||
// p(item.name)
|
|
||||||
// .marginLeft(0, em)
|
|
||||||
// .marginBottom(0.1, em)
|
|
||||||
// }
|
|
||||||
// })
|
|
||||||
// .marginLeft(3, em) // spacing between columns
|
|
||||||
// })
|
|
||||||
// })
|
|
||||||
// .paddingLeft(5, em)
|
|
||||||
// .paddingTop(10, em)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
getJSONData() {
|
|
||||||
const script = document.getElementById('jsonData');
|
|
||||||
if (!script) {
|
|
||||||
console.warn('initial-data script not found');
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
// script.textContent is the raw JSON string
|
|
||||||
const data = JSON.parse(script.textContent);
|
|
||||||
console.log(data)
|
|
||||||
return data;
|
|
||||||
} catch (err) {
|
|
||||||
console.error('Failed to parse initial-data JSON:', err);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
register(DownloadsPanel)
|
|
||||||
@@ -1,34 +0,0 @@
|
|||||||
import "./NavMenu.js"
|
|
||||||
import "./HomePanel.js"
|
|
||||||
import "./DownloadsPanel.js"
|
|
||||||
|
|
||||||
class Home extends Shadow {
|
|
||||||
|
|
||||||
render() {
|
|
||||||
ZStack(() => {
|
|
||||||
|
|
||||||
switch(window.location.pathname) {
|
|
||||||
case "/":
|
|
||||||
HomePanel()
|
|
||||||
break;
|
|
||||||
case "/downloads":
|
|
||||||
DownloadsPanel()
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.backgroundColor("var(--main)")
|
|
||||||
.display("block")
|
|
||||||
.width(100, vw).height("auto")
|
|
||||||
.color("var(--accent)")
|
|
||||||
.fontFamily("Arial")
|
|
||||||
.onAppear(() => {
|
|
||||||
document.body.style.backgroundColor = "var(--main)"
|
|
||||||
})
|
|
||||||
.onNavigate(() => {
|
|
||||||
console.log("navved")
|
|
||||||
this.rerender()
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
register(Home)
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
class HomePanel extends Shadow {
|
|
||||||
render() {
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
register(HomePanel)
|
|
||||||
@@ -1,37 +0,0 @@
|
|||||||
class NavMenu extends Shadow {
|
|
||||||
|
|
||||||
NavButton(text) {
|
|
||||||
return p(text)
|
|
||||||
.cursor("default")
|
|
||||||
.onAppear(function () {
|
|
||||||
console.log(window.location.pathname, "/" + this.innerText.toLowerCase())
|
|
||||||
if(window.location.pathname === ("/" + this.innerText.toLowerCase())) {
|
|
||||||
this.style.textDecoration = "underline"
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.onHover(function (hovering) {
|
|
||||||
if(hovering) {
|
|
||||||
this.style.textDecoration = "underline"
|
|
||||||
} else {
|
|
||||||
this.style.textDecoration = ""
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.onClick(function (done) {
|
|
||||||
if(done) {
|
|
||||||
window.navigateTo(this.innerText === "Home" ? "/" : this.innerText.toLowerCase())
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
|
||||||
HStack(() => {
|
|
||||||
this.NavButton("Home")
|
|
||||||
this.NavButton("Downloads")
|
|
||||||
})
|
|
||||||
.gap(2, em)
|
|
||||||
.x(50, vw).y(5, vh)
|
|
||||||
.center()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
register(NavMenu)
|
|
||||||
@@ -7,7 +7,21 @@
|
|||||||
<link rel="stylesheet" href="/_/code/shared.css"></script>
|
<link rel="stylesheet" href="/_/code/shared.css"></script>
|
||||||
<script src="/_/code/quill.js"></script>
|
<script src="/_/code/quill.js"></script>
|
||||||
<script type="module" src="/75820185/index.js"></script>
|
<script type="module" src="/75820185/index.js"></script>
|
||||||
|
<style>
|
||||||
|
:root {
|
||||||
|
--main: #6A2C1C;
|
||||||
|
--accent: #FEB279;
|
||||||
|
}
|
||||||
|
|
||||||
|
html, body {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
overflow: hidden;
|
||||||
|
background: var(--main);
|
||||||
|
}
|
||||||
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body style="margin: 0px;">
|
<body style="margin: 0px;">
|
||||||
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
148
cave/index.js
148
cave/index.js
@@ -1,2 +1,146 @@
|
|||||||
import "./components/Home.js"
|
/*
|
||||||
Home()
|
Samuel Russell
|
||||||
|
Captured Sun
|
||||||
|
12.29.2025
|
||||||
|
*/
|
||||||
|
|
||||||
|
class Canvas {
|
||||||
|
STROKE_COLOR = getComputedStyle(document.documentElement).getPropertyValue("--accent").trim();
|
||||||
|
c = document.createElement("canvas")
|
||||||
|
ctx;
|
||||||
|
|
||||||
|
/* -----------------------------
|
||||||
|
Camera
|
||||||
|
----------------------------- */
|
||||||
|
camera = {
|
||||||
|
x: 0,
|
||||||
|
y: 0,
|
||||||
|
scale: 1,
|
||||||
|
ZOOM_SPEED: 0.016,
|
||||||
|
PAN_SPEED: 1.5,
|
||||||
|
FOCUS_THRESHOLD: 4.0
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -----------------------------
|
||||||
|
Rectangle
|
||||||
|
----------------------------- */
|
||||||
|
rect = {
|
||||||
|
x: -300,
|
||||||
|
y: -200,
|
||||||
|
w: 600,
|
||||||
|
h: 400
|
||||||
|
};
|
||||||
|
|
||||||
|
resize = () => {
|
||||||
|
// Make Canvas Fill Screen
|
||||||
|
this.c.style.width = window.innerWidth + "px";
|
||||||
|
this.c.style.height = window.innerHeight + "px";
|
||||||
|
|
||||||
|
// Set Internal Render Size by DPR
|
||||||
|
const dpr = window.devicePixelRatio || 1;
|
||||||
|
this.c.width = window.innerWidth * dpr;
|
||||||
|
this.c.height = window.innerHeight * dpr;
|
||||||
|
this.ctx.scale(dpr, dpr);
|
||||||
|
}
|
||||||
|
|
||||||
|
onWheel = (e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
let camera = this.camera
|
||||||
|
|
||||||
|
const rectCanvas = this.c.getBoundingClientRect();
|
||||||
|
const mouseX = e.clientX - rectCanvas.left;
|
||||||
|
const mouseY = e.clientY - rectCanvas.top;
|
||||||
|
|
||||||
|
if (!e.ctrlKey) {
|
||||||
|
const dpr = window.devicePixelRatio || 1;
|
||||||
|
|
||||||
|
// Two-finger pan in world coordinates
|
||||||
|
camera.x += (e.deltaX * dpr) * camera.PAN_SPEED / camera.scale;
|
||||||
|
camera.y += (e.deltaY * dpr) * camera.PAN_SPEED / camera.scale;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const dpr = window.devicePixelRatio || 1;
|
||||||
|
|
||||||
|
const worldX = (
|
||||||
|
mouseX -
|
||||||
|
(this.c.width / dpr) / 2 // X coordinate of canvas center in CSS pixels
|
||||||
|
) // Mouse offset from canvas center in CSS pixels
|
||||||
|
/ camera.scale // Account for Zoom: shift by camera's zoom position
|
||||||
|
+ camera.x; // Account for Pan: shift by camera’s world X position
|
||||||
|
|
||||||
|
const worldY = (
|
||||||
|
mouseY -
|
||||||
|
(this.c.height / dpr) / 2
|
||||||
|
)
|
||||||
|
/ camera.scale
|
||||||
|
+ camera.y;
|
||||||
|
|
||||||
|
// Apply zoom
|
||||||
|
const zoomFactor = Math.exp(-e.deltaY * camera.ZOOM_SPEED);
|
||||||
|
camera.scale *= zoomFactor;
|
||||||
|
camera.scale = Math.max(0.04, Math.min(10, camera.scale));
|
||||||
|
|
||||||
|
// Adjust camera to keep cursor fixed
|
||||||
|
camera.x = worldX - (mouseX - (this.c.width / dpr) / 2) / camera.scale;
|
||||||
|
camera.y = worldY - (mouseY - (this.c.height / dpr) / 2) / camera.scale;
|
||||||
|
}
|
||||||
|
|
||||||
|
draw = () => {
|
||||||
|
let ctx = this.ctx
|
||||||
|
let rect = this.rect
|
||||||
|
let camera = this.camera
|
||||||
|
let scale = camera.scale
|
||||||
|
requestAnimationFrame(this.draw);
|
||||||
|
|
||||||
|
ctx.setTransform(1, 0, 0, 1, 0, 0);
|
||||||
|
ctx.clearRect(0, 0, this.c.width, this.c.height);
|
||||||
|
|
||||||
|
let drawMenus = () => {
|
||||||
|
|
||||||
|
ctx.setTransform(1, 0, 0, 1, 0, 0); // reset transform for UI
|
||||||
|
ctx.fillStyle = "rgba(30,30,30,0.8)";
|
||||||
|
ctx.fillRect(10,10,150,100);
|
||||||
|
|
||||||
|
ctx.fillStyle = "#FEB279";
|
||||||
|
ctx.fillRect(20,20,120,30);
|
||||||
|
ctx.fillRect(20,60,120,30);
|
||||||
|
|
||||||
|
ctx.fillStyle = "#000";
|
||||||
|
ctx.font = "60px arial";
|
||||||
|
ctx.fillText("Button 1", 20, 40);
|
||||||
|
ctx.fillText("Button 2", 20, 80);
|
||||||
|
}
|
||||||
|
|
||||||
|
let drawSpace = () => {
|
||||||
|
ctx.translate(this.c.width / 2, this.c.height / 2);
|
||||||
|
ctx.scale(scale, scale);
|
||||||
|
ctx.translate(-camera.x, -camera.y);
|
||||||
|
|
||||||
|
ctx.strokeStyle = this.STROKE_COLOR;
|
||||||
|
ctx.lineWidth = 0.5 / scale;
|
||||||
|
ctx.strokeRect(rect.x, rect.y, rect.w, rect.h);
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx.save()
|
||||||
|
|
||||||
|
drawSpace()
|
||||||
|
|
||||||
|
ctx.restore()
|
||||||
|
|
||||||
|
drawMenus(ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
document.body.appendChild(this.c)
|
||||||
|
this.ctx = this.c.getContext("2d");
|
||||||
|
|
||||||
|
window.addEventListener("resize", this.resize);
|
||||||
|
this.resize();
|
||||||
|
|
||||||
|
this.c.addEventListener("wheel", this.onWheel, { passive: false });
|
||||||
|
this.draw()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
new Canvas()
|
||||||
Reference in New Issue
Block a user