info_outline
# CookPixiUI
這是一個主要用於 Code.Gamelet Pixi v5 的 UI 模組。
# 元件介紹
## ScrollView(滑動容器元件)
**ScrollView** 是一個可捲動的容器元件,適用於清單、選單、物品欄等場景。
支援以下功能:
- 指定顯示區域的寬度與高度
- 垂直或水平滑動方向(可選)
- 拖曳滑動內容(支援滑鼠與觸控)
- 慣性滾動(速度遞減)
- 自動遮罩超出區域的內容
- 可動態加入或清除內容項目
### `ScrollView.addContent(...child: PIXI.DisplayObject[]): void;`
添加內容到滑動容器中。
- `child` — 要加入的顯示物件(例如卡片、格子、圖片等)
### `ScrollView.clearContent(): void;`
清除內容容器內的所有子物件。
### 使用範例
```ts
// 請先確保該檔案頂層有 import(引入)ScrollView class(類別)
import ScrollView = CG.CookPixiUI.Components.ScrollView;
```
#### 建立垂直滑動區域
```ts
// 建立一個 300 x (畫面高度 - 100) 的垂直滑動區域
const scrollView_V = new ScrollView(300, CG.Base.pixi.stageHeight - 100, 'vertical');
scrollView_V.position.set(50, 50);
CG.Base.pixi.root.addChild(scrollView_V);
// 單元格尺寸設定(寬 300、高 50)
const rowCellSize = { width: 300, height: 50 };
// 加入 20 個垂直排列的矩形內容
for (let i = 0; i < 20; i++) {
const item = getRowItemCell(i);
scrollView_V.addContent(item);
}
/**
* 建立一個垂直列表用的彩色矩形區塊(含文字)
* @param index 第幾個項目(用來標示文字與計算 Y 座標)
*/
function getRowItemCell(index: number): PIXI.Graphics {
const item = new PIXI.Graphics()
.beginFill(0xFFFFFF * Math.random()) // 隨機顏色
.drawRect(0, 0, rowCellSize.width, rowCellSize.height)
.endFill();
// 設定位置(x 固定,y 根據索引排列)
item.position.set(10, index * (rowCellSize.height + 10));
// 建立文字物件並加入 item 內
const label = new PIXI.Text(`Item ${index + 1}`, {
fontSize: 20,
fill: 0xFFFFFF,
stroke: 0,
strokeThickness: 4,
lineJoin: 'round',
} as PIXI.TextStyle);
label.anchor.set(0, 0.5);
label.position.set(10, 25);
item.addChild(label);
return item;
}
```
#### 建立水平滑動區域
```ts
// 建立一個 (畫面寬度 - 450) x 150 的水平滑動區域
const scrollView_H = new ScrollView(CG.Base.pixi.stageWidth - 450, 150, 'horizontal');
scrollView_H.position.set(400, CG.Base.pixi.stageHeight * 0.5 - 75);
CG.Base.pixi.root.addChild(scrollView_H);
// 單元格尺寸設定(寬 80、高 100)
const colCellSize = { width: 80, height: 100 };
// 加入 15 個水平排列的彩色方塊
for (let i = 0; i < 15; i++) {
const item = getColItemCell(i);
scrollView_H.addContent(item);
}
/**
* 建立一個水平列表用的彩色方塊(含文字)
* @param index 第幾個項目(用來標示文字與計算 X 座標)
*/
function getColItemCell(index: number): PIXI.Graphics {
const item = new PIXI.Graphics()
.beginFill(0x66ccff + (index * 0x111111)) // 每個項目不同顏色
.drawRoundedRect(0, 0, colCellSize.width, colCellSize.height, 12)
.endFill();
// 設定位置(y 固定,x 根據索引排列)
item.position.set(index * (colCellSize.width + 20), 25);
// 建立文字物件並加入 item 內
const label = new PIXI.Text(`${index + 1}`, {
fontSize: 25,
fill: 0xFFFFFF,
stroke: 0,
strokeThickness: 5,
lineJoin: 'round',
} as PIXI.TextStyle);
label.anchor.set(0.5);
label.position.set(40, 50);
item.addChild(label);
return item;
}
```
## ListViewCell(清單項目元件)
**ListViewCell** 是清單中每個資料項目的基底元件,由 `ListView` 管理與重用。
每個 Cell 顯示對應的一筆資料,由 ListView 控制其內容更新與位置配置。
主要功能:
- 儲存該筆資料內容與索引(`data` 與 `index`)
- 提供 `setItem(index, data)` 方法,供 ListView 設定內容
- 靜態屬性 `width`、`height` 用於 ListView 的動態排版
注意事項:
- Cell 不持有所有資料,只管理自己那一筆
- UI 細節需由子類別實作
- 使用時子類別必須呼叫 `super.setItem(index, data)`,確保父類記錄資料狀態,以利 ListView 正確管理重用機制
### 使用範例
```ts
// 請先確保該檔案頂層有 import(引入)ListViewCell class(類別)
import ListViewCell = CG.CookPixiUI.Components.ListViewCell;
```
#### 建立用於垂直清單的項目
```ts
/** 一個簡單的 Cell 實作,顯示數字(垂直版)。 */
export class NumberCell_V extends ListViewCell<number> {
/** 靜態寬度(由 ListView 使用) */
static width = 300;
/** 靜態高度(由 ListView 使用) */
static height = 40;
private _background: PIXI.Graphics;
private _label: PIXI.Text;
constructor() {
super();
this._background = new PIXI.Graphics();
this.addChild(this._background);
this._label = new PIXI.Text('', {
fontSize: 20,
fill: 0x333333,
});
this._label.anchor.set(0.5);
this._label.position.set(NumberCell_V.width / 2, NumberCell_V.height / 2);
this.addChild(this._label);
}
/**
* 設定 Cell 資料並更新顯示內容。
* @param index - 資料在列表中的位置
* @param data - 對應的數值內容
*/
setItem(index: number, data: number): void {
super.setItem(index, data); // 一定要呼叫,讓父類別記住 index 和 data,ListView 才能正確管理 Cell
// 重新繪製底色
this._background.clear()
.beginFill(index % 2 === 0 ? 0xeeeeee : 0xdddddd) // 依據 index 決定底色,交錯顯示兩種顏色
.drawRoundedRect(0.5, 0.5, NumberCell_V.width - 1, NumberCell_V.height - 1, 5)
.endFill();
this._label.text = `#${index} → ${data}`;
}
}
```
#### 建立用於水平清單的項目
```ts
/** 一個簡單的 Cell 實作,顯示數字(水平版)。 */
export class NumberCell_H extends ListViewCell<number> {
/** 靜態寬度(由 ListView 使用) */
static width = 80;
/** 靜態高度(由 ListView 使用) */
static height = 100;
private _background: PIXI.Graphics;
private _label: PIXI.Text;
constructor() {
super();
this._background = new PIXI.Graphics();
this.addChild(this._background);
this._label = new PIXI.Text('', {
fontSize: 18,
fill: 0x224466
});
this._label.anchor.set(0.5);
this._label.position.set(NumberCell_H.width / 2, NumberCell_H.height / 2);
this.addChild(this._label);
}
/**
* 設定 Cell 資料並更新顯示內容。
* @param index - 資料在列表中的位置
* @param data - 對應的數值內容
*/
setItem(index: number, data: number): void {
super.setItem(index, data); // 一定要呼叫,讓父類別記住 index 和 data,ListView 才能正確管理 Cell
// 重新繪製底色
this._background.clear()
.beginFill(index % 2 === 0 ? 0xddeeff : 0xaabbcc) // 依據 index 決定底色,交錯顯示兩種顏色
.drawRoundedRect(0.5, 0.5, NumberCell_H.width - 1, NumberCell_H.height - 1, 6)
.endFill();
this._label.text = `${data}`;
}
}
```
## ListView(清單元件)
**ListView** 是一個高效能的清單元件,繼承自 `ScrollView`,適用於大量資料的滾動顯示場景。
適用於大量資料的滾動顯示場景,例如排行榜、道具欄、選單等。
主要特性:
- 垂直或水平滾動顯示資料項目
- 自動建立、回收 Cell 項目以節省效能
- Cell 由 ListView 自動管理,會重複使用
- Cell 類別需繼承自 ListViewCell,並實作 setItem() 接收資料
注意事項:
- Cell 將由 ListView 自動管理,請勿自行新增或刪除
- Cell 的尺寸由靜態屬性 width / height 提供
### `ListView.addData(...data: U[]): void;`
加入一筆或多筆資料,並立即更新畫面。
- `data` — 欲加入的資料內容
### `ListView.refreshVisibleCells(): void;`
根據目前滾動位置更新可見 Cell。
- 回收不在顯示範圍內的 Cell
- 產生新的 Cell,設定資料與位置
### `ListView.jumpToIndex(index: number): void;`
瞬間跳轉到指定資料索引位置,讓該項目顯示在可視區起始處(上方或左方)。
- `index` — 欲顯示的資料索引
### 使用範例
```ts
// 請先確保該檔案頂層有 import(引入)ListView class(類別)
import ListView = CG.CookPixiUI.Components.ListView;
```
#### 建立垂直滑動區域
```ts
// 建立垂直 ListView 實例
const listView_V = new ListView<NumberCell_V, number>(
NumberCell_V.width,
CG.Base.pixi.stageHeight - 100,
NumberCell_V,
ListView.DIRECTION.VERTICAL
);
listView_V.position.set(50, 50);
CG.Base.pixi.root.addChild(listView_V);
// 填入資料
const numbers = Array.from({ length: 100 }, (item, i) => i + 1);
listView_V.addData(...numbers);
// 跳到第 26 筆
listView_V.jumpToIndex(26);
```
#### 建立水平滑動區域
```ts
// 建立水平 ListView 實例
const listView_H = new ListView<NumberCell_H, number>(
CG.Base.pixi.stageWidth - 400,
NumberCell_H.height,
NumberCell_H,
ListView.DIRECTION.HORIZONTAL
);
listView_H.position.set(350, CG.Base.pixi.stageHeight * 0.5 - NumberCell_H.height * 0.5);
CG.Base.pixi.root.addChild(listView_H);
// 填入資料
const numbers = Array.from({ length: 100 }, (item, i) => i + 1);
listView_H.addData(...numbers);
// 跳到第 50 筆
listView_H.jumpToIndex(50);
```
---
## Authors
**[cook1470](/profile/cook1470)**