Upload apps/cong-thuc/src/App.svelte with huggingface_hub
Browse files- apps/cong-thuc/src/App.svelte +38 -11
apps/cong-thuc/src/App.svelte
CHANGED
|
@@ -24,8 +24,13 @@
|
|
| 24 |
let currentSearchStr = '';
|
| 25 |
let searchStartIndex = -1;
|
| 26 |
|
| 27 |
-
// Zoom State
|
| 28 |
let zoom = 0.65;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 29 |
|
| 30 |
const latexTemplates = [
|
| 31 |
{ cat: 'Cơ bản', name: 'Phân số', code: '$$ \\frac{a}{b} $$', icon: 'a/b' },
|
|
@@ -281,19 +286,36 @@ $ A = mat(1, 2; 3, 4) $
|
|
| 281 |
}
|
| 282 |
|
| 283 |
function handleWheel(e: WheelEvent) {
|
| 284 |
-
|
| 285 |
-
|
| 286 |
-
|
| 287 |
-
|
| 288 |
-
|
| 289 |
-
|
| 290 |
-
zoom = Math.max(zoom - zoomFactor, 0.3);
|
| 291 |
-
}
|
| 292 |
}
|
| 293 |
}
|
| 294 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 295 |
function resetView() {
|
| 296 |
zoom = 0.65;
|
|
|
|
|
|
|
| 297 |
}
|
| 298 |
|
| 299 |
async function renderContent() {
|
|
@@ -460,10 +482,15 @@ $ A = mat(1, 2; 3, 4) $
|
|
| 460 |
</div>
|
| 461 |
|
| 462 |
<div
|
| 463 |
-
class="flex-1 overflow-
|
| 464 |
on:wheel|nonpassive={handleWheel}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 465 |
>
|
| 466 |
-
<div class="
|
| 467 |
{#if compileError}
|
| 468 |
<div class="w-full max-w-[21cm] bg-rose-50 border border-rose-200 text-rose-700 p-6 rounded-xl font-mono text-sm whitespace-pre-wrap shadow-sm">
|
| 469 |
<div class="font-bold mb-2">Lỗi Biên Dịch:</div>
|
|
|
|
| 24 |
let currentSearchStr = '';
|
| 25 |
let searchStartIndex = -1;
|
| 26 |
|
| 27 |
+
// Zoom & Pan State
|
| 28 |
let zoom = 0.65;
|
| 29 |
+
let panX = 0;
|
| 30 |
+
let panY = 0;
|
| 31 |
+
let isPanning = false;
|
| 32 |
+
let startPanX = 0;
|
| 33 |
+
let startPanY = 0;
|
| 34 |
|
| 35 |
const latexTemplates = [
|
| 36 |
{ cat: 'Cơ bản', name: 'Phân số', code: '$$ \\frac{a}{b} $$', icon: 'a/b' },
|
|
|
|
| 286 |
}
|
| 287 |
|
| 288 |
function handleWheel(e: WheelEvent) {
|
| 289 |
+
e.preventDefault();
|
| 290 |
+
const zoomFactor = 0.05;
|
| 291 |
+
if (e.deltaY < 0) {
|
| 292 |
+
zoom = Math.min(zoom + zoomFactor, 3);
|
| 293 |
+
} else {
|
| 294 |
+
zoom = Math.max(zoom - zoomFactor, 0.2);
|
|
|
|
|
|
|
| 295 |
}
|
| 296 |
}
|
| 297 |
|
| 298 |
+
function handlePanStart(e: MouseEvent) {
|
| 299 |
+
if (e.button !== 0 && e.button !== 1) return;
|
| 300 |
+
isPanning = true;
|
| 301 |
+
startPanX = e.clientX - panX;
|
| 302 |
+
startPanY = e.clientY - panY;
|
| 303 |
+
}
|
| 304 |
+
|
| 305 |
+
function handlePanMove(e: MouseEvent) {
|
| 306 |
+
if (!isPanning) return;
|
| 307 |
+
panX = e.clientX - startPanX;
|
| 308 |
+
panY = e.clientY - startPanY;
|
| 309 |
+
}
|
| 310 |
+
|
| 311 |
+
function handlePanEnd() {
|
| 312 |
+
isPanning = false;
|
| 313 |
+
}
|
| 314 |
+
|
| 315 |
function resetView() {
|
| 316 |
zoom = 0.65;
|
| 317 |
+
panX = 0;
|
| 318 |
+
panY = 0;
|
| 319 |
}
|
| 320 |
|
| 321 |
async function renderContent() {
|
|
|
|
| 482 |
</div>
|
| 483 |
|
| 484 |
<div
|
| 485 |
+
class="flex-1 overflow-hidden relative flex justify-center items-start pt-16 bg-zinc-200/50 bg-[radial-gradient(#d4d4d8_1px,transparent_1px)] [background-size:16px_16px] select-none"
|
| 486 |
on:wheel|nonpassive={handleWheel}
|
| 487 |
+
on:mousedown={handlePanStart}
|
| 488 |
+
on:mousemove={handlePanMove}
|
| 489 |
+
on:mouseup={handlePanEnd}
|
| 490 |
+
on:mouseleave={handlePanEnd}
|
| 491 |
+
style="cursor: {isPanning ? 'grabbing' : 'grab'};"
|
| 492 |
>
|
| 493 |
+
<div class="relative transition-transform duration-75" style="transform: translate({panX}px, {panY}px) scale({zoom}); transform-origin: top center;">
|
| 494 |
{#if compileError}
|
| 495 |
<div class="w-full max-w-[21cm] bg-rose-50 border border-rose-200 text-rose-700 p-6 rounded-xl font-mono text-sm whitespace-pre-wrap shadow-sm">
|
| 496 |
<div class="font-bold mb-2">Lỗi Biên Dịch:</div>
|