CoolFace
Apppublic

turkeywu/facecombin

sourceHugging Faceupdated 3mo agoView on Hugging Face
0likes
index.html652 linesDownload Raw Back to face combin
1<!DOCTYPE html>2<html lang="zh-TW">3<head>4    <meta charset="UTF-8">5    <meta name="viewport" content="width=device-width, initial-scale=1.0">6    <title>人臉組合遊戲</title>7    <style>8        * {9            margin: 0;10            padding: 0;11            box-sizing: border-box;12            font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;13        }14        15        body {16            background: linear-gradient(135deg, #1a2a6c, #b21f1f, #fdbb2d);17            color: white;18            min-height: 100vh;19            display: flex;20            flex-direction: column;21            align-items: center;22            padding: 2rem;23        }24        25        .container {26            max-width: 1200px;27            width: 100%;28            text-align: center;29        }30        31        h1 {32            font-size: 2.5rem;33            margin-bottom: 1rem;34            text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.3);35        }36        37        .description {38            font-size: 1.2rem;39            margin-bottom: 2rem;40            max-width: 700px;41            margin-left: auto;42            margin-right: auto;43            line-height: 1.6;44        }45        46        .game-area {47            display: flex;48            justify-content: center;49            gap: 2rem;50            margin-bottom: 2rem;51        }52        53        .face-container {54            width: 400px;55            height: 500px;56            background-color: rgba(255, 255, 255, 0.1);57            border-radius: 15px;58            position: relative;59            overflow: visible;60            box-shadow: 0 10px 30px rgba(0, 0, 0, 0.3);61            border: 2px solid rgba(255, 255, 255, 0.2);62        }63        64        .face-part {65            position: absolute;66            width: 100%;67            display: flex;68            justify-content: center;69            align-items: center;70            overflow: hidden;71            cursor: move;72            transition: transform 0.2s ease;73        }74        75        .face-part.dragging {76            cursor: grabbing;77            z-index: 100;78        }79        80        .face-part.selected {81            outline: 2px dashed #ffeb3b;82            outline-offset: 2px;83        }84        85        /* 確保額頭在最上層 */86        .forehead {87            top: 0;88            height: 35%;89            z-index: 30;90        }91        92        .eyes-nose {93            top: 30%;94            height: 45%;95            z-index: 20;96        }97        98        .mouth-chin {99            bottom: 0;100            height: 35%;101            z-index: 10;102        }103        104        .face-part img {105            max-width: 100%;106            max-height: 100%;107            object-fit: contain;108            pointer-events: none;109            transition: transform 0.3s ease;110        }111        112        .right-panel {113            display: flex;114            flex-direction: column;115            gap: 1.5rem;116            width: 300px;117        }118        119        .controls {120            display: flex;121            flex-direction: column;122            gap: 1rem;123        }124        125        button {126            padding: 12px 30px;127            font-size: 1.2rem;128            border: none;129            border-radius: 50px;130            background: linear-gradient(to right, #ff7e5f, #feb47b);131            color: white;132            cursor: pointer;133            transition: all 0.3s ease;134            box-shadow: 0 4px 15px rgba(0, 0, 0, 0.2);135            font-weight: bold;136        }137        138        button:hover {139            transform: translateY(-3px);140            box-shadow: 0 7px 20px rgba(0, 0, 0, 0.3);141        }142        143        button:active {144            transform: translateY(1px);145        }146        147        button:disabled {148            background: #cccccc;149            cursor: not-allowed;150            transform: none;151            box-shadow: none;152        }153        154        .result-message {155            margin-top: 1.5rem;156            font-size: 1.3rem;157            font-weight: bold;158            min-height: 2rem;159            text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.5);160        }161        162        .reset-position {163            margin-top: 10px;164            padding: 8px 16px;165            font-size: 0.9rem;166        }167        168        .scale-controls {169            display: flex;170            flex-direction: column;171            gap: 1rem;172            margin-top: 1rem;173            width: 100%;174        }175        176        .scale-control-group {177            display: flex;178            justify-content: space-between;179            align-items: center;180            background: rgba(255, 255, 255, 0.1);181            padding: 10px 15px;182            border-radius: 10px;183        }184        185        .scale-label {186            font-size: 1rem;187            font-weight: bold;188        }189        190        .scale-buttons {191            display: flex;192            gap: 0.5rem;193        }194        195        .scale-btn {196            padding: 6px 12px;197            font-size: 0.9rem;198        }199        200        .instructions {201            margin-top: 1rem;202            font-size: 0.9rem;203            color: rgba(255, 255, 255, 0.8);204            max-width: 400px;205        }206        207        .current-selection {208            margin-top: 1rem;209            font-size: 1rem;210            color: #ffeb3b;211            min-height: 1.5rem;212        }213        214        @media (max-width: 768px) {215            .game-area {216                flex-direction: column;217                align-items: center;218            }219            220            .right-panel {221                width: 100%;222                max-width: 400px;223            }224            225            .face-container {226                width: 300px;227                height: 400px;228            }229            230            .scale-control-group {231                flex-direction: column;232                gap: 0.5rem;233            }234        }235    </style>236</head>237<body>238    <div class="container">239        <h1>人臉組合遊戲</h1>240        <p class="description">按下開始按鈕,隨機組合額頭、眼睛鼻子、嘴巴下巴,創造獨一無二的新面孔!</p>241        242        <div class="game-area">243            <div class="face-container" id="face-container">244                <div class="face-part forehead" id="forehead-part">245                    <img id="forehead-img" src="data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMzAwIiBoZWlnaHQ9IjEyMCIgdmlld0JveD0iMCAwIDMwMCAxMjAiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CjxyZWN0IHdpZHRoPSIzMDAiIGhlaWdodD0iMTIwIiBmaWxsPSIjNGE5MGUyIi8+Cjx0ZXh0IHg9IjE1MCIgeT0iNjAiIGZvbnQtZmFtaWx5PSJBcmlhbCIgZm9udC1zaXplPSIxNCIgZmlsbD0id2hpdGUiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGRvbWluYW50LWJhc2VsaW5lPSJtaWRkbGUiPuiPnOWHuzwvdGV4dD4KPC9zdmc+" alt="額頭">246                </div>247                <div class="face-part eyes-nose" id="eyes-nose-part">248                    <img id="eyes-nose-img" src="data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMzAwIiBoZWlnaHQ9IjE2MCIgdmlld0JveD0iMCAwIDMwMCAxNjAiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CjxyZWN0IHdpZHRoPSIzMDAiIGhlaWdodD0iMTYwIiBmaWxsPSIjN2VkMzIxIi8+Cjx0ZXh0IHg9IjE1MCIgeT0iODAiIGZvbnQtZmFtaWx5PSJBcmlhbCIgZm9udC1zaXplPSIxNCIgZmlsbD0id2hpdGUiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGRvbWluYW50LWJhc2VsaW5lPSJtaWRkbGUiPuihqOi/nOaUueiPnDwvdGV4dD4KPC9zdmc+" alt="眼睛鼻子">249                </div>250                <div class="face-part mouth-chin" id="mouth-chin-part">251                    <img id="mouth-chin-img" src="data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMzAwIiBoZWlnaHQ9IjEyMCIgdmlld0JveD0iMCAwIDMwMCAxMjAiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CjxyZWN0IHdpZHRoPSIzMDAiIGhlaWdodD0iMTIwIiBmaWxsPSIjZDAwMjFiIi8+Cjx0ZXh0IHg9IjE1MCIgeT0iNjAiIGZvbnQtZmFtaWx5PSJBcmlhbCIgZm9udC1zaXplPSIxNCIgZmlsbD0id2hpdGUiI116leHQtYW5jaG9yPSJtaWRkbGUiIGRvbWluYW50LWJhc2VsaW5lPSJtaWRkbGUiPuWNl+WbnuWnkzwvdGV4dD4KPC9zdmc+" alt="嘴巴下巴">252                </div>253            </div>254            255            <div class="right-panel">256                <div class="current-selection" id="current-selection">257                    點擊選擇要調整的部位258                </div>259                260                <div class="scale-controls">261                    <div class="scale-control-group">262                        <div class="scale-label">額頭</div>263                        <div class="scale-buttons">264                            <button class="scale-btn" data-part="forehead" data-action="zoom-out">縮小</button>265                            <button class="scale-btn" data-part="forehead" data-action="reset">重置</button>266                            <button class="scale-btn" data-part="forehead" data-action="zoom-in">放大</button>267                        </div>268                    </div>269                    270                    <div class="scale-control-group">271                        <div class="scale-label">眼睛鼻子</div>272                        <div class="scale-buttons">273                            <button class="scale-btn" data-part="eyesNose" data-action="zoom-out">縮小</button>274                            <button class="scale-btn" data-part="eyesNose" data-action="reset">重置</button>275                            <button class="scale-btn" data-part="eyesNose" data-action="zoom-in">放大</button>276                        </div>277                    </div>278                    279                    <div class="scale-control-group">280                        <div class="scale-label">嘴巴下巴</div>281                        <div class="scale-buttons">282                            <button class="scale-btn" data-part="mouthChin" data-action="zoom-out">縮小</button>283                            <button class="scale-btn" data-part="mouthChin" data-action="reset">重置</button>284                            <button class="scale-btn" data-part="mouthChin" data-action="zoom-in">放大</button>285                        </div>286                    </div>287                </div>288                289                <button class="reset-position" id="reset-position-btn">重置所有位置與大小</button>290                291                <div class="controls">292                    <button id="start-btn">開始組合</button>293                    <button id="stop-btn" disabled>停止組合</button>294                </div>295                296                <div class="result-message" id="result-message">297                    按下開始按鈕創造新面孔!298                </div>299                300                <div class="instructions">301                    提示:點擊選擇要調整的部位,然後使用縮放按鈕調整大小,或直接拖動調整位置302                </div>303            </div>304        </div>305    </div>306 307    <script>308        // 圖片資料庫 - 根據您的資料夾結構309        const faceParts = {310            forehead: [],311            eyesNose: [],312            mouthChin: []313        };314 315        // 初始化圖片路徑316        function initImagePaths() {317            // 額頭圖片路徑 (head資料夾)318            for (let i = 1; i <= 28; i++) {319                faceParts.forehead.push({320                    id: i,321                    src: `combind/head/${i}.jpg`322                });323            }324            325            // 眼睛鼻子圖片路徑 (eye資料夾)326            for (let i = 1; i <= 28; i++) {327                faceParts.eyesNose.push({328                    id: i,329                    src: `combind/eye/${i}.jpg`330                });331            }332            333            // 嘴巴下巴圖片路徑 (mouse資料夾)334            for (let i = 1; i <= 28; i++) {335                faceParts.mouthChin.push({336                    id: i,337                    src: `combind/mouse/${i}.jpg`338                });339            }340        }341 342        // DOM元素343        const startBtn = document.getElementById('start-btn');344        const stopBtn = document.getElementById('stop-btn');345        const resultMessage = document.getElementById('result-message');346        const resetPositionBtn = document.getElementById('reset-position-btn');347        const currentSelectionText = document.getElementById('current-selection');348        const faceContainer = document.getElementById('face-container');349        350        // 臉部部位元素351        const foreheadImg = document.getElementById('forehead-img');352        const eyesNoseImg = document.getElementById('eyes-nose-img');353        const mouthChinImg = document.getElementById('mouth-chin-img');354        355        // 臉部部位容器元素356        const foreheadPart = document.getElementById('forehead-part');357        const eyesNosePart = document.getElementById('eyes-nose-part');358        const mouthChinPart = document.getElementById('mouth-chin-part');359        360        // 遊戲狀態361        let isSpinning = false;362        let spinInterval;363        let currentSelection = {364            forehead: 0,365            eyesNose: 0,366            mouthChin: 0367        };368        369        // 拖動狀態370        let isDragging = false;371        let currentDraggingPart = null;372        let dragOffset = { x: 0, y: 0 };373        374        // 縮放狀態375        let scaleFactors = {376            forehead: 1,377            eyesNose: 1,378            mouthChin: 1379        };380        381        // 當前選中的部位382        let selectedPart = null;383        384        // 初始化遊戲385        function initGame() {386            // 初始化圖片路徑387            initImagePaths();388            389            // 設置初始圖片390            updateFace();391            392            // 設置拖動事件393            setupDragging();394            395            // 設置縮放按鈕事件396            setupScaleButtons();397            398            // 事件監聽399            startBtn.addEventListener('click', startSpinning);400            stopBtn.addEventListener('click', stopSpinning);401            resetPositionBtn.addEventListener('click', resetAll);402            403            // 初始選擇第一個部位404            selectPart('forehead');405        }406        407        // 設置拖動功能408        function setupDragging() {409            const parts = [foreheadPart, eyesNosePart, mouthChinPart];410            411            parts.forEach(part => {412                // 鼠標按下事件413                part.addEventListener('mousedown', (e) => {414                    startDrag(e);415                    // 點擊時選擇該部位416                    const partId = part.id.replace('-part', '');417                    selectPart(partId);418                });419                420                // 觸摸設備支持421                part.addEventListener('touchstart', (e) => {422                    startDrag(e);423                    // 點擊時選擇該部位424                    const partId = part.id.replace('-part', '');425                    selectPart(partId);426                }, { passive: false });427            });428            429            // 鼠標移動事件430            document.addEventListener('mousemove', drag);431            document.addEventListener('touchmove', drag, { passive: false });432            433            // 鼠標釋放事件434            document.addEventListener('mouseup', endDrag);435            document.addEventListener('touchend', endDrag);436        }437        438        // 設置縮放按鈕事件439        function setupScaleButtons() {440            const scaleButtons = document.querySelectorAll('.scale-btn');441            442            scaleButtons.forEach(button => {443                button.addEventListener('click', () => {444                    const part = button.dataset.part;445                    const action = button.dataset.action;446                    447                    // 選擇對應的部位448                    selectPart(part);449                    450                    // 執行對應的操作451                    if (action === 'zoom-in') {452                        zoomPart(part, 0.1);453                    } else if (action === 'zoom-out') {454                        zoomPart(part, -0.1);455                    } else if (action === 'reset') {456                        resetPartScale(part);457                    }458                });459            });460        }461        462        // 選擇部位463        function selectPart(partId) {464            // 移除所有部位的選中狀態465            foreheadPart.classList.remove('selected');466            eyesNosePart.classList.remove('selected');467            mouthChinPart.classList.remove('selected');468            469            // 設置當前選中的部位470            selectedPart = partId;471            472            // 添加選中狀態473            if (partId === 'forehead') {474                foreheadPart.classList.add('selected');475                currentSelectionText.textContent = '當前選擇: 額頭';476            } else if (partId === 'eyesNose') {477                eyesNosePart.classList.add('selected');478                currentSelectionText.textContent = '當前選擇: 眼睛鼻子';479            } else if (partId === 'mouthChin') {480                mouthChinPart.classList.add('selected');481                currentSelectionText.textContent = '當前選擇: 嘴巴下巴';482            }483        }484        485        // 開始拖動486        function startDrag(e) {487            e.preventDefault();488            isDragging = true;489            currentDraggingPart = e.currentTarget;490            currentDraggingPart.classList.add('dragging');491            492            // 計算偏移量493            const rect = currentDraggingPart.getBoundingClientRect();494            if (e.type === 'mousedown') {495                dragOffset.x = e.clientX - rect.left;496                dragOffset.y = e.clientY - rect.top;497            } else if (e.type === 'touchstart') {498                dragOffset.x = e.touches[0].clientX - rect.left;499                dragOffset.y = e.touches[0].clientY - rect.top;500            }501        }502        503        // 拖動中504        function drag(e) {505            if (!isDragging || !currentDraggingPart) return;506            507            e.preventDefault();508            509            let clientX, clientY;510            if (e.type === 'mousemove') {511                clientX = e.clientX;512                clientY = e.clientY;513            } else if (e.type === 'touchmove') {514                clientX = e.touches[0].clientX;515                clientY = e.touches[0].clientY;516            }517            518            // 計算新位置519            const containerRect = faceContainer.getBoundingClientRect();520            const newLeft = clientX - containerRect.left - dragOffset.x;521            const newTop = clientY - containerRect.top - dragOffset.y;522            523            // 擴大移動範圍 - 允許元素移出容器524            const maxLeft = containerRect.width + 100;525            const maxTop = containerRect.height + 100;526            527            const boundedLeft = Math.max(-100, Math.min(maxLeft, newLeft));528            const boundedTop = Math.max(-100, Math.min(maxTop, newTop));529            530            // 應用新位置531            currentDraggingPart.style.left = `${boundedLeft}px`;532            currentDraggingPart.style.top = `${boundedTop}px`;533        }534        535        // 結束拖動536        function endDrag() {537            if (isDragging && currentDraggingPart) {538                currentDraggingPart.classList.remove('dragging');539            }540            isDragging = false;541            currentDraggingPart = null;542        }543        544        // 重置所有位置和大小545        function resetAll() {546            // 重置位置547            foreheadPart.style.left = '0px';548            foreheadPart.style.top = '0px';549            eyesNosePart.style.left = '0px';550            eyesNosePart.style.top = '175px';551            mouthChinPart.style.left = '0px';552            mouthChinPart.style.top = '325px';553            554            // 重置縮放555            scaleFactors = {556                forehead: 1,557                eyesNose: 1,558                mouthChin: 1559            };560            561            // 應用縮放重置562            applyScale();563            564            // 重置選擇565            selectPart('forehead');566        }567        568        // 重置特定部位的縮放569        function resetPartScale(part) {570            scaleFactors[part] = 1;571            applyScale();572        }573        574        // 縮放特定部位575        function zoomPart(part, delta) {576            scaleFactors[part] = Math.max(0.5, Math.min(2, scaleFactors[part] + delta));577            applyScale();578        }579        580        // 應用縮放581        function applyScale() {582            foreheadImg.style.transform = `scale(${scaleFactors.forehead})`;583            eyesNoseImg.style.transform = `scale(${scaleFactors.eyesNose})`;584            mouthChinImg.style.transform = `scale(${scaleFactors.mouthChin})`;585        }586        587        // 創建佔位圖片588        function createPlaceholderImage(text, color) {589            const svg = `<svg width="300" height="120" viewBox="0 0 300 120" fill="none" xmlns="http://www.w3.org/2000/svg">590                <rect width="300" height="120" fill="${color}"/>591                <text x="150" y="60" font-family="Arial" font-size="14" fill="white" text-anchor="middle" dominant-baseline="middle">${text}</text>592            </svg>`;593            return 'data:image/svg+xml;base64,' + btoa(svg);594        }595        596        // 開始旋轉597        function startSpinning() {598            if (isSpinning) return;599            600            isSpinning = true;601            startBtn.disabled = true;602            stopBtn.disabled = false;603            resultMessage.textContent = "組合中...";604            605            // 隨機選擇臉部部位606            spinInterval = setInterval(() => {607                currentSelection.forehead = Math.floor(Math.random() * faceParts.forehead.length);608                currentSelection.eyesNose = Math.floor(Math.random() * faceParts.eyesNose.length);609                currentSelection.mouthChin = Math.floor(Math.random() * faceParts.mouthChin.length);610                611                // 更新臉部圖片612                updateFace();613            }, 100); // 每100ms更新一次614        }615        616        // 停止旋轉617        function stopSpinning() {618            if (!isSpinning) return;619            620            clearInterval(spinInterval);621            isSpinning = false;622            startBtn.disabled = false;623            stopBtn.disabled = true;624            625            // 顯示結果訊息626            resultMessage.textContent = "新面孔創造成功!";627        }628        629        // 更新臉部圖片630        function updateFace() {631            // 設置圖片並添加錯誤處理632            foreheadImg.src = faceParts.forehead[currentSelection.forehead].src;633            foreheadImg.onerror = function() {634                this.src = createPlaceholderImage('額頭', '#4a90e2');635            };636            637            eyesNoseImg.src = faceParts.eyesNose[currentSelection.eyesNose].src;638            eyesNoseImg.onerror = function() {639                this.src = createPlaceholderImage('眼睛鼻子', '#7ed321');640            };641            642            mouthChinImg.src = faceParts.mouthChin[currentSelection.mouthChin].src;643            mouthChinImg.onerror = function() {644                this.src = createPlaceholderImage('嘴巴下巴', '#d0021b');645            };646        }647        648        // 初始化遊戲649        window.onload = initGame;650    </script>651</body>652</html>