solid canvas prototpye
This commit is contained in:
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