HTML5 Hesap Makinesi

 HTML5 Hesap Makinesi yapalım.


Özellikler :

  1. 9:16 Format & Telefon Çerçevesi: Masaüstünde şık bir akıllı telefon çerçevesinde, mobilde ise tam ekran duyarlı (responsive) olarak çalışır.

  2. 4 Canlı Tema Seçeneği: Neon Cyberpunk, Sunset Orange, Electric Purple ve Emerald Neon olmak üzere göze hitap eden canlı tema paletleri mevcuttur.

  3. Standart & Bilimsel Mod: Tek tuşla trigonometrik fonksiyonlar (sin, cos, tan), karekök, kare alma gibi gelişmiş bilimsel hesaplama moduna geçiş yapabilirsiniz.

  4. İşlem Geçmişi: Yapılan tüm işlemler hafızada tutulur, geçmiş panelinden eski sonuçlara tıklayarak tekrar işleme devam edebilirsiniz.

  5. Tamamen Çevrimdışı: Harici kütüphane gerektirmez, tüm veriler tarayıcınızın localStorage alanında güvenle saklanır.

Canlı Temalı Hesap Makinesi

Neon Calc

0

İşlem Geçmişi

Henüz geçmiş işlem yok.

<!DOCTYPE html>
<html lang="tr" class="h-full">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Canlı Temalı Hesap Makinesi</title>
    <!-- Tailwind CSS CDN -->
    <script src="https://cdn.tailwindcss.com"></script>
    <script>
        tailwind.config = {
            darkMode: 'class',
            theme: {
                extend: {
                    colors: {
                        cyber: { bg: '#0b0c10', card: '#1f2833', accent: '#66fcf1', text: '#c5c6c7', btn: '#1f2833', hover: '#45a29e' },
                        sunset: { bg: '#1a0933', card: '#2d124f', accent: '#ff758c', text: '#ffeb3b', btn: '#3d1b66', hover: '#ff758c' },
                        electric: { bg: '#0c071e', card: '#1d123d', accent: '#a855f7', text: '#f3e8ff', btn: '#2c1a59', hover: '#c084fc' },
                        emerald: { bg: '#021c1e', card: '#00332c', accent: '#10b981', text: '#e6fffa', btn: '#004d40', hover: '#34d399' }
                    }
                }
            }
        }
    </script>
    <style>
        @media (min-width: 640px) {
            .phone-frame {
                width: 100%;
                max-width: 400px;
                height: 85vh;
                max-height: 820px;
                box-shadow: 0 25px 60px -15px rgba(0, 0, 0, 0.6);
                border-radius: 2.5rem;
                border: 8px solid rgba(255, 255, 255, 0.1);
                overflow: hidden;
            }
        }
        @media (max-width: 639px) {
            .phone-frame {
                width: 100vw;
                height: 100vh;
                border-radius: 0;
            }
        }
        .btn-press:active {
            transform: scale(0.93);
        }
        ::-webkit-scrollbar { width: 4px; }
        ::-webkit-scrollbar-track { background: transparent; }
        ::-webkit-scrollbar-thumb { background: rgba(255,255,255,0.2); border-radius: 10px; }
    </style>
</head>
<body class="h-full flex items-center justify-center transition-colors duration-500" id="bodyBg" style="background-color: #0b0c10;">

    <!-- 9:16 Telefon Çerçevesi -->
    <div id="appContainer" class="phone-frame flex flex-col relative transition-all duration-500 shadow-2xl bg-[#0b0c10] text-[#c5c6c7]">
        
        <!-- Üst Bilgi Çubuğu -->
        <header class="px-6 py-4 flex items-center justify-between border-b border-white/10 z-10">
            <div class="flex items-center space-x-2">
                <span id="appLogo" class="text-xl">⚡</span>
                <h1 id="appTitle" class="font-bold text-sm tracking-wider uppercase">Neon Calc</h1>
            </div>
            
            <div class="flex items-center space-x-2">
                <!-- Mod Değiştir (Standart / Bilimsel) -->
                <button onclick="toggleMode()" id="modeBtn" class="px-2.5 py-1 rounded-lg text-xs font-semibold border border-white/20 transition hover:scale-105 active:scale-95">
                    Bilimsel
                </button>
                <!-- Geçmiş Butonu -->
                <button onclick="toggleHistory()" class="p-2 rounded-xl border border-white/20 transition hover:scale-105 active:scale-95" title="Geçmiş">
                    📜
                </button>
                <!-- Tema Menüsü Butonu -->
                <button onclick="toggleThemeModal()" class="p-2 rounded-xl border border-white/20 transition hover:scale-105 active:scale-95" title="Temalar">
                    🎨
                </button>
            </div>
        </header>

        <!-- Ekran (Display) Alanı -->
        <div class="px-6 py-5 flex flex-col justify-end items-end border-b border-white/10 bg-black/20" style="min-height: 140px;">
            <div id="historyDisplay" class="text-xs opacity-60 tracking-wider mb-1 truncate w-full text-right font-mono"></div>
            <div id="mainDisplay" class="text-4xl font-bold tracking-tight truncate w-full text-right font-mono transition-all">0</div>
        </div>

        <!-- Ana Tuş Takımı / Hesap Makinesi Gövdesi -->
        <div class="flex-1 p-5 flex flex-col justify-between overflow-y-auto">
            
            <!-- Standart & Bilimsel Buton Grid -->
            <div id="keypadGrid" class="grid grid-cols-4 gap-3 my-auto">
                <!-- Dinamik olarak doldurulacak -->
            </div>
        </div>

        <!-- Geçmiş Paneli (Slide-over) -->
        <div id="historyPanel" class="absolute inset-x-0 bottom-0 top-[70px] bg-inherit z-20 transform translate-y-full transition-transform duration-300 ease-in-out flex flex-col p-5 border-t border-white/10 shadow-2xl">
            <div class="flex justify-between items-center mb-4">
                <h2 class="font-bold text-sm uppercase tracking-wider">İşlem Geçmişi</h2>
                <div class="space-x-2">
                    <button onclick="clearHistory()" class="text-xs opacity-70 hover:opacity-100 px-2 py-1 border border-white/20 rounded-lg">Temizle</button>
                    <button onclick="toggleHistory()" class="text-xs opacity-70 hover:opacity-100 font-bold px-2 py-1">✕ Kapat</button>
                </div>
            </div>
            <div id="historyList" class="flex-1 overflow-y-auto space-y-2 pr-1">
                <div class="text-center opacity-40 text-xs py-10">Henüz geçmiş işlem yok.</div>
            </div>
        </div>

        <!-- Tema Seçim Paneli (Modal) -->
        <div id="themeModal" class="absolute inset-0 z-30 bg-black/70 backdrop-blur-sm hidden flex items-center justify-center p-6">
            <div class="w-full max-w-xs rounded-2xl p-5 shadow-2xl border border-white/20 bg-slate-900 text-white" id="themeModalContent">
                <div class="flex justify-between items-center mb-4">
                    <h3 class="font-bold text-sm tracking-wide">Tema Seçin</h3>
                    <button onclick="toggleThemeModal()" class="text-xs opacity-70 hover:opacity-100 font-bold px-2 py-1">✕ Kapat</button>
                </div>
                <div class="space-y-2.5">
                    <button onclick="setTheme('cyber')" class="w-full flex items-center justify-between p-3 rounded-xl border border-white/10 bg-[#1f2833] text-[#66fcf1] font-semibold text-sm transition hover:scale-[1.02]">
                        <span class="flex items-center space-x-2"><span>⚡</span><span>Neon Cyberpunk</span></span>
                        <span class="w-4 h-4 rounded-full bg-[#66fcf1]"></span>
                    </button>
                    <button onclick="setTheme('sunset')" class="w-full flex items-center justify-between p-3 rounded-xl border border-white/10 bg-[#2d124f] text-[#ff758c] font-semibold text-sm transition hover:scale-[1.02]">
                        <span class="flex items-center space-x-2"><span>🌅</span><span>Sunset Orange</span></span>
                        <span class="w-4 h-4 rounded-full bg-[#ff758c]"></span>
                    </button>
                    <button onclick="setTheme('electric')" class="w-full flex items-center justify-between p-3 rounded-xl border border-white/10 bg-[#1d123d] text-[#c084fc] font-semibold text-sm transition hover:scale-[1.02]">
                        <span class="flex items-center space-x-2"><span>🔮</span><span>Electric Purple</span></span>
                        <span class="w-4 h-4 rounded-full bg-[#a855f7]"></span>
                    </button>
                    <button onclick="setTheme('emerald')" class="w-full flex items-center justify-between p-3 rounded-xl border border-white/10 bg-[#00332c] text-[#34d399] font-semibold text-sm transition hover:scale-[1.02]">
                        <span class="flex items-center space-x-2"><span>💎</span><span>Emerald Neon</span></span>
                        <span class="w-4 h-4 rounded-full bg-[#10b981]"></span>
                    </button>
                </div>
            </div>
        </div>

    </div>

    <!-- JavaScript Hesap Makinesi Mantığı -->
    <script>
        // Uygulama Durumu
        let currentInput = '0';
        let historyExpression = '';
        let isScientific = false;
        let currentTheme = localStorage.getItem('calc_theme') || 'cyber';
        let historyList = JSON.parse(localStorage.getItem('calc_history') || '[]');

        // Temalar Tanımı
        const themes = {
            cyber: { bg: '#0b0c10', card: '#1f2833', accent: '#66fcf1', text: '#c5c6c7', btnBg: '#1f2833', btnHover: '#2c3847', opBg: '#2c3847' },
            sunset: { bg: '#1a0933', card: '#2d124f', accent: '#ff758c', text: '#ffeb3b', btnBg: '#3d1b66', btnHover: '#4d237d', opBg: '#57227d' },
            electric: { bg: '#0c071e', card: '#1d123d', accent: '#c084fc', text: '#f3e8ff', btnBg: '#2c1a59', btnHover: '#3b2473', opBg: '#4c2e8a' },
            emerald: { bg: '#021c1e', card: '#00332c', accent: '#34d399', text: '#e6fffa', btnBg: '#004d40', btnHover: '#006655', opBg: '#005f53' }
        };

        window.onload = function() {
            setTheme(currentTheme);
            renderKeypad();
            updateDisplay();
        };

        // Tema Uygulama
        function setTheme(themeName) {
            currentTheme = themeName;
            localStorage.setItem('calc_theme', themeName);
            const t = themes[themeName];

            const container = document.getElementById('appContainer');
            container.style.backgroundColor = t.bg;
            container.style.color = t.text;
            document.getElementById('bodyBg').style.backgroundColor = t.bg;
            document.getElementById('themeModal').classList.add('hidden');
            renderKeypad();
        }

        function toggleThemeModal() {
            const modal = document.getElementById('themeModal');
            modal.classList.toggle('hidden');
        }

        // Mod Değiştirme (Standart / Bilimsel)
        function toggleMode() {
            isScientific = !isScientific;
            document.getElementById('modeBtn').innerText = isScientific ? 'Standart' : 'Bilimsel';
            renderKeypad();
        }

        // Tuş Takımı Oluşturucu
        function renderKeypad() {
            const grid = document.getElementById('keypadGrid');
            grid.innerHTML = '';
            const t = themes[currentTheme];

            let buttons = [];
            if (isScientific) {
                grid.className = "grid grid-cols-4 gap-2.5 my-auto";
                buttons = [
                    { label: 'sin', action: 'sci', val: 'Math.sin(' },
                    { label: 'cos', action: 'sci', val: 'Math.cos(' },
                    { label: 'tan', action: 'sci', val: 'Math.tan(' },
                    { label: 'π', action: 'num', val: 'Math.PI' },
                    { label: 'x²', action: 'sci', val: '**2' },
                    { label: '√', action: 'sci', val: 'Math.sqrt(' },
                    { label: '(', action: 'num', val: '(' },
                    { label: ')', action: 'num', val: ')' },
                    { label: 'C', action: 'clear', class: 'text-red-400 font-bold' },
                    { label: '⌫', action: 'backspace' },
                    { label: '%', action: 'num', val: '/100' },
                    { label: '÷', action: 'op', val: '/' },
                    { label: '7', action: 'num', val: '7' },
                    { label: '8', action: 'num', val: '8' },
                    { label: '9', action: 'num', val: '9' },
                    { label: '×', action: 'op', val: '*' },
                    { label: '4', action: 'num', val: '4' },
                    { label: '5', action: 'num', val: '5' },
                    { label: '6', action: 'num', val: '6' },
                    { label: '-', action: 'op', val: '-' },
                    { label: '1', action: 'num', val: '1' },
                    { label: '2', action: 'num', val: '2' },
                    { label: '3', action: 'num', val: '3' },
                    { label: '+', action: 'op', val: '+' },
                    { label: '0', action: 'num', val: '0', span: 'col-span-2' },
                    { label: '.', action: 'num', val: '.' },
                    { label: '=', action: 'calculate', class: 'text-white font-bold shadow-lg' }
                ];
            } else {
                grid.className = "grid grid-cols-4 gap-3 my-auto";
                buttons = [
                    { label: 'C', action: 'clear', class: 'text-red-400 font-bold' },
                    { label: '(', action: 'num', val: '(' },
                    { label: ')', action: 'num', val: ')' },
                    { label: '÷', action: 'op', val: '/' },
                    { label: '7', action: 'num', val: '7' },
                    { label: '8', action: 'num', val: '8' },
                    { label: '9', action: 'num', val: '9' },
                    { label: '×', action: 'op', val: '*' },
                    { label: '4', action: 'num', val: '4' },
                    { label: '5', action: 'num', val: '5' },
                    { label: '6', action: 'num', val: '6' },
                    { label: '-', action: 'op', val: '-' },
                    { label: '1', action: 'num', val: '1' },
                    { label: '2', action: 'num', val: '2' },
                    { label: '3', action: 'num', val: '3' },
                    { label: '+', action: 'op', val: '+' },
                    { label: '0', action: 'num', val: '0', span: 'col-span-2' },
                    { label: '.', action: 'num', val: '.' },
                    { label: '=', action: 'calculate', class: 'text-white font-bold shadow-lg' }
                ];
            }

            buttons.forEach(btn => {
                const buttonEl = document.createElement('button');
                buttonEl.innerText = btn.label;
                buttonEl.className = `btn-press py-3.5 rounded-2xl text-sm font-semibold transition-all duration-150 flex items-center justify-center shadow-sm select-none ${btn.span || ''} ${btn.class || ''}`;
                
                if (btn.action === 'calculate') {
                    buttonEl.style.backgroundColor = t.accent;
                    buttonEl.style.color = '#000000';
                } else {
                    buttonEl.style.backgroundColor = t.btnBg;
                    buttonEl.style.color = t.text;
                }

                buttonEl.onclick = () => handleButton(btn);
                grid.appendChild(buttonEl);
            });
        }

        // Tuş Tıklama Mantığı
        function handleButton(btn) {
            // Hafif titreşim desteği (mobil cihazlar için)
            if (navigator.vibrate) navigator.vibrate(15);

            if (btn.action === 'num' || btn.action === 'sci') {
                if (currentInput === '0' && !isNaN(btn.val)) {
                    currentInput = btn.val;
                } else {
                    currentInput += btn.val;
                }
            } else if (btn.action === 'op') {
                currentInput += ' ' + btn.label + ' ';
            } else if (btn.action === 'clear') {
                currentInput = '0';
                historyExpression = '';
            } else if (btn.action === 'backspace') {
                if (currentInput.length > 1) {
                    currentInput = currentInput.trim().slice(0, -1);
                } else {
                    currentInput = '0';
                }
            } else if (btn.action === 'calculate') {
                calculateResult();
            }
            updateDisplay();
        }

        // Hesaplama Fonksiyonu
        function calculateResult() {
            try {
                historyExpression = currentInput;
                // Matematiksel sembolleri JS formatına çevir
                let evalString = currentInput
                    .replace(/×/g, '*')
                    .replace(/÷/g, '/');

                let result = eval(evalString);
                if (isNaN(result) || !isFinite(result)) {
                    throw new Error("Geçersiz işlem");
                }

                // Sonucu yuvarla (hassasiyet hatası önlemek için)
                result = parseFloat(result.toFixed(8));

                // Geçmişe ekle
                addToHistory(historyExpression, result);

                currentInput = result.toString();
                historyExpression = '';
            } catch (error) {
                currentInput = 'Hata';
                setTimeout(() => { currentInput = '0'; updateDisplay(); }, 1200);
            }
        }

        function updateDisplay() {
            document.getElementById('mainDisplay').innerText = currentInput;
            document.getElementById('historyDisplay').innerText = historyExpression;
        }

        // Geçmiş Yönetimi
        function addToHistory(expr, res) {
            historyList.unshift({ expr: expr, res: res });
            if (historyList.length > 20) historyList.pop();
            localStorage.setItem('calc_history', JSON.stringify(historyList));
            renderHistoryList();
        }

        function toggleHistory() {
            const panel = document.getElementById('historyPanel');
            const isClosed = panel.style.transform === 'translateY(0px)' || panel.style.transform === '';
            panel.style.transform = isClosed ? 'translateY(0)' : 'translateY(100%)';
            if (isClosed) renderHistoryList();
        }

        function renderHistoryList() {
            const listEl = document.getElementById('historyList');
            listEl.innerHTML = '';

            if (historyList.length === 0) {
                listEl.innerHTML = '<div class="text-center opacity-40 text-xs py-10">Henüz geçmiş işlem yok.</div>';
                return;
            }

            historyList.forEach(item => {
                const div = document.createElement('div');
                div.className = "p-3 rounded-xl border border-white/10 bg-black/20 flex flex-col items-end cursor-pointer hover:bg-white/5 transition";
                div.onclick = () => {
                    currentInput = item.res.toString();
                    toggleHistory();
                    updateDisplay();
                };
                div.innerHTML = `
                    <span class="text-xs opacity-60 font-mono">${item.expr}</span>
                    <span class="text-sm font-bold font-mono">${item.res}</span>
                `;
                listEl.appendChild(div);
            });
        }

        function clearHistory() {
            historyList = [];
            localStorage.removeItem('calc_history');
            renderHistoryList();
        }
    </script>
</body>
</html>


ÖNEMLİ NOT:

Kodun  en üst tarafında yer alan:
<script src="https://cdn.tailwindcss.com"></script>  
satırı internete bağımlı çalışır. 
tailwindcss.js
dosyasını internetten indirip html dosyasının yanına koyup satırı şu şekilde değiştirirseniz:
<script src="tailwindcss.js"></script>   
tamamen localde çalışırsınız.


Yorumlar