document.addEventListener('DOMContentLoaded', () => { // Function Graph Visualization with enhanced controls const functionCtx = document.getElementById('functionGraph').getContext('2d'); let xMin = -10, xMax = 10, yMin = -5, yMax = 5; const algebraCtx = document.getElementById('algebraGraph').getContext('2d'); // Initialize function graph const functionGraph = new Chart(functionCtx, { type: 'line', data: { datasets: [{ label: 'Function', borderColor: '#7c3aed', backgroundColor: 'rgba(124, 58, 237, 0.1)', borderWidth: 2, pointRadius: 0, fill: true }] }, options: { responsive: true, maintainAspectRatio: false, scales: { x: { type: 'linear', position: 'center', min: xMin, max: xMax, title: { display: true, text: 'x-axis', font: { weight: 'bold' } }, grid: { color: (ctx) => ctx.tick.value === 0 ? '#000' : 'rgba(0, 0, 0, 0.1)' } }, y: { type: 'linear', position: 'center', min: yMin, max: yMax, title: { display: true, text: 'y-axis', font: { weight: 'bold' } }, grid: { color: (ctx) => ctx.tick.value === 0 ? '#000' : 'rgba(0, 0, 0, 0.1)' } } }, plugins: { tooltip: { mode: 'nearest', intersect: false, callbacks: { label: (context) => { return `f(${context.parsed.x.toFixed(2)}) = ${context.parsed.y.toFixed(2)}`; } } }, legend: { display: false }, zoom: { pan: { enabled: true, mode: 'xy' }, zoom: { wheel: { enabled: true }, pinch: { enabled: true }, mode: 'xy' } } }, interaction: { mode: 'nearest', intersect: false } } }); // Initialize algebra graph const algebraGraph = new Chart(algebraCtx, { type: 'line', data: { datasets: [{ label: 'Linear Equation', borderColor: '#0ea5e9', backgroundColor: 'rgba(14, 165, 233, 0.1)', borderWidth: 2, pointRadius: 0 }] }, options: { responsive: true, scales: { x: { type: 'linear', position: 'center', min: -10, max: 10 }, y: { type: 'linear', position: 'center', min: -10, max: 10 } } } }); // Add zoom and pan controls document.getElementById('zoomIn').addEventListener('click', () => { xMin *= 0.8; xMax *= 0.8; yMin *= 0.8; yMax *= 0.8; updateGraphScale(); }); document.getElementById('zoomOut').addEventListener('click', () => { xMin *= 1.2; xMax *= 1.2; yMin *= 1.2; yMax *= 1.2; updateGraphScale(); }); document.getElementById('resetView').addEventListener('click', () => { xMin = -10; xMax = 10; yMin = -5; yMax = 5; updateGraphScale(); }); function updateGraphScale() { functionGraph.options.scales.x.min = xMin; functionGraph.options.scales.x.max = xMax; functionGraph.options.scales.y.min = yMin; functionGraph.options.scales.y.max = yMax; functionGraph.update(); } // Update function graph when input changes document.getElementById('functionInput').addEventListener('input', function() { updateFunctionGraph(); }); // Mouse move coordinates display const coordDisplay = document.getElementById('coordinatesDisplay'); document.getElementById('functionGraph').addEventListener('mousemove', (e) => { const rect = e.target.getBoundingClientRect(); const x = xMin + (xMax - xMin) * (e.clientX - rect.left) / rect.width; const y = yMax - (yMax - yMin) * (e.clientY - rect.top) / rect.height; coordDisplay.textContent = `x: ${x.toFixed(2)}, y: ${y.toFixed(2)}`; }); function updateFunctionGraph() { const func = document.getElementById('functionInput').value; const data = []; let isValid = true; for (let x = xMin; x <= xMax; x += (xMax - xMin)/200) { try { const y = math.evaluate(func, {x: x}); if (!isNaN(y) && isFinite(y)) { data.push({x: x, y: y}); } else { isValid = false; } } catch (e) { console.error("Error evaluating function:", e); isValid = false; } } // Update line color based on validity functionGraph.data.datasets[0].borderColor = isValid ? '#7c3aed' : '#ef4444'; functionGraph.data.datasets[0].data = data; functionGraph.update(); } // Update algebra graph with sliders document.getElementById('sliderM').addEventListener('input', updateAlgebraGraph); document.getElementById('sliderB').addEventListener('input', updateAlgebraGraph); function updateAlgebraGraph() { const m = parseFloat(document.getElementById('sliderM').value); const b = parseFloat(document.getElementById('sliderB').value); const data = [ {x: -10, y: m*-10 + b}, {x: 10, y: m*10 + b} ]; algebraGraph.data.datasets[0].data = data; algebraGraph.update(); } // Initialize graphs updateFunctionGraph(); updateAlgebraGraph(); // Geometry Canvas Interaction const geometryCanvas = document.getElementById('geometryCanvas'); let isDrawing = false; let currentShape = null; let startX, startY; document.getElementById('drawLine').addEventListener('click', () => setShapeMode('line')); document.getElementById('drawCircle').addEventListener('click', () => setShapeMode('circle')); document.getElementById('drawRectangle').addEventListener('click', () => setShapeMode('rectangle')); document.getElementById('drawTriangle').addEventListener('click', () => setShapeMode('triangle')); function setShapeMode(shape) { currentShape = shape; clearGeometryCanvas(); } function clearGeometryCanvas() { geometryCanvas.innerHTML = '
Draw shapes here
'; } geometryCanvas.addEventListener('mousedown', (e) => { if (!currentShape) return; isDrawing = true; const rect = geometryCanvas.getBoundingClientRect(); startX = e.clientX - rect.left; startY = e.clientY - rect.top; // Clear instructions if present if (geometryCanvas.querySelector('div')) { geometryCanvas.innerHTML = ''; } }); geometryCanvas.addEventListener('mousemove', (e) => { if (!isDrawing || !currentShape) return; const rect = geometryCanvas.getBoundingClientRect(); const endX = e.clientX - rect.left; const endY = e.clientY - rect.top; // Clear previous shape geometryCanvas.innerHTML = ''; // Draw new shape const svg = document.createElementNS("http://www.w3.org/2000/svg", "svg"); svg.setAttribute('width', '100%'); svg.setAttribute('height', '100%'); svg.style.position = 'absolute'; let shape; switch (currentShape) { case 'line': shape = document.createElementNS("http://www.w3.org/2000/svg", "line"); shape.setAttribute('x1', startX); shape.setAttribute('y1', startY); shape.setAttribute('x2', endX); shape.setAttribute('y2', endY); shape.setAttribute('stroke', '#7c3aed'); shape.setAttribute('stroke-width', '2'); break; case 'circle': const radius = Math.sqrt(Math.pow(endX - startX, 2) + Math.pow(endY - startY, 2)); shape = document.createElementNS("http://www.w3.org/2000/svg", "circle"); shape.setAttribute('cx', startX); shape.setAttribute('cy', startY); shape.setAttribute('r', radius); shape.setAttribute('fill', 'rgba(124, 58, 237, 0.2)'); shape.setAttribute('stroke', '#7c3aed'); shape.setAttribute('stroke-width', '2'); break; case 'rectangle': shape = document.createElementNS("http://www.w3.org/2000/svg", "rect"); shape.setAttribute('x', Math.min(startX, endX)); shape.setAttribute('y', Math.min(startY, endY)); shape.setAttribute('width', Math.abs(endX - startX)); shape.setAttribute('height', Math.abs(endY - startY)); shape.setAttribute('fill', 'rgba(124, 58, 237, 0.2)'); shape.setAttribute('stroke', '#7c3aed'); shape.setAttribute('stroke-width', '2'); break; case 'triangle': shape = document.createElementNS("http://www.w3.org/2000/svg", "polygon"); const points = `${startX},${startY} ${endX},${endY} ${startX},${endY}`; shape.setAttribute('points', points); shape.setAttribute('fill', 'rgba(124, 58, 237, 0.2)'); shape.setAttribute('stroke', '#7c3aed'); shape.setAttribute('stroke-width', '2'); break; } svg.appendChild(shape); geometryCanvas.appendChild(svg); }); geometryCanvas.addEventListener('mouseup', () => { isDrawing = false; }); geometryCanvas.addEventListener('mouseleave', () => { isDrawing = false; }); });