12abef4076
Write a basic web app with a Rust engine, compiled to WebAssembly, powering a Civet interface. Do linear algebra in the engine using the `nalgebra` crate.
114 lines
2.8 KiB
Plaintext
114 lines
2.8 KiB
Plaintext
// engine functions
|
|
{default: init, Circle, circThru} from "./pkg/engine.js"
|
|
|
|
// === elements and state ===
|
|
|
|
// input
|
|
dataInputs .= new Array<HTMLInputElement>(6)
|
|
data .= new Float64Array(6)
|
|
|
|
// output and display
|
|
let circ: Circle | null
|
|
let display: HTMLCanvasElement
|
|
let ctx: CanvasRenderingContext2D
|
|
|
|
// === display ===
|
|
|
|
// display style
|
|
const rView = 5
|
|
const highlightStyle = "#fcfcfc"
|
|
const gridStyle = "#404040"
|
|
const dataFillStyles = ["#ba5d09", "#0e8a06", "#8951fb"]
|
|
const dataStrokeStyles = ["#f89142", "#58c145", "#c396fc"]
|
|
|
|
function render: void
|
|
// update resolution
|
|
res .= display.width / (2*rView)
|
|
|
|
// set transformation
|
|
ctx.setTransform 1, 0, 0, -1, 0.5*display.width, 0.5*display.height
|
|
|
|
// clear previous frame
|
|
ctx.clearRect -0.5*display.width, -0.5*display.height, display.width, display.height
|
|
|
|
// draw grid
|
|
gridRange .= [Math.ceil(-rView + 0.01) .. Math.floor(rView - 0.01)]
|
|
edgeScr .= res*rView
|
|
ctx.strokeStyle = gridStyle
|
|
for t of gridRange
|
|
tScr .= res*t
|
|
|
|
// draw horizontal grid line
|
|
ctx.beginPath()
|
|
ctx.moveTo -edgeScr, tScr
|
|
ctx.lineTo edgeScr, tScr
|
|
ctx.stroke()
|
|
|
|
// draw vertical grid line
|
|
ctx.beginPath()
|
|
ctx.moveTo tScr, -edgeScr
|
|
ctx.lineTo tScr, edgeScr
|
|
ctx.stroke()
|
|
|
|
// draw circle
|
|
if circ
|
|
ctx.beginPath()
|
|
ctx.strokeStyle = highlightStyle
|
|
ctx.arc res*circ.center_x, res*circ.center_y, res*circ.radius, 0, 2*Math.PI
|
|
ctx.stroke()
|
|
|
|
// draw data points
|
|
for n of [0..2]
|
|
const ind_x = 2*n
|
|
const ind_y = ind_x + 1
|
|
if dataInputs[ind_x].validity.valid and dataInputs[ind_y].validity.valid
|
|
ctx.beginPath()
|
|
ctx.fillStyle = dataFillStyles[n]
|
|
ctx.strokeStyle = dataStrokeStyles[n]
|
|
ctx.arc res*data[ind_x], res*data[ind_y], 3, 0, 2*Math.PI
|
|
ctx.fill()
|
|
ctx.stroke()
|
|
|
|
// === interaction ===
|
|
|
|
// --- inputs ---
|
|
|
|
function inputData: void
|
|
allDataValid .= true
|
|
for n of [0 .. dataInputs.length-1]
|
|
if dataInputs[n].validity.valid
|
|
data[n] = dataInputs[n].valueAsNumber
|
|
else
|
|
allDataValid = false
|
|
|
|
if allDataValid
|
|
try
|
|
circ = circThru data
|
|
catch ex
|
|
circ = null
|
|
console.error ex
|
|
else
|
|
circ = null
|
|
|
|
// update the display
|
|
requestAnimationFrame(render)
|
|
|
|
// --- binding ---
|
|
|
|
function bindDoc: Promise<void>
|
|
// wait for the engine to load
|
|
await init()
|
|
|
|
// set up the data inputs
|
|
for n of [0..5]
|
|
dataInputs[n] = document.querySelector(`#data-input-${n}`) as HTMLInputElement
|
|
dataInputs[n].addEventListener "input", inputData
|
|
dataInputs[n].style.borderColor = dataFillStyles[Math.floor(0.5*n)]
|
|
|
|
// initialize the display
|
|
display = document.querySelector("#display") as HTMLCanvasElement
|
|
ctx = display.getContext("2d") as CanvasRenderingContext2D
|
|
inputData()
|
|
|
|
document.addEventListener "DOMContentLoaded", bindDoc
|