import React, { useState } from "react"; const LinearTransformationWidget: React.FC = () => { const [h, setH] = useState(0); // Horizontal shift (x - h) const [k, setK] = useState(0); // Vertical shift + k const [reflectX, setReflectX] = useState(false); // -f(x) const stretch = 1; // a * f(x) // Base function f(x) = 0.5x // Transformed g(x) = a * f(x - h) + k // g(x) = a * (0.5 * (x - h)) + k // Actually, let's use f(x) = x for simplicity, or 0.5x to show slope changes easier? // PDF examples use general f(x). Let's use f(x) = x as base. // g(x) = stretch * (x - h) + k. If reflectX is true, stretch becomes -stretch. const effectiveStretch = reflectX ? -stretch : stretch; const range = 10; const scale = 20; // 20px per unit const size = 300; const center = size / 2; const toPx = (v: number, isY = false) => isY ? center - v * scale : center + v * scale; // Base: y = 0.5x (to make it distinct from diagonals) const getBasePath = () => { const m = 0.5; const x1 = -range, x2 = range; const y1 = m * x1; const y2 = m * x2; return `M ${toPx(x1)} ${toPx(y1, true)} L ${toPx(x2)} ${toPx(y2, true)}`; }; const getTransformedPath = () => { // f(x) = 0.5x // g(x) = effectiveStretch * (0.5 * (x - h)) + k const x1 = -range, x2 = range; const y1 = effectiveStretch * (0.5 * (x1 - h)) + k; const y2 = effectiveStretch * (0.5 * (x2 - h)) + k; return `M ${toPx(x1)} ${toPx(y1, true)} L ${toPx(x2)} ${toPx(y2, true)}`; }; return (

Base:{" "} f(x) = 0.5x

g(x) = {reflectX ? "-" : ""} {stretch !== 1 ? stretch : ""}f(x {h > 0 ? "-" : "+"}{" "} {Math.abs(h)}) {k >= 0 ? "+" : "-"} {Math.abs(k)}

setH(parseInt(e.target.value))} className="w-full h-2 bg-indigo-100 rounded-lg appearance-none cursor-pointer accent-indigo-600 mt-1" />
Left (x+h) Right (x-h)
setK(parseInt(e.target.value))} className="w-full h-2 bg-emerald-100 rounded-lg appearance-none cursor-pointer accent-emerald-600 mt-1" />
{/* Axes */} {/* Base Function (Ghost) */} f(x) {/* Transformed Function */} g(x)
); }; export default LinearTransformationWidget;