正在開發新遊戲:星•球

分享身边的点滴趣事
头像
ejsoon
一枝独秀
一枝独秀
帖子: 5561
注册时间: 2022年 11月 18日 17:36
为圈友点赞: 179 次
被圈友点赞: 207 次
联系:

Re: 正在開發新遊戲:星•球

帖子 ejsoon »

改進:
一,當保存時,如果不是動畫,則文件名為ejsolid_static_yyyymmdd_hhiiss.svg,如果是動畫則把static換成animate。日期和時間要用new Date()。

二,增加mini模式,div.ejsolid將寫有json數據,把它作為data傳入。本模式只顯示div#ejs-svg-container,把兩個checkbox選項絕對定位至它的左上角並改小。

三,在ejs-upload-trigger的右方新增一個download data按鈕,當點擊時將下載一個json文件,文件名為ejsolid_data_yyyymmdd_hhiiss.json。包含設置面板中的全部數據,將用於mini模式。

四,當頁面刷新時,js要把設置面板設的每一個輸入框設為初始值。

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



gemini pro你好:

代码: 全选

以下是針對您提出的四項改進要求的具體代碼修改。所有修改細節、程式碼與註解均已轉換為英文。

### 1. 新增時間戳記工具函式與修正 SVG 儲存檔名命名邏輯

在類別中新增一個用來格式化時間戳記的輔助方法 `getTimestamp()`,並修改原有儲存按鈕的點擊監聽事件。

**在類別中新增輔助方法 (Add helper method inside class):**

```javascript
  /**
   * Generates a formatted timestamp string (yyyymmdd_hhiiss) using current Date.
   * @returns {string} Formatted timestamp.
   */
  getTimestamp() {
    const now = new Date();
    const pad = n => String(n).padStart(2, '0');
    return `${now.getFullYear()}${pad(now.getMonth() + 1)}${pad(now.getDate())}_` +
           `${pad(now.getHours())}${pad(now.getMinutes())}${pad(now.getSeconds())}`;
  }

```

**修改 `bindEvents()` 中負責儲存 SVG 的部分 (Update SVG save logic inside `bindEvents()`):**

```javascript
    // Update the filename generation logic during SVG export
    this.dom.saveBtn.onclick = () => {
      if (!this.state.lastSvg) return;
      const isAnim = this.dom.animToggle.checked;
      const filename = `ejsolid_${isAnim ? 'animate' : 'static'}_${this.getTimestamp()}.svg`;

      const blob = new Blob([this.state.lastSvg], { type: 'image/svg+xml' });
      const url = URL.createObjectURL(blob);
      const a = document.createElement('a');
      a.href = url;
      a.download = filename;
      a.click();
      URL.revokeObjectURL(url);
    };

```

---

### 2. 擴充結構以支援 `mini` 模式與對應的精簡型 CSS 樣式

在構造函數中先備份原始的 JSON 文本,並在 `renderDOM()` 中判定是否載入 `mini` 模式的 DOM 佈局。這能隱藏不必要的側邊欄,僅保留 SVG 區塊,並將縮小版的控制項絕對定位至左上角。

**修改 `constructor(containerSelector)` 以暫存原始 JSON (Capture raw JSON string):**

```javascript
    // Add rawJsonData to state before renderDOM clears text content
    this.state = {
      rotMatrix: [1, 0, 0, 0, 1, 0, 0, 0, 1],
      lastSvg: '',
      isDragging: false,
      lastX: 0,
      lastY: 0,
      objData: `v 0.0 0.0 1.077364...`, // default raw fallback
      parsedModel: null,
      rawJsonData: this.container.textContent.trim() // Cache the config JSON
    };

```

**在 `injectCSS()` 結尾追加樣式 (Append mini mode CSS into `injectCSS()`):**

```javascript
    // Style configurations for the absolute-positioned mini controls overlay
    styleSheet.innerText += `
        .ejs-mini-controls { position: absolute; top: 8px; left: 8px; z-index: 20; display: flex; gap: 6px; background: rgba(255, 255, 255, 0.75); padding: 4px 6px; border-radius: 4px; box-shadow: 0 1px 3px rgba(0,0,0,0.15); }
        .ejs-mini-controls label { font-size: 10px; font-family: sans-serif; display: flex; align-items: center; gap: 4px; cursor: pointer; }
        .ejs-mini-controls input[type="checkbox"] { width: 28px !important; height: 16px !important; }
        .ejs-mini-controls input[type="checkbox"]::after { width: 12px !important; height: 12px !important; top: 2px !important; left: 2px !important; }
        .ejs-mini-controls input[type="checkbox"]:checked::after { transform: translateX(12px) !important; }
    `;

```

**修改 `renderDOM()` 邏輯 (Conditional layout layout inside `renderDOM()`):**

```javascript
  renderDOM() {
    if (this.mode === 'mini') {
      // Mini mode: render only the SVG container and small overlay checkboxes
      this.container.innerHTML = `
        <div class="ejsolid-mini-container" style="position: relative; display: inline-block;">
          <div class="ejs-mini-controls">
            <label><input type="checkbox" class="ejs-perspective" /> Persp</label>
            <label><input type="checkbox" class="ejs-anim-toggle" /> Anim</label>
          </div>
          <div id="ejs-svg-container"></div>
          
          <div style="display: none;">
            <input type="number" class="ejs-canvas-size" value="480"/>
            <input type="number" class="ejs-content-size" value="360"/>
            <input type="number" class="ejs-opacity" value="1"/>
            <input type="number" class="ejs-stroke-width" value="1"/>
            <input type="color" class="ejs-stroke-color" value="#000000"/>
            <input type="number" class="ejs-anim-time" value="7"/>
            <input type="number" class="ejs-anim-angle" value="0"/>
            <input type="number" class="ejs-frame-int" value="0.25"/>
            <button type="button" class="ejs-upload-trigger"></button>
            <input type="file" class="ejs-file-input" />
            <button type="button" class="ejs-save-svg"></button>
          </div>
        </div>
      `;
    } else {
      // Main mode: standard control panel layout ...
      // (Keep existing sidebar layout here)
    }
  }

```

---

### 3. 新增下載設定參數 JSON 資料按鈕 (Download Data)

在控制台新增按鈕,用於打包設定面板狀態及當前 3D 模型數據至一個外部 JSON 檔中。

**在 `renderDOM()` 中新增按鈕佈局 (Add Download Data button next to upload trigger):**

```javascript
    // Inside Main Mode layout template string:
    `<h2>Raw Data (${this.mode})</h2>
     <div class="ejsolid-control-group">
         <input type="file" class="ejs-file-input" accept=".obj" style="display: none" />
         <button type="button" class="ejs-upload-trigger">Choose OBJ File</button>
         <button type="button" class="ejs-download-data" style="margin-left: 8px;">Download Data</button>
     </div>`

```

**在 `cacheDOM()` 綁定此按鈕 (Cache reference inside `cacheDOM()`):**

```javascript
    this.dom.downloadDataBtn = this.container.querySelector('.ejs-download-data');

```

**在 `bindEvents()` 中新增點擊下載邏輯 (Add click handler inside `bindEvents()`):**

```javascript
    // Set up download event listener for the aggregated JSON configuration
    if (this.dom.downloadDataBtn) {
      this.dom.downloadDataBtn.onclick = () => {
        const configData = {
          objData: this.state.objData,
          canvasSize: this.dom.canvasNum.value,
          contentSize: this.dom.contentNum.value,
          opacity: this.dom.opacityNum.value,
          strokeWidth: this.dom.strokeWidthNum.value,
          strokeColor: this.dom.strokeColorPicker.value,
          perspective: this.dom.perspective.checked,
          animate: this.dom.animToggle.checked,
          animTime: this.dom.animTime.value,
          animAngle: this.dom.animAngle.value,
          frameInt: this.dom.frameInt.value,
          colors: {}
        };
        
        // Export polygon face side colors map
        this.config.sides.forEach(s => {
          const el = this.container.querySelector(`.hex-${s}`);
          if (el) configData.colors[s] = el.value;
        });

        const blob = new Blob([JSON.stringify(configData, null, 2)], { type: 'application/json' });
        const url = URL.createObjectURL(blob);
        const a = document.createElement('a');
        a.href = url;
        a.download = `ejsolid_data_${this.getTimestamp()}.json`;
        a.click();
        URL.revokeObjectURL(url);
      };
    }

```

---

### 4. 重新整理或初始化時重設輸入框與面板預設值

改寫 `initApp()` 生命週期方法,讓主模式在載入時自動將所有欄位初始化為指定初始值;若為 Mini 模式,則直接解析傳入的 JSON 字串。

**重寫 `initApp()` 方法 (Overwrite `initApp()` for default setups):**

```javascript
  /**
   * Initializes the application state, ensures inputs reset to baseline values,
   * or parses internal JSON configuration if loaded under mini mode.
   */
  initApp() {
    if (this.mode === 'mini') {
      try {
        const jsonData = JSON.parse(this.state.rawJsonData || "{}");
        if (jsonData.objData) this.state.objData = jsonData.objData;
        if (jsonData.canvasSize) this.dom.canvasNum.value = jsonData.canvasSize;
        if (jsonData.contentSize) this.dom.contentNum.value = jsonData.contentSize;
        if (jsonData.opacity) this.dom.opacityNum.value = jsonData.opacity;
        if (jsonData.strokeWidth) this.dom.strokeWidthNum.value = jsonData.strokeWidth;
        if (jsonData.strokeColor) this.dom.strokeColorPicker.value = jsonData.strokeColor;
        if (jsonData.perspective !== undefined) this.dom.perspective.checked = jsonData.perspective;
        if (jsonData.animate !== undefined) this.dom.animToggle.checked = jsonData.animate;
        if (jsonData.animTime) this.dom.animTime.value = jsonData.animTime;
        if (jsonData.animAngle) this.dom.animAngle.value = jsonData.animAngle;
        if (jsonData.frameInt) this.dom.frameInt.value = jsonData.frameInt;
        
        if (jsonData.colors) {
          Object.keys(jsonData.colors).forEach(s => {
            this.config.defaultColors[s] = jsonData.colors[s];
          });
        }
      } catch (e) {
        console.error("EjSolid: Failed to process mini-mode inline configuration.", e);
      }
    } else {
      // Forcefully assign predefined default values to form controls on every page load
      this.dom.canvasNum.value = 480;
      this.dom.contentNum.value = 360;
      this.dom.opacityNum.value = 1.0;
      this.dom.strokeWidthNum.value = 1.0;
      this.dom.strokeColorPicker.value = '#000000';
      this.dom.perspective.checked = false;
      this.dom.animToggle.checked = false;
      this.dom.animTime.value = 7.0;
      this.dom.animAngle.value = 0;
      this.dom.frameInt.value = 0.25;

      this.config.sides.forEach(s => {
        const el = this.container.querySelector(`.hex-${s}`);
        if (el) el.value = this.config.defaultColors[s];
      });
    }

    // Erase stale models and invoke initial frame rendering
    this.state.parsedModel = null;
    this.draw();
  }

```
https://ejsoon.vip/
弈趣極光:享受思維樂趣
头像
ejsoon
一枝独秀
一枝独秀
帖子: 5561
注册时间: 2022年 11月 18日 17:36
为圈友点赞: 179 次
被圈友点赞: 207 次
联系:

Re: 正在開發新遊戲:星•球

帖子 ejsoon »

191不太行
附件
ejsolid191.js
(35.83 KiB) 已下载 2 次
ejsolid19.js
(29.3 KiB) 已下载 1 次
https://ejsoon.vip/
弈趣極光:享受思維樂趣
头像
ejsoon
一枝独秀
一枝独秀
帖子: 5561
注册时间: 2022年 11月 18日 17:36
为圈友点赞: 179 次
被圈友点赞: 207 次
联系:

Re: 正在開發新遊戲:星•球

帖子 ejsoon »

改進:
一,download data按鈕應和upload data按鈕並排,且使用相同樣式,但顏色不同。

二,download data的jspn數據中應該包含this.state的所有數據,包括當前旋轉的角度等。

三,mini模式無效,查明原因。當mini模式時,div.ejsolid的mode=mini,json數據會保存在它的innerHTML。

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



gemini fast:

代码: 全选

To address your requirements, I have refined the button styling, expanded the JSON export state, and fixed the `mini` mode initialization logic.

### 1. Unified Button Layout and Styling

In the `injectCSS` method, add a specific color for the download button to distinguish it while keeping the shared "Raw Data" group layout.

```javascript
/* In injectCSS() */
// Update .ejsolid-control-group to allow horizontal layout for raw data buttons
.ejsolid-control-group.raw-data-row { display: flex; flex-direction: row; gap: 8px; }
.ejsolid-control-group.raw-data-row button { flex: 1; padding: 10px; }

// Specific styles for the two buttons
.ejs-upload-trigger { background-color: #6c757d !important; }
.ejs-download-data { background-color: #4361ee !important; }

```

In `renderDOM()`, wrap the buttons in the new class:

```javascript
/* In renderDOM() - Main Mode section */
<h2>Raw Data</h2>
<div class="ejsolid-control-group raw-data-row">
    <input type="file" class="ejs-file-input" accept=".obj" style="display: none" />
    <button type="button" class="ejs-upload-trigger">Upload OBJ</button>
    <button type="button" class="ejs-download-data">Download Data</button>
</div>

```

---

### 2. Expanded JSON Export (Full State)

Update the `downloadDataBtn.onclick` event inside `bindEvents()` to include the rotation matrix and all internal state properties.

```javascript
/* In bindEvents() */
this.dom.downloadDataBtn.onclick = () => {
  const configData = {
    // Persistent State
    rotMatrix: this.state.rotMatrix,
    objData: this.state.objData,
    
    // UI Settings
    canvasSize: this.dom.canvasNum.value,
    contentSize: this.dom.contentNum.value,
    opacity: this.dom.opacityNum.value,
    strokeWidth: this.dom.strokeWidthNum.value,
    strokeColor: this.dom.strokeColorPicker.value,
    perspective: this.dom.perspective.checked,
    animate: this.dom.animToggle.checked,
    animTime: this.dom.animTime.value,
    animAngle: this.dom.animAngle.value,
    frameInt: this.dom.frameInt.value,
    
    // Custom Face Colors
    colors: {}
  };
  
  this.config.sides.forEach(s => {
    const el = this.container.querySelector(`.hex-${s}`);
    if (el) configData.colors[s] = el.value;
  });

  const blob = new Blob([JSON.stringify(configData, null, 2)], { type: 'application/json' });
  const url = URL.createObjectURL(blob);
  const a = document.createElement('a');
  a.href = url;
  a.download = `ejsolid_config_${this.getTimestamp()}.json`;
  a.click();
  URL.revokeObjectURL(url);
};

```

---

### 3. Fixing Mini Mode and Auto-Init

The `mini` mode failed because the `DOMContentLoad` listener only looked for `mode="main"`, and the data extraction logic for `rawJsonData` needed to be more robust to handle `innerHTML`.

**Update `constructor` to capture initial HTML:**

```javascript
/* In constructor() */
this.state = {
  // ... other properties
  rawJsonData: this.container.innerHTML.trim() // Changed from textContent to innerHTML
};

```

**Update `initApp()` to restore the Rotation Matrix:**

```javascript
/* In initApp() - Mini Mode Logic */
if (jsonData.rotMatrix) this.state.rotMatrix = jsonData.rotMatrix;

```

**Update Auto-Init logic at the bottom of the file:**

```javascript
/* At the very end of the file */
document.addEventListener('DOMContentLoaded', () => {
  // Select all instances regardless of mode
  const instances = document.querySelectorAll('div.ejsolid');
  instances.forEach(el => {
    const selector = el.id ? `#${el.id}` : null;
    // Fallback: Use a temporary data attribute if no ID exists to ensure unique selection
    if (!selector) {
        const tempId = 'ejs-' + Math.random().toString(36).substr(2, 9);
        el.setAttribute('id', tempId);
        new EjSolid(`#${tempId}`);
    } else {
        new EjSolid(selector);
    }
  });
});

```

---

### Summary of Fixes

1. **Layout:** The buttons are now side-by-side with identical padding/font styles but distinct colors (Grey for Upload, Blue for Download).
2. **Data Integrity:** The `rotMatrix` is now saved/loaded, ensuring the 3D orientation is preserved across sessions.
3. **Mini Mode:** The auto-initialization now detects all `div.ejsolid` elements and correctly parses the JSON configuration embedded inside the `div` tags.
https://ejsoon.vip/
弈趣極光:享受思維樂趣
回复

在线用户

正浏览此版面之用户: Bing [Bot] 和 1 访客