將改進混亂時鐘的網頁版

分享和讨论Javascript相关的话题
头像
ejsoon
一枝独秀
一枝独秀
帖子: 5192
注册时间: 2022年 11月 18日 17:36
为圈友点赞: 175 次
被圈友点赞: 204 次
联系:

Re: 將改進混亂時鐘的網頁版

帖子 ejsoon »

當有圖片處於「自動保存」狀態時,點擊一個圖標,它應該是上載,而不是切換所保存的圖片。
https://ejsoon.vip/
弈趣極光:享受思維樂趣
头像
ejsoon
一枝独秀
一枝独秀
帖子: 5192
注册时间: 2022年 11月 18日 17:36
为圈友点赞: 175 次
被圈友点赞: 204 次
联系:

Re: 將改進混亂時鐘的網頁版

帖子 ejsoon »

改進ejtilelocal:

代码: 全选

改進程式:
1.把add、delete、update、undo、redo、dataarea、minimize等這些過於簡單的id加上前綴ejlcl。

2.當點擊update時,將進入「伸手」狀態。當處於「伸手」狀態時,點擊其中一個dataarea>img.ejtilesvgdata,則「握手」成功,程式將每隔7秒就把數據保存至img所指向的地方。

3.當「握手成功」後,再次點擊任意一個dataarea>img.ejtilesvgdata,包括「握手成功」的那個,它的作用都是將此data上載。

4.當「握手」之後再次點擊update,它將會「放手」,即取消每隔7秒保存數據。當只處於「伸手」狀態,再次點擊update也會取消此狀態。

5.當點擊delete、undo或redo時,如果處於「握手」狀態,則先「放手」,再執行相應操作。

6.當點擊delete時,它應始終保持「刪除狀態」,點擊其中一個dataarea>img.ejtilesvgdata則刪除相應數據,刪除完後不會退出該狀態,只有再次點擊delete才會退出。

7.只有在「握手、放手」時才會把當前數據存進undo stack中,每隔7秒保存不會。

只需給出所要修改的地方。所有的代碼和注釋都要使用英文。
附件
ejtilelocalstorage202604181010.js
(11.6 KiB) 已下载 4 次
https://ejsoon.vip/
弈趣極光:享受思維樂趣
头像
ejsoon
一枝独秀
一枝独秀
帖子: 5192
注册时间: 2022年 11月 18日 17:36
为圈友点赞: 175 次
被圈友点赞: 204 次
联系:

Re: 將改進混亂時鐘的網頁版

帖子 ejsoon »

發現gemoni fast已經夠用了:

代码: 全选

To improve the script while maintaining its functionality and structure, here are the specific modifications. These changes update IDs with the `ejlcl` prefix and implement the new "Handshake" logic for auto-saving.

### 1. Updated HTML String and Element Selection
Change the IDs in the `htmlString` and the corresponding variable assignments to use the `ejlcl` prefix.

```javascript
// Updated HTML with ejlcl prefixes
const htmlString = `
    <style>
        /* ... existing styles ... */
        .functionbuttons .select svg { border: 1px solid #a72; }
    </style>
    <div class="savetolocalstorage">
        <div id="ejlclminimize">
            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><line x1="4" y1="12" x2="20" y2="12"></line></svg>
        </div>
        <h4 class="savetolocalstorageh4">Local Storage</h4>
        <div class="functionbuttons">
            <span id="ejlcladd"><svg ...></span>
            <span id="ejlcldelete"><svg ...></span>
            <span id="ejlclupdate"><svg ...></span>
            <span id="ejlclundo"><svg ...></span>
            <span id="ejlclredo"><svg ...></span>
        </div>
        <div id="ejlcldataarea" class="dataarea" style="position: relative;"></div>
    </div>
`;

// Updated Element Selectors
const dataarea = document.getElementById('ejlcldataarea');
const addButton = document.getElementById('ejlcladd');
const deleteButton = document.getElementById('ejlcldelete');
const updateButton = document.getElementById('ejlclupdate');
const undoButton = document.getElementById('ejlclundo');
const redoButton = document.getElementById('ejlclredo');
const minimizeButton = document.getElementById('ejlclminimize');
```

---

### 2. Implementation of Handshake and Persistent Delete Logic
The following modifications replace the existing click listeners and logic for `dataarea`, `updateButton`, and `deleteButton`.

```javascript
// New state variable for "Handshake" status
let isHandshaking = false; 

function releaseHand() {
    if (autoSaveInterval) {
        clearInterval(autoSaveInterval);
        autoSaveInterval = null;
    }
    if (autoSaveTarget) {
        autoSaveTarget.style.border = '';
        autoSaveTarget = null;
        isHandshaking = false;
        saveState(); // Push to undo stack only on "release"
    }
}

// Logic for dataarea click (Handshake and Upload)
dataarea.addEventListener('click', function(event) {
    const target = event.target;
    if (target.classList.contains('ejtilesvgdata')) {
        if (deleteMode) {
            deleteSvg(target);
            // No longer exiting deleteMode here; remains active until toggled
        } else if (updateMode && !isHandshaking) {
            // Reaching out -> Handshake Success
            saveState(); // Save state before starting handshake
            autoSaveTarget = target;
            autoSaveTarget.style.border = '2px solid #a72';
            isHandshaking = true;
            autoSaveInterval = setInterval(autoSaveTick, 7000);
        } else {
            // Normal click OR click during active Handshake: Upload data
            etmain.outerHTML = atob(target.src.split(',')[1]);
            etinit();
            recordHistory();
        }
        setButtonBorder();
    }
});

// Update Button: Toggle Handshake
updateButton.addEventListener('click', function() {
    if (updateMode) {
        if (isHandshaking) releaseHand();
        updateMode = false;
    } else {
        updateMode = true;
        deleteMode = false; // Disable delete if update is turned on
    }
    setButtonBorder();
});

// Delete Button: Toggle Delete Mode and release Hand if active
deleteButton.addEventListener('click', function() {
    if (isHandshaking) releaseHand();
    deleteMode = !deleteMode;
    if (deleteMode) updateMode = false;
    setButtonBorder();
});

// Undo/Redo: Release Hand before operation
undoButton.addEventListener('click', () => {
    if (isHandshaking) releaseHand();
    undols();
});

redoButton.addEventListener('click', () => {
    if (isHandshaking) releaseHand();
    redols();
});
```

---

### 3. Updated `autoSaveTick`
Ensure the auto-save function updates storage but skips the `saveState()` history stack as requested.

```javascript
function autoSaveTick() {
    if (!autoSaveTarget) return;
    
    let etmainclone = etmain.cloneNode(true);
    let etmaincwait = etmainclone.querySelector(".etwait");
    if (etmaincwait) etmaincwait.remove();
    
    let data = etmainclone.outerHTML;
    autoSaveTarget.src = 'data:image/svg+xml;base64,' + btoa(data);
    
    // Update storage without pushing to undo stack
    updateLocalStorage();
    showSaveIndicator(autoSaveTarget);
}
```

---

### 4. Modified `deleteSvg`
Update the `deleteSvg` function to ensure it doesn't accidentally interfere with the persistent delete mode.

```javascript
function deleteSvg(img) {
    // If we happen to delete the auto-save target, stop the interval
    if (img === autoSaveTarget) {
        clearInterval(autoSaveInterval);
        autoSaveInterval = null;
        autoSaveTarget = null;
        isHandshaking = false;
    }
    img.remove();
    saveState();
    updateLocalStorage();
}
```
https://ejsoon.vip/
弈趣極光:享受思維樂趣
头像
ejsoon
一枝独秀
一枝独秀
帖子: 5192
注册时间: 2022年 11月 18日 17:36
为圈友点赞: 175 次
被圈友点赞: 204 次
联系:

Re: 將改進混亂時鐘的網頁版

帖子 ejsoon »

算了還是用pro吧。

代码: 全选

改進程式:
1.把add、delete、update、undo、redo、dataarea、minimize等這些過於簡單的id加上前綴ejlcl。

2.當點擊update時,將進入「伸手」狀態。當處於「伸手」狀態時,點擊其中一個dataarea>img.ejtilesvgdata,則「握手」成功,程式將每隔7秒就把數據保存至img所指向的地方。

3.當「握手」之後再次點擊update,它將會「放手」,即取消每隔7秒保存數據。當只處於「伸手」狀態,再次點擊update也會取消此狀態。

4.當「握手成功」後,再次點擊任意一個dataarea>img.ejtilesvgdata,包括「握手成功」的那個,它的作用都是將此data上載。同時「放手」。

5.當點擊add、delete、undo或redo時,如果處於「握手」狀態,則先「放手」,再執行相應操作。

6.當點擊delete時,它應始終保持「刪除狀態」,點擊其中一個dataarea>img.ejtilesvgdata則刪除相應數據,刪除完後不會退出該狀態,只有再次點擊delete才會退出,或者點擊add、update、undo、redo也會先退出再執行相應功能。。

7.只有在「握手、放手」時才會把當前數據存進undo stack中,每隔7秒保存不會。

只需給出所要修改的地方。所有的代碼和注釋都要使用英文。
gemini pro:

代码: 全选

Here are the exact modifications needed to implement your requirements. Replace the corresponding sections in your original script with the code blocks below.

### 1. Update the `htmlString` (Prefixing IDs)
Replace the `<style>` block and HTML template to update `dataarea`, `minimize`, and the function buttons with the `ejlcl` prefix.

```javascript
// Replace the htmlString declaration
const htmlString = `
    <style>
        .savetolocalstorage {
            width: 80%;
            margin: 20px auto;
            border: 1px solid #ccc;
            padding: 10px;
            position: relative;
        }
        .functionbuttons > span {
            display: inline-block;
            width: 24px;
            height: 24px;
            box-sizing: content-box;
            margin-right: 7px;
        }
        .functionbuttons svg {
            border: 1px solid #ccc;
            cursor: pointer;
        }
        .functionbuttons .select svg {
            border: 1px solid #a72;
        }
        #ejlcldataarea {
            display: flex;
            flex-wrap: wrap;
        }
        .savetolocalstorage img {
            width: 120px;
            height: 120px;
            border: 1px solid #777;
            margin: 5px;
            cursor: pointer;
        }
        .savetolocalstorageh4 {
            margin: 4px 0;
        }
        #ejlclminimize {
            background: transparent;
            border: none;
            cursor: pointer;
            position: absolute;
            top: 10px;
            right: 10px;
        }
        #ejlclminimize svg {
            width: 24px;
            height: 24px;
            fill: none;
            stroke: currentColor;
            stroke-width: 2;
            stroke-linecap: round;
            stroke-linejoin: round;
            border: 1px solid #777;
        }
        #localStorageButton {
            margin-top: 7px;
        }
    </style>
    <div class="savetolocalstorage">
        <div id="ejlclminimize">
            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
                <line x1="4" y1="12" x2="20" y2="12"></line>
            </svg>
        </div>
        <h4 class="savetolocalstorageh4">Local Storage</h4>
        <div class="functionbuttons">
            <span id="ejlcladd"><svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="24" height="24"><path d="M 5,12 h 14 M 12,5 v 14" stroke="#333" fill="none" stroke-width="2"></path></svg></span>
            <span id="ejlcldelete"><svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="24" height="24"><path d="M 5,12 h 14" stroke="#333" fill="none" stroke-width="2"></path></svg></span>
            <span id="ejlclupdate"><svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="24" height="24"><path d="M 12,2 L 12,20 M 7,15 L 12,20 L 17,15" stroke="#333" fill="none" stroke-width="2"></path></svg></span>
            <span id="ejlclundo"><svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="24" height="24"><path d="M 12,20 A 8,8 0 1 0 4,12" stroke="#333" stroke-width="2" fill="none"></path><path d="M 8,11 L 4,16 L 0,11 Z" stroke="none" fill="#333"></path></svg></span>
            <span id="ejlclredo"><svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="24" height="24"><path d="M 12,20 A 8,8 0 1 1 20,12" stroke="#333" stroke-width="2" fill="none"></path><path d="M 16,11 L 20,16 L 24,11 Z" stroke="none" fill="#333"></path></svg></span>
        </div>
        <div id="ejlcldataarea" style="position: relative;"></div>
    </div>
`;
```

### 2. Update Element Selectors
Replace the `querySelector` and `getElementById` assignments to match the newly prefixed IDs.

```javascript
// Replace the DOM query assignments
const dataarea = document.getElementById('ejlcldataarea');
const addButton = document.getElementById('ejlcladd');
const deleteButton = document.getElementById('ejlcldelete');
const updateButton = document.getElementById('ejlclupdate');
const undoButton = document.getElementById('ejlclundo');
const redoButton = document.getElementById('ejlclredo');
const minimizeButton = document.getElementById('ejlclminimize');
```

### 3. Add State Management Functions
Insert these helper functions right before your event listeners. They manage the "let go" functionality and clean up states before executing new commands.

```javascript
// Helper function to "let go" (cancel handshake or reaching out state)
function cancelHandshake() {
    if (updateMode) {
        updateMode = false;
        if (autoSaveInterval) {
            clearInterval(autoSaveInterval);
            autoSaveInterval = null;
        }
        if (autoSaveTarget) {
            autoSaveTarget.style.border = '';
            autoSaveTarget = null;
            saveState(); // Push to undo stack when letting go
        }
    }
}

// Helper function to let go AND cancel delete mode
function cancelHandshakeAndModes() {
    cancelHandshake();
    deleteMode = false;
    setButtonBorder();
}
```

### 4. Update Event Listeners
Replace the event listeners for `dataarea`, `add`, `delete`, `update`, `undo`, and `redo` with the following block to fulfill requirements #2, #3, #4, #5, and #6.

```javascript
// Replace existing event listeners for dataarea and buttons
dataarea.addEventListener('click', function(event) {
    const target = event.target;
    if (target.classList.contains('ejtilesvgdata')) {
        if (deleteMode) {
            // Persistent delete mode: execute delete, DO NOT turn off deleteMode
            deleteSvg(target);
        } else if (updateMode) {
            if (!autoSaveTarget) {
                // Currently "reaching out" -> "Handshake" successful
                saveState(); // Push to undo stack when turning on auto-save
                autoSaveTarget = target;
                autoSaveTarget.style.border = '2px solid #a72';
                
                if (autoSaveInterval) clearInterval(autoSaveInterval);
                autoSaveInterval = setInterval(autoSaveTick, 7000);
            } else {
                // Currently in "Handshake" -> load data and "let go"
                etmain.outerHTML = atob(target.src.split(',')[1]);
                etinit();
                recordHistory();
                cancelHandshake(); // Let go (cancels 7s interval & pushes to stack)
                setButtonBorder();
            }
        } else {
            // Normal click
            etmain.outerHTML = atob(target.src.split(',')[1]);
            etinit();
            recordHistory();
        }
    }
});

addButton.addEventListener('click', function() {
    cancelHandshakeAndModes(); // "Let go" first
    addSvg();
});

deleteButton.addEventListener('click', function() {
    if (deleteMode) {
        deleteMode = false; // Exit persistent delete mode
    } else {
        cancelHandshakeAndModes(); // "Let go" first
        deleteMode = true; // Enter persistent delete mode
    }
    setButtonBorder();
});

updateButton.addEventListener('click', function() {
    if (updateMode) {
        // "Let go" (cancel handshake or reaching out)
        cancelHandshake();
    } else {
        // "Reach out"
        cancelHandshakeAndModes(); // Cancel delete mode if active
        updateMode = true;
    }
    setButtonBorder();
});

undoButton.addEventListener('click', function() {
    cancelHandshakeAndModes(); // "Let go" first
    undols();
});

redoButton.addEventListener('click', function() {
    cancelHandshakeAndModes(); // "Let go" first
    redols();
});
```

### 5. Update the `showSaveIndicator` Function
Because the `add` button ID was changed, the selector used to clone the SVG inside `showSaveIndicator` must also be updated.

```javascript
// Replace the querySelector inside showSaveIndicator
function showSaveIndicator(img) {
    const addSvg = document.querySelector('#ejlcladd svg'); // Updated ID
    const plusIndicator = addSvg.cloneNode(true);
    
    // Position the SVG over the target image
    plusIndicator.style.position = 'absolute';
    plusIndicator.style.top = img.offsetTop + 'px';
    plusIndicator.style.left = img.offsetLeft + 'px';
    plusIndicator.style.width = '24px';
    plusIndicator.style.height = '24px';
    plusIndicator.style.borderRadius = '2px';
    plusIndicator.style.zIndex = '10';
    
    // Change the SVG path stroke to green
    const paths = plusIndicator.querySelectorAll('path');
    paths.forEach(p => p.setAttribute('stroke', '#0f0'));
    
    dataarea.appendChild(plusIndicator);
    
    // Remove the indicator after 500 milliseconds
    setTimeout(() => {
        plusIndicator.remove();
    }, 500);
}
```
https://ejsoon.vip/
弈趣極光:享受思維樂趣
头像
ejsoon
一枝独秀
一枝独秀
帖子: 5192
注册时间: 2022年 11月 18日 17:36
为圈友点赞: 175 次
被圈友点赞: 204 次
联系:

Re: 將改進混亂時鐘的網頁版

帖子 ejsoon »

改進:
當點擊center時,如果svg中不存在「viewBox="0 0 480 480" preserveAspectRatio="xMidYMid meet"」屬性,則加上。當upload ejtile時,如果存在則要在上載的內容中去掉。

只需給出所要修改的地方,所有的代碼和注釋都要使用英文。
附件
ejtileanimate202511172231.js
(137.7 KiB) 已下载 4 次
https://ejsoon.vip/
弈趣極光:享受思維樂趣
头像
ejsoon
一枝独秀
一枝独秀
帖子: 5192
注册时间: 2022年 11月 18日 17:36
为圈友点赞: 175 次
被圈友点赞: 204 次
联系:

Re: 將改進混亂時鐘的網頁版

帖子 ejsoon »

gemini pro:

代码: 全选

根據您的需求,以下是針對 `etaniCenterClick` 函數(處理 **center** 點擊)以及 `handleContentHTMLClick` 函數(處理 **upload ejtile**)的修改建議:

### 1. 修改 `etaniCenterClick` 函數
在設置 `etdrop` 的變換屬性之前,檢查 `etani`(SVG 對象)是否具有 `viewBox` 和 `preserveAspectRatio` 屬性,若無則添加。

```javascript
// Handle the 'Center' button click to reset the .etdrop transform
function etaniCenterClick() {
    const etdrop = etani.querySelector('.etdrop');
    if (!etdrop) return;

    // --- Add these lines to handle viewBox and preserveAspectRatio ---
    if (!etani.getAttribute('viewBox')) {
        etani.setAttribute('viewBox', '0 0 480 480');
    }
    if (!etani.getAttribute('preserveAspectRatio')) {
        etani.setAttribute('preserveAspectRatio', 'xMidYMid meet');
    }
    // ----------------------------------------------------------------

    // toggle center or current transform
    if (this.innerHTML === 'center') {
        this.innerHTML = 'current';
        etdrop.setAttribute('transform', 'translate(240,240) scale(1,1)');
        updateEtaniResult();
    } else {
        this.innerHTML = 'center';
        const originalSvg = document.getElementById('etmain');
        const originalDrop = originalSvg.querySelector('.etdrop');
        const originalTransform = originalDrop.getAttribute('transform');
        if (originalTransform) {
            etdrop.setAttribute('transform', originalTransform);
            updateEtaniResult();
        }
    }
}
```

### 2. 修改 `handleContentHTMLClick` 函數中的上載邏輯
在執行 `etaniEjtileClick()` 之前,先移除 `etani` 中存在的 `viewBox` 和 `preserveAspectRatio` 屬性。

```javascript
// Handle the HTML popup window
function handleContentHTMLClick() {
    if (!etani) return;
    // ... (existing code for UI setup)

    etaniWindow(htmlDiv, () => {
        const parser = new DOMParser();
        const eDom = parser.parseFromString(textarea.value, 'image/svg+xml');
        etani = eDom.documentElement;

        // ... (existing code for mode setting)

        // upload ejtile
        if (ejtileSpan.classList.contains('selected')) {
            // --- Add these lines to remove attributes before uploading ---
            etani.removeAttribute('viewBox');
            etani.removeAttribute('preserveAspectRatio');
            // -----------------------------------------------------------
            etaniEjtileClick();
        }

        // update UI and result
        updateUIandResult();
    });
}
```
gemini fast:

代码: 全选

// 修改 handleContentHTMLClick 函數內部的確認邏輯
etaniWindow(htmlDiv, () => {
    const parser = new DOMParser();
    const eDom = parser.parseFromString(textarea.value, 'image/svg+xml');
    
    // Only remove attributes from the content to be uploaded, not changing current etani attributes directly here
    const uploadContent = eDom.documentElement;

    // set repeat or freeze mode for the new etani state
    etani = uploadContent; // Update current state
    let eMode = document.querySelector('.etaniMode');
    eMode.querySelector('span.active').classList.remove('active');
    if (etani.getAttribute('rfm') === 'repeat') {
        eMode.querySelector('.etaniModeRepeat').classList.add('active');
    } else if (etani.getAttribute('rfm') === 'freeze') {
        eMode.querySelector('.etaniModeFreeze').classList.add('active');
    } else if (etani.getAttribute('rfm') === 'mixed') {
        eMode.querySelector('.etaniModeMixed').classList.add('active');
    }

    // upload ejtile
    if (ejtileSpan.classList.contains('selected')) {
        // --- Remove attributes only from the temporary upload document ---
        uploadContent.removeAttribute('viewBox');
        uploadContent.removeAttribute('preserveAspectRatio');
        // -----------------------------------------------------------------
        etaniEjtileClick();
    }

    // update UI and result
    updateUIandResult();
});
https://ejsoon.vip/
弈趣極光:享受思維樂趣
头像
ejsoon
一枝独秀
一枝独秀
帖子: 5192
注册时间: 2022年 11月 18日 17:36
为圈友点赞: 175 次
被圈友点赞: 204 次
联系:

Re: 將改進混亂時鐘的網頁版

帖子 ejsoon »

開始重寫chaosclock了:

代码: 全选

重寫該程式:
1.保留取到svg的部分,以及區分兩種模式的部分。注意頁面上可能出現多個svg,它們之間不要發生干涉。

2.當取到svg之後,將其稱作棋盤,其內部的.etdrop>use[href=tilen]稱作棋子,其中n是0~11的整數,代表棋子1~12。

3.當button模式要產生隨機盤面時,將把每個棋子隨機放在非正位的地方(更改它的translate)。

棋子12的正位是(0,-144),從棋子1開始,以(0,0)為圓心,以144為半徑,每隔30度順時針偏移,就是它的正位坐標。

計算出的坐標值保留最多三位小數,要用「*1000,round(),/1000」。

4.當number模式時,把每個棋子按順序從棋子1的正位開始放。

比如[chaosclock]3,1,11,5,7,10,12,6,2,9,8,4[/chaosclock],則是把棋子3放在棋子1的正位,把棋子1放在棋子2的正位。

如果中間出現0,則說明有棋子是不在鐘面上的,這些棋子如果是單數,則把它移到(-208,y)的坐標上,雙數棋子則移到(208,y),y的值隨機從「-200,-120,-40,40,120,200」中取,一個位置只能放一個棋子。

比如[chaosclock]0,2,9,0,0,0,3,0,4,7,11,0[/chaosclock],則棋子1和棋子6等都不在鐘面上,最終隨機把棋子1移到了(-208,40),棋子6移到了(208,120)。

5.當完成以上步驟時,遊戲開始。拿到cclok中的#path1029和#path900,分別稱作分針和時針。

起初時針的rotate為90,表示輪到乙方,每當行動方切換,它就會增加180。

遊戲一開始是輪到乙方,當輪到任何一方時,他都可以點擊鐘面上的棋子,則這個棋子將會繞(0,0)坐標順時針旋轉1秒至它要到達的地方。

用js實現旋轉動畫,只包括對translate的改動。

棋子所要到達的地方,是它的棋子的數值乘以30度。如果所到達的地方有其它棋子,則這個棋子將會被吃掉。

被吃掉的棋子,如果是單數則移到「x=-208,y在六個數隨機取」的坐標上,雙數則是x=208。移動時先把透明度設為0.5,再用js實現移動動畫,用時1s,移完後再把透明度去掉。

比如[chaosclock]3,1,11,5,7,10,12,6,2,9,8,4[/chaosclock],這時輪到乙方,當點擊棋子3時,它將走到棋子5所在的位置,棋子5將變透明度0.5並移到左邊x為-208的某個地方。
https://ejsoon.vip/
弈趣極光:享受思維樂趣
回复

在线用户

正浏览此版面之用户: 没有注册用户 和 1 访客