chore(build): refactor codebase for production
This commit is contained in:
@ -1,4 +1,4 @@
|
||||
import React, { useState, useRef, useEffect } from 'react';
|
||||
import React, { useState, useRef } from "react";
|
||||
|
||||
const SimilarityWidget: React.FC = () => {
|
||||
const [ratio, setRatio] = useState(0.5); // Position of D along AB (0 to 1)
|
||||
@ -13,22 +13,22 @@ const SimilarityWidget: React.FC = () => {
|
||||
// Calculate D and E based on ratio
|
||||
const D = {
|
||||
x: A.x + (B.x - A.x) * ratio,
|
||||
y: A.y + (B.y - A.y) * ratio
|
||||
y: A.y + (B.y - A.y) * ratio,
|
||||
};
|
||||
|
||||
|
||||
const E = {
|
||||
x: A.x + (C.x - A.x) * ratio,
|
||||
y: A.y + (C.y - A.y) * ratio
|
||||
y: A.y + (C.y - A.y) * ratio,
|
||||
};
|
||||
|
||||
const handleInteraction = (clientY: number) => {
|
||||
if (!svgRef.current) return;
|
||||
const rect = svgRef.current.getBoundingClientRect();
|
||||
const y = clientY - rect.top;
|
||||
|
||||
|
||||
// Clamp y between A.y and B.y
|
||||
const clampedY = Math.max(A.y, Math.min(B.y, y));
|
||||
|
||||
|
||||
// Calculate new ratio
|
||||
const newRatio = (clampedY - A.y) / (B.y - A.y);
|
||||
setRatio(Math.max(0.1, Math.min(0.9, newRatio))); // clamp to avoid degenerate
|
||||
@ -47,70 +47,152 @@ const SimilarityWidget: React.FC = () => {
|
||||
|
||||
return (
|
||||
<div className="bg-white p-6 rounded-xl shadow-lg border border-slate-200 flex flex-col md:flex-row items-center gap-8">
|
||||
<svg
|
||||
<svg
|
||||
ref={svgRef}
|
||||
width="400"
|
||||
height="350"
|
||||
width="400"
|
||||
height="350"
|
||||
className="select-none cursor-ns-resize"
|
||||
onMouseDown={handleMouseDown}
|
||||
onMouseMove={handleMouseMove}
|
||||
onMouseUp={() => isDragging.current = false}
|
||||
onMouseLeave={() => isDragging.current = false}
|
||||
onMouseUp={() => (isDragging.current = false)}
|
||||
onMouseLeave={() => (isDragging.current = false)}
|
||||
>
|
||||
{/* Main Triangle */}
|
||||
<path d={`M ${A.x} ${A.y} L ${B.x} ${B.y} L ${C.x} ${C.y} Z`} fill="none" stroke="#e2e8f0" strokeWidth="2" />
|
||||
|
||||
<path
|
||||
d={`M ${A.x} ${A.y} L ${B.x} ${B.y} L ${C.x} ${C.y} Z`}
|
||||
fill="none"
|
||||
stroke="#e2e8f0"
|
||||
strokeWidth="2"
|
||||
/>
|
||||
|
||||
{/* Filled Top Triangle (Similar) */}
|
||||
<path d={`M ${A.x} ${A.y} L ${D.x} ${D.y} L ${E.x} ${E.y} Z`} fill="rgba(244, 63, 94, 0.1)" stroke="none" />
|
||||
<path
|
||||
d={`M ${A.x} ${A.y} L ${D.x} ${D.y} L ${E.x} ${E.y} Z`}
|
||||
fill="rgba(244, 63, 94, 0.1)"
|
||||
stroke="none"
|
||||
/>
|
||||
|
||||
{/* Parallel Line DE */}
|
||||
<line x1={D.x} y1={D.y} x2={E.x} y2={E.y} stroke="#e11d48" strokeWidth="3" />
|
||||
|
||||
<line
|
||||
x1={D.x}
|
||||
y1={D.y}
|
||||
x2={E.x}
|
||||
y2={E.y}
|
||||
stroke="#e11d48"
|
||||
strokeWidth="3"
|
||||
/>
|
||||
|
||||
{/* Labels */}
|
||||
<text x={A.x} y={A.y - 10} textAnchor="middle" fontWeight="bold" fill="#64748b">A</text>
|
||||
<text x={B.x - 10} y={B.y} textAnchor="end" fontWeight="bold" fill="#64748b">B</text>
|
||||
<text x={C.x + 10} y={C.y} textAnchor="start" fontWeight="bold" fill="#64748b">C</text>
|
||||
<text x={D.x - 10} y={D.y} textAnchor="end" fontWeight="bold" fill="#e11d48">D</text>
|
||||
<text x={E.x + 10} y={E.y} textAnchor="start" fontWeight="bold" fill="#e11d48">E</text>
|
||||
<text
|
||||
x={A.x}
|
||||
y={A.y - 10}
|
||||
textAnchor="middle"
|
||||
fontWeight="bold"
|
||||
fill="#64748b"
|
||||
>
|
||||
A
|
||||
</text>
|
||||
<text
|
||||
x={B.x - 10}
|
||||
y={B.y}
|
||||
textAnchor="end"
|
||||
fontWeight="bold"
|
||||
fill="#64748b"
|
||||
>
|
||||
B
|
||||
</text>
|
||||
<text
|
||||
x={C.x + 10}
|
||||
y={C.y}
|
||||
textAnchor="start"
|
||||
fontWeight="bold"
|
||||
fill="#64748b"
|
||||
>
|
||||
C
|
||||
</text>
|
||||
<text
|
||||
x={D.x - 10}
|
||||
y={D.y}
|
||||
textAnchor="end"
|
||||
fontWeight="bold"
|
||||
fill="#e11d48"
|
||||
>
|
||||
D
|
||||
</text>
|
||||
<text
|
||||
x={E.x + 10}
|
||||
y={E.y}
|
||||
textAnchor="start"
|
||||
fontWeight="bold"
|
||||
fill="#e11d48"
|
||||
>
|
||||
E
|
||||
</text>
|
||||
|
||||
{/* Drag Handle */}
|
||||
<circle cx={D.x} cy={D.y} r="6" fill="#e11d48" stroke="white" strokeWidth="2" />
|
||||
<circle cx={E.x} cy={E.y} r="6" fill="#e11d48" stroke="white" strokeWidth="2" />
|
||||
|
||||
<circle
|
||||
cx={D.x}
|
||||
cy={D.y}
|
||||
r="6"
|
||||
fill="#e11d48"
|
||||
stroke="white"
|
||||
strokeWidth="2"
|
||||
/>
|
||||
<circle
|
||||
cx={E.x}
|
||||
cy={E.y}
|
||||
r="6"
|
||||
fill="#e11d48"
|
||||
stroke="white"
|
||||
strokeWidth="2"
|
||||
/>
|
||||
</svg>
|
||||
|
||||
<div className="flex-1 w-full">
|
||||
<h3 className="text-lg font-bold text-slate-800 mb-4">Triangle Proportionality</h3>
|
||||
<p className="text-sm text-slate-500 mb-6">Drag the red line. Because DE || BC, the small triangle is similar to the large triangle.</p>
|
||||
|
||||
<div className="space-y-4">
|
||||
<div className="bg-slate-50 p-4 rounded-lg border-l-4 border-rose-500">
|
||||
<p className="text-xs font-bold text-slate-400 uppercase mb-1">Scale Factor</p>
|
||||
<p className="font-mono text-xl text-rose-700">{ratio.toFixed(2)}</p>
|
||||
</div>
|
||||
<h3 className="text-lg font-bold text-slate-800 mb-4">
|
||||
Triangle Proportionality
|
||||
</h3>
|
||||
<p className="text-sm text-slate-500 mb-6">
|
||||
Drag the red line. Because DE || BC, the small triangle is similar to
|
||||
the large triangle.
|
||||
</p>
|
||||
|
||||
<div className="bg-white border border-slate-200 p-4 rounded-lg shadow-sm">
|
||||
<p className="font-mono text-sm mb-2 text-slate-600">Corresponding Sides Ratio:</p>
|
||||
<div className="flex items-center justify-between font-mono font-bold text-lg">
|
||||
<div className="text-rose-600">AD / AB</div>
|
||||
<div className="text-slate-400">=</div>
|
||||
<div className="text-rose-600">AE / AC</div>
|
||||
<div className="text-slate-400">=</div>
|
||||
<div className="text-rose-600">{ratio.toFixed(2)}</div>
|
||||
</div>
|
||||
<div className="space-y-4">
|
||||
<div className="bg-slate-50 p-4 rounded-lg border-l-4 border-rose-500">
|
||||
<p className="text-xs font-bold text-slate-400 uppercase mb-1">
|
||||
Scale Factor
|
||||
</p>
|
||||
<p className="font-mono text-xl text-rose-700">
|
||||
{ratio.toFixed(2)}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="bg-white border border-slate-200 p-4 rounded-lg shadow-sm">
|
||||
<p className="font-mono text-sm mb-2 text-slate-600">
|
||||
Corresponding Sides Ratio:
|
||||
</p>
|
||||
<div className="flex items-center justify-between font-mono font-bold text-lg">
|
||||
<div className="text-rose-600">AD / AB</div>
|
||||
<div className="text-slate-400">=</div>
|
||||
<div className="text-rose-600">AE / AC</div>
|
||||
<div className="text-slate-400">=</div>
|
||||
<div className="text-rose-600">{ratio.toFixed(2)}</div>
|
||||
</div>
|
||||
|
||||
<div className="bg-white border border-slate-200 p-4 rounded-lg shadow-sm">
|
||||
<p className="font-mono text-sm mb-2 text-slate-600">Area Ratio (k²):</p>
|
||||
<div className="flex items-center justify-between font-mono font-bold text-lg">
|
||||
<div className="text-rose-600">Area(ADE)</div>
|
||||
<div className="text-slate-400">/</div>
|
||||
<div className="text-slate-600">Area(ABC)</div>
|
||||
<div className="text-slate-400">=</div>
|
||||
<div className="text-rose-600">{(ratio * ratio).toFixed(2)}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="bg-white border border-slate-200 p-4 rounded-lg shadow-sm">
|
||||
<p className="font-mono text-sm mb-2 text-slate-600">
|
||||
Area Ratio (k²):
|
||||
</p>
|
||||
<div className="flex items-center justify-between font-mono font-bold text-lg">
|
||||
<div className="text-rose-600">Area(ADE)</div>
|
||||
<div className="text-slate-400">/</div>
|
||||
<div className="text-slate-600">Area(ABC)</div>
|
||||
<div className="text-slate-400">=</div>
|
||||
<div className="text-rose-600">{(ratio * ratio).toFixed(2)}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user