HTML Olarak çalışan Versiyonu

This commit is contained in:
hOLOlu
2025-11-09 17:24:14 +03:00
commit 63b58b55c6
9 changed files with 2822 additions and 0 deletions

414
old/index.html Normal file
View File

@@ -0,0 +1,414 @@
<!DOCTYPE html>
<html lang="tr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>3D Yazıcı Kalibrasyon</title>
<script crossorigin src="https://unpkg.com/react@18/umd/react.production.min.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.production.min.js"></script>
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; }
/* Utility Classes */
.min-h-screen { min-height: 100vh; }
.bg-gradient { background: linear-gradient(135deg, #0f172a 0%, #1e293b 50%, #0f172a 100%); }
.text-white { color: white; }
.p-4 { padding: 1rem; }
.max-w-6xl { max-width: 72rem; }
.mx-auto { margin-left: auto; margin-right: auto; }
.text-center { text-align: center; }
.mb-2 { margin-bottom: 0.5rem; }
.mb-4 { margin-bottom: 1rem; }
.mb-6 { margin-bottom: 1.5rem; }
.mb-8 { margin-bottom: 2rem; }
.mt-1 { margin-top: 0.25rem; }
.mt-2 { margin-top: 0.5rem; }
.mt-4 { margin-top: 1rem; }
.mt-6 { margin-top: 1.5rem; }
.text-4xl { font-size: 2.25rem; line-height: 2.5rem; }
.text-2xl { font-size: 1.5rem; line-height: 2rem; }
.text-xl { font-size: 1.25rem; line-height: 1.75rem; }
.text-lg { font-size: 1.125rem; line-height: 1.75rem; }
.text-sm { font-size: 0.875rem; line-height: 1.25rem; }
.text-xs { font-size: 0.75rem; line-height: 1rem; }
.font-bold { font-weight: 700; }
.font-semibold { font-weight: 600; }
.bg-slate-800 { background-color: rgba(30, 41, 59, 0.5); }
.bg-slate-700 { background-color: #334155; }
.bg-slate-900 { background-color: #0f172a; }
.text-slate-400 { color: #94a3b8; }
.text-slate-500 { color: #64748b; }
.text-slate-300 { color: #cbd5e1; }
.text-cyan-400 { color: #22d3ee; }
.text-cyan-300 { color: #67e8f9; }
.text-blue-400 { color: #60a5fa; }
.text-blue-300 { color: #93c5fd; }
.text-green-400 { color: #4ade80; }
.text-yellow-400 { color: #facc15; }
.text-yellow-300 { color: #fde047; }
.border { border-width: 1px; }
.border-slate-700 { border-color: #334155; }
.border-slate-600 { border-color: #475569; }
.rounded { border-radius: 0.25rem; }
.rounded-lg { border-radius: 0.5rem; }
.px-3 { padding-left: 0.75rem; padding-right: 0.75rem; }
.px-4 { padding-left: 1rem; padding-right: 1rem; }
.px-6 { padding-left: 1.5rem; padding-right: 1.5rem; }
.py-2 { padding-top: 0.5rem; padding-bottom: 0.5rem; }
.py-3 { padding-top: 0.75rem; padding-bottom: 0.75rem; }
.p-4 { padding: 1rem; }
.p-6 { padding: 1.5rem; }
.w-full { width: 100%; }
.flex { display: flex; }
.items-center { align-items: center; }
.justify-between { justify-content: space-between; }
.gap-2 { gap: 0.5rem; }
.gap-4 { gap: 1rem; }
.grid { display: grid; }
.grid-cols-1 { grid-template-columns: repeat(1, minmax(0, 1fr)); }
.overflow-x-auto { overflow-x: auto; }
.whitespace-nowrap { white-space: nowrap; }
.shadow-lg { box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1); }
.cursor-pointer { cursor: pointer; }
.transition-all { transition: all 0.3s; }
.backdrop-blur { backdrop-filter: blur(8px); }
.block { display: block; }
.space-y-1 > * + * { margin-top: 0.25rem; }
.space-y-3 > * + * { margin-top: 0.75rem; }
.list-decimal { list-style-type: decimal; }
.list-inside { list-style-position: inside; }
.ml-4 { margin-left: 1rem; }
.overflow-x-auto::-webkit-scrollbar { height: 8px; }
.overflow-x-auto::-webkit-scrollbar-track { background: #1e293b; }
.overflow-x-auto::-webkit-scrollbar-thumb { background: #334155; border-radius: 4px; }
.bg-gradient-cyan { background: linear-gradient(135deg, #06b6d4 0%, #3b82f6 100%); }
.bg-cyan-10 { background-color: rgba(34, 211, 238, 0.1); }
.border-cyan-30 { border-color: rgba(34, 211, 238, 0.3); }
.bg-blue-10 { background-color: rgba(96, 165, 250, 0.1); }
.border-blue-30 { border-color: rgba(96, 165, 250, 0.3); }
input[type="number"] {
-moz-appearance: textfield;
color: white;
}
input[type="number"]::-webkit-inner-spin-button,
input[type="number"]::-webkit-outer-spin-button {
-webkit-appearance: none;
margin: 0;
}
button:hover {
transform: translateY(-2px);
box-shadow: 0 20px 25px -5px rgba(6, 182, 212, 0.3);
}
.tab-active {
background: linear-gradient(135deg, #06b6d4 0%, #3b82f6 100%);
color: white;
}
.tab-inactive {
background-color: rgba(30, 41, 59, 0.5);
color: #94a3b8;
}
.tab-inactive:hover {
background-color: #334155;
}
pre {
white-space: pre-wrap;
word-wrap: break-word;
font-family: 'Courier New', monospace;
}
code {
background-color: #0f172a;
padding: 0.125rem 0.5rem;
border-radius: 0.25rem;
}
@media (min-width: 768px) {
.md\\:grid-cols-3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.md\\:flex-row { flex-direction: row; }
}
@media (max-width: 767px) {
.flex-col { flex-direction: column; }
}
</style>
</head>
<body>
<div id="root"></div>
<script>
const { useState, createElement: e } = React;
// Icon components (simplified versions)
const Download = () => e('svg', { width: 20, height: 20, viewBox: '0 0 24 24', fill: 'none', stroke: 'currentColor', strokeWidth: 2 },
e('path', { d: 'M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4M7 10l5 5 5-5M12 15V3' }));
const Settings = () => e('svg', { width: 20, height: 20, viewBox: '0 0 24 24', fill: 'none', stroke: 'currentColor', strokeWidth: 2 },
e('circle', { cx: 12, cy: 12, r: 3 }),
e('path', { d: 'M12 1v6m0 6v6m8.66-10a9 9 0 1 1-17.32 0' }));
const Move = () => e('svg', { width: 18, height: 18, viewBox: '0 0 24 24', fill: 'none', stroke: 'currentColor', strokeWidth: 2 },
e('polyline', { points: '5 9 2 12 5 15' }),
e('polyline', { points: '9 5 12 2 15 5' }),
e('polyline', { points: '15 19 12 22 9 19' }),
e('polyline', { points: '19 9 22 12 19 15' }),
e('line', { x1: 2, y1: 12, x2: 22, y2: 12 }),
e('line', { x1: 12, y1: 2, x2: 12, y2: 22 }));
const Box = () => e('svg', { width: 18, height: 18, viewBox: '0 0 24 24', fill: 'none', stroke: 'currentColor', strokeWidth: 2 },
e('path', { d: 'M21 16V8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73l7 4a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16z' }),
e('polyline', { points: '3.27 6.96 12 12.01 20.73 6.96' }),
e('line', { x1: 12, y1: 22.08, x2: 12, y2: 12 }));
const Maximize2 = () => e('svg', { width: 18, height: 18, viewBox: '0 0 24 24', fill: 'none', stroke: 'currentColor', strokeWidth: 2 },
e('polyline', { points: '15 3 21 3 21 9' }),
e('polyline', { points: '9 21 3 21 3 15' }),
e('line', { x1: 21, y1: 3, x2: 14, y2: 10 }),
e('line', { x1: 3, y1: 21, x2: 10, y2: 14 }));
function PrinterCalibration() {
const [activeTab, setActiveTab] = useState('x-axis');
const [settings, setSettings] = useState({
bedTemp: 60,
nozzleTemp: 200,
nozzleDiameter: 0.4
});
const [xAxisConfig, setXAxisConfig] = useState({ distance: 100, steps: 80, measured: 0 });
const [yAxisConfig, setYAxisConfig] = useState({ distance: 100, steps: 80, measured: 0 });
const [zAxisConfig, setZAxisConfig] = useState({ distance: 10, steps: 400, measured: 0 });
const [extruderConfig, setExtruderConfig] = useState({ distance: 100, steps: 93, measured: 0 });
const [skewConfig, setSkewConfig] = useState({ ac: 141.4, bd: 141.4, ad: 141.4 });
const calculateSteps = (config) => {
if (config.measured > 0) {
return ((config.distance / config.measured) * config.steps).toFixed(2);
}
return config.steps;
};
const calculateSkew = () => {
const ac = parseFloat(skewConfig.ac);
const bd = parseFloat(skewConfig.bd);
const ad = parseFloat(skewConfig.ad);
if (ac > 0 && bd > 0 && ad > 0) {
return {
xy: (Math.atan2(ac - 141.4, 100) * (180 / Math.PI)).toFixed(4),
xz: (Math.atan2(bd - 141.4, 100) * (180 / Math.PI)).toFixed(4),
yz: (Math.atan2(ad - 141.4, 100) * (180 / Math.PI)).toFixed(4)
};
}
return { xy: '0.0000', xz: '0.0000', yz: '0.0000' };
};
const generateGCode = () => {
let gcode = '; 3D Yazıcı Kalibrasyon G-Code\n';
gcode += '; Oluşturma Tarihi: ' + new Date().toLocaleString('tr-TR') + '\n\n';
gcode += `M140 S${settings.bedTemp}\nM104 S${settings.nozzleTemp}\n`;
gcode += `M190 S${settings.bedTemp}\nM109 S${settings.nozzleTemp}\n\n`;
const configs = { 'x-axis': xAxisConfig, 'y-axis': yAxisConfig, 'z-axis': zAxisConfig, 'extruder': extruderConfig };
const axes = { 'x-axis': 'X', 'y-axis': 'Y', 'z-axis': 'Z', 'extruder': 'E' };
if (activeTab === 'skew') {
const skew = calculateSkew();
gcode += `M852 I${skew.xy} J${skew.xz} K${skew.yz}\nM500\n`;
} else {
const config = configs[activeTab];
const axis = axes[activeTab];
gcode += 'G28\nG90\n';
if (activeTab === 'extruder') {
gcode += `M82\nG92 E0\nG1 E${config.distance} F100\n`;
} else {
if (activeTab !== 'z-axis') gcode += 'G1 Z10 F3000\n';
gcode += `G1 ${axis}${config.distance} F${activeTab === 'z-axis' ? '300' : '3000'}\n`;
}
gcode += `M400\n; M92 ${axis}${calculateSteps(config)}\n; M500\n`;
}
gcode += '\nM104 S0\nM140 S0\nG28 X Y\nM84\n';
return gcode;
};
const downloadGCode = () => {
const blob = new Blob([generateGCode()], { type: 'text/plain' });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = `calibration_${activeTab}_${Date.now()}.gcode`;
a.click();
URL.revokeObjectURL(url);
};
const tabs = [
{ id: 'x-axis', name: 'X Ekseni', icon: Move },
{ id: 'y-axis', name: 'Y Ekseni', icon: Move },
{ id: 'z-axis', name: 'Z Ekseni', icon: Move },
{ id: 'extruder', name: 'Extruder', icon: Box },
{ id: 'skew', name: 'Çarpıklık', icon: Maximize2 }
];
const renderAxisCalibration = (config, setConfig, axis) => {
return e('div', null,
e('h3', { className: 'text-2xl font-semibold mb-4 text-cyan-400' }, `${axis} Ekseni Kalibrasyonu`),
e('div', { className: 'grid grid-cols-1 md:grid-cols-3 gap-4 mb-6' },
e('div', null,
e('label', { className: 'block text-sm text-slate-400 mb-1' }, 'Hedef Mesafe (mm)'),
e('input', {
type: 'number',
value: config.distance,
onChange: (ev) => setConfig({...config, distance: parseInt(ev.target.value)}),
className: 'w-full bg-slate-700 border border-slate-600 rounded px-3 py-2'
})
),
e('div', null,
e('label', { className: 'block text-sm text-slate-400 mb-1' }, 'Mevcut Steps/mm'),
e('input', {
type: 'number',
step: '0.01',
value: config.steps,
onChange: (ev) => setConfig({...config, steps: parseFloat(ev.target.value)}),
className: 'w-full bg-slate-700 border border-slate-600 rounded px-3 py-2'
})
),
e('div', null,
e('label', { className: 'block text-sm text-slate-400 mb-1' }, 'Ölçülen Mesafe (mm)'),
e('input', {
type: 'number',
step: '0.01',
value: config.measured,
onChange: (ev) => setConfig({...config, measured: parseFloat(ev.target.value)}),
className: 'w-full bg-slate-700 border border-slate-600 rounded px-3 py-2',
placeholder: 'Test sonrası giriniz'
})
)
),
config.measured > 0 && e('div', { className: 'bg-cyan-10 border border-cyan-30 rounded-lg p-4' },
e('h4', { className: 'font-semibold text-cyan-400 mb-2' }, 'Hesaplanan Değer:'),
e('p', { className: 'text-2xl font-bold text-cyan-300' }, `${calculateSteps(config)} steps/mm`)
)
);
};
return e('div', { className: 'min-h-screen bg-gradient text-white p-4' },
e('div', { className: 'max-w-6xl mx-auto' },
e('div', { className: 'text-center mb-8' },
e('h1', { className: 'text-4xl font-bold mb-2', style: { background: 'linear-gradient(135deg, #22d3ee 0%, #3b82f6 100%)', WebkitBackgroundClip: 'text', WebkitTextFillColor: 'transparent' } },
'3D Yazıcı Kalibrasyon'
),
e('p', { className: 'text-slate-400' }, 'Profesyonel Kalibrasyon ve G-code Üretici')
),
e('div', { className: 'bg-slate-800 backdrop-blur rounded-lg p-6 mb-6 border border-slate-700' },
e('div', { className: 'flex items-center gap-2 mb-4' },
e(Settings),
e('h2', { className: 'text-xl font-semibold' }, 'Genel Ayarlar')
),
e('div', { className: 'grid grid-cols-1 md:grid-cols-3 gap-4' },
e('div', null,
e('label', { className: 'block text-sm text-slate-400 mb-1' }, 'Tabla Sıcaklığı (°C)'),
e('input', {
type: 'number',
value: settings.bedTemp,
onChange: (ev) => setSettings({...settings, bedTemp: parseInt(ev.target.value)}),
className: 'w-full bg-slate-700 border border-slate-600 rounded px-3 py-2'
})
),
e('div', null,
e('label', { className: 'block text-sm text-slate-400 mb-1' }, 'Nozzle Sıcaklığı (°C)'),
e('input', {
type: 'number',
value: settings.nozzleTemp,
onChange: (ev) => setSettings({...settings, nozzleTemp: parseInt(ev.target.value)}),
className: 'w-full bg-slate-700 border border-slate-600 rounded px-3 py-2'
})
),
e('div', null,
e('label', { className: 'block text-sm text-slate-400 mb-1' }, 'Nozzle Çapı (mm)'),
e('input', {
type: 'number',
step: '0.1',
value: settings.nozzleDiameter,
onChange: (ev) => setSettings({...settings, nozzleDiameter: parseFloat(ev.target.value)}),
className: 'w-full bg-slate-700 border border-slate-600 rounded px-3 py-2'
})
)
)
),
e('div', { className: 'flex gap-2 mb-6 overflow-x-auto' },
tabs.map(tab => e('button', {
key: tab.id,
onClick: () => setActiveTab(tab.id),
className: `flex items-center gap-2 px-4 py-3 rounded-lg transition-all whitespace-nowrap ${activeTab === tab.id ? 'tab-active shadow-lg' : 'tab-inactive'}`
},
e(tab.icon),
tab.name
))
),
e('div', { className: 'bg-slate-800 backdrop-blur rounded-lg p-6 border border-slate-700 mb-6' },
activeTab === 'x-axis' && renderAxisCalibration(xAxisConfig, setXAxisConfig, 'X'),
activeTab === 'y-axis' && renderAxisCalibration(yAxisConfig, setYAxisConfig, 'Y'),
activeTab === 'z-axis' && renderAxisCalibration(zAxisConfig, setZAxisConfig, 'Z'),
activeTab === 'extruder' && renderAxisCalibration(extruderConfig, setExtruderConfig, 'Extruder'),
activeTab === 'skew' && e('div', null,
e('h3', { className: 'text-2xl font-semibold mb-4 text-cyan-400' }, 'Çarpıklık Kalibrasyonu'),
e('div', { className: 'grid grid-cols-1 md:grid-cols-3 gap-4 mb-6' },
['ac', 'bd', 'ad'].map((key, idx) => e('div', { key },
e('label', { className: 'block text-sm text-slate-400 mb-1' }, ['AC Köşegeni (mm)', 'BD Köşegeni (mm)', 'AD Köşegeni (mm)'][idx]),
e('input', {
type: 'number',
step: '0.01',
value: skewConfig[key],
onChange: (ev) => setSkewConfig({...skewConfig, [key]: ev.target.value}),
className: 'w-full bg-slate-700 border border-slate-600 rounded px-3 py-2'
})
))
),
e('div', { className: 'bg-cyan-10 border border-cyan-30 rounded-lg p-4' },
e('h4', { className: 'font-semibold text-cyan-400 mb-3' }, 'Hesaplanan Çarpıklık Değerleri:'),
e('div', { className: 'grid grid-cols-1 md:grid-cols-3 gap-4' },
['xy', 'xz', 'yz'].map(k => e('div', { key: k },
e('p', { className: 'text-sm text-slate-400' }, `${k.toUpperCase()} Çarpıklığı`),
e('p', { className: 'text-xl font-bold text-cyan-300' }, `${calculateSkew()[k]}°`)
))
)
)
)
),
e('div', { className: 'bg-slate-800 backdrop-blur rounded-lg p-6 border border-slate-700' },
e('div', { className: 'flex flex-col md:flex-row items-center justify-between gap-4' },
e('div', null,
e('h3', { className: 'text-lg font-semibold mb-1' }, 'G-code Oluştur'),
e('p', { className: 'text-sm text-slate-400' }, 'Seçili kalibrasyon için G-code dosyası indir')
),
e('button', {
onClick: downloadGCode,
className: 'flex items-center gap-2 bg-gradient-cyan px-6 py-3 rounded-lg font-semibold transition-all shadow-lg cursor-pointer'
},
e(Download),
'G-code İndir'
)
),
e('div', { className: 'mt-6' },
e('h4', { className: 'text-sm font-semibold text-slate-400 mb-2' }, 'G-code Önizleme:'),
e('div', { className: 'bg-slate-900 rounded-lg p-4 overflow-x-auto' },
e('pre', { className: 'text-xs text-green-400' }, generateGCode())
)
)
)
)
);
}
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(e(PrinterCalibration));
</script>
</body>
</html>