USER
<script setup lang="ts">
import { onMounted, ref, reactive, computed, watch, Ref } from 'vue'
import { Pixihttp } from '../systems/http.ts'
import {
Spritesheet,
AnimatedSprite,
Texture,
Application,
Sprite,
} from 'pixi.js'
// import * as PIXI from 'pixi.js'
import liuxinPath from '@/assets/liuxin/liuxin.png'
import liuxinPathJS from '@/assets/liuxin/liuxin.json'
// 已有的状态
const checked_type = ref('1')
const model_id = ref('')
const canvasdomref = ref(null)
// 使用 reactive 创建响应式数组
const stable_diffusion_xls = reactive<Array<any>>([])
const fluxs = reactive<Array<any>>([])
// 分页状态
const currentPage = ref(1)
const itemsPerPage = 50
// 监听 checked_type 变化,重置 currentPage
watch(checked_type, () => {
currentPage.value = 1
})
// 计算总页数
const totalPages = computed(() => {
const totalItems =
checked_type.value === '1' ? stable_diffusion_xls.length : fluxs.length
return Math.ceil(totalItems / itemsPerPage)
})
// 计算当前页显示的模型
const paginatedModels = computed(() => {
const models = checked_type.value === '1' ? stable_diffusion_xls : fluxs
const start = (currentPage.value - 1) * itemsPerPage
const end = start + itemsPerPage
return models.slice(start, end)
})
// 新增:画廊相关状态
const images = reactive<Array<string>>([])
const galleryCurrentPage = ref(1)
const galleryItemsPerPage = 12
const code_input_ = ref('')
const ondraw = () => {
console.log(code_input_.value)
}
// 计算画廊总页数
const galleryTotalPages = computed(() =>
Math.ceil(images.length / galleryItemsPerPage)
)
// 计算当前页显示的图片
const paginatedGalleryImages = computed(() => {
const start = (galleryCurrentPage.value - 1) * galleryItemsPerPage
const end = start + galleryItemsPerPage
return images.slice(start, end)
})
// 监听 galleryCurrentPage 变化,确保其不超过总页数
watch(galleryTotalPages, (newTotal) => {
if (galleryCurrentPage.value > newTotal) {
galleryCurrentPage.value = newTotal
}
})
onMounted(async () => {
try {
const canvas = canvasdomref.value
let width = window.screen.width
let height = window.screen.height
if (width > height) {
console.log('横屏')
} else {
console.log('竖屏')
}
console.log('屏幕长宽:', width, height)
let app = new Application()
await app.init({ background: '#1099bb' })
let canvasInfo = app.canvas
const sprite = new Sprite(Texture.from(liuxinPath))
const liuxinsheet = new Spritesheet(Texture.from(liuxinPath), liuxinPathJS)
await liuxinsheet.parse()
const liuxinsp = new AnimatedSprite(
liuxinsheet.animations['9c0d85519fc29bd805102e958f2e83e5_wps图片']
)
liuxinsp.animationSpeed = 0.03
liuxinsp.width = 300
liuxinsp.height = 300
liuxinsp.loop = true
liuxinsp.gotoAndPlay(0)
const container = new PIXI.Container()
container.x = app.screen.width / 2
container.y = app.screen.height / 3
liuxinsp!.anchor.x = 0.5
liuxinsp!.anchor.y = 0.5
console.log(
'精灵当前位置-x:',
liuxinsp.position.x,
'y:',
liuxinsp.position.y
)
container.addChild(liuxinsp)
app.stage.addChild(container)
// @ts-ignore
canvas?.appendChild(canvasInfo)
const httpdata = await Pixihttp.get_model_list()
for (let entry of httpdata.data) {
if (entry.model_category === 'stable_diffusion_xl') {
stable_diffusion_xls.push(entry)
} else if (entry.model_category === 'flux') {
fluxs.push(entry)
}
}
// 按 api_calls 降序排序 stable_diffusion_xls
stable_diffusion_xls.sort((a, b) => b.api_calls - a.api_calls)
// 按 api_calls 降序排序 fluxs
fluxs.sort((a, b) => b.api_calls - a.api_calls)
console.log('Stable Diffusion XL Models:', stable_diffusion_xls)
console.log('Flux Models:', fluxs)
// 初始化画廊图片(假设有100张图片)
for (let i = 1; i <= 100; i++) {
images.push(
'https://cdn.pixabay.com/photo/2023/08/11/08/29/highland-cattle-8183107_1280.jpg'
)
}
} catch (error) {
console.error('Failed to fetch model list:', error)
}
})
</script>
<template>
<div class="root">
<div ref="canvasdomref">
<van-row justify="center">
<van-col :span="20">
<div class="main-container">
<!-- 标题部分 -->
<van-row class="header" justify="center">
<van-col>
<h1 class="title">模型测试</h1>
</van-col>
</van-row>
<!-- 模型类型选择 -->
<van-row class="section" justify="center">
<van-col :span="12">
<div class="model-type">
<van-radio-group
v-model="checked_type"
direction="horizontal"
>
<van-radio name="1">SD-XL</van-radio>
<van-radio name="2">FLUX</van-radio>
</van-radio-group>
</div>
</van-col>
</van-row>
<!-- 模型ID输入 -->
<van-row class="section" justify="center">
<van-col :span="12">
<div class="model-id">
<van-cell-group inset>
<van-field
v-model="model_id"
label="模型ID:"
left-icon="smile-o"
right-icon="warning-o"
placeholder="输入模型ID"
clearable
/>
</van-cell-group>
</div>
</van-col>
</van-row>
<!-- 模型列表和代码输入区域 -->
<van-row class="section align-stretch" justify="center">
<!-- 模型列表 -->
<van-col :span="12" class="flex-item">
<div class="model-list">
<v-list lines="one" density="compact" max-height="300">
<v-list-item
v-for="item in paginatedModels"
:key="item.model_id"
:title="item.model_name + ' 调用次数: ' + item.api_calls"
:subtitle="'模型ID: ' + item.model_id"
></v-list-item>
</v-list>
<v-pagination
v-model="currentPage"
:length="totalPages"
class="pagination"
></v-pagination>
</div>
</van-col>
<!-- 代码输入 -->
<van-col :span="12" class="flex-item">
<div class="code_input">
<v-container>
<v-textarea
row-height="15"
bg-color="amber-lighten-4"
color="orange orange-darken-4"
label="代码输入"
rows="10"
v-model="code_input_"
placeholder='{
"key": "",
"model_id": "your_model_id",
"prompt": "ultra realistic close up portrait ((beautiful pale cyberpunk female with heavy black eyeliner)), blue eyes, shaved side haircut, hyper detail, cinematic lighting, magic neon, dark red city, Canon EOS R3, nikon, f/1.4, ISO 200, 1/160s, 8K, RAW, unedited, symmetrical balance, in-frame, 8K",
"negative_prompt": "",
"width": "512",
"height": "512",
"samples": "1",
"num_inference_steps": "31",
"safety_checker": "no",
"enhance_prompt": "yes",
"seed": null,
"guidance_scale": 7.5,
"panorama": "no",
"self_attention": "no",
"upscale": "no",
"embeddings_model": null,
"lora_model": null,
"tomesd": "yes",
"clip_skip": "2",
"use_karras_sigmas": "yes",
"vae": null,
"lora_strength": null,
"scheduler": "UniPCMultistepScheduler",
"webhook": null,
"track_id": null
}'
auto-grow
></v-textarea>
</v-container>
<v-btn block @click="ondraw">开始绘图</v-btn>
</div>
</van-col>
</van-row>
<!-- 新增:画廊部分 -->
<van-row class="draw" justify="center">
<van-col :span="24">
<div class="gallery">
<h2 class="gallery-title">画廊</h2>
<van-row justify="start" wrap>
<van-col
v-for="(image, index) in paginatedGalleryImages"
:key="index"
:span="4"
class="gallery-item"
>
<img
:src="image"
alt="Gallery Image"
class="gallery-image"
/>
</van-col>
</van-row>
<v-pagination
v-model="galleryCurrentPage"
:length="galleryTotalPages"
class="pagination"
></v-pagination>
</div>
</van-col>
</van-row>
</div>
</van-col>
</van-row>
</div>
</div>
</template>
<style scoped>
.root {
background-color: #f5f5f5;
padding: 20px 0;
min-height: 100vh;
}
.main-container {
background-color: #ffffff;
padding: 30px;
border-radius: 8px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}
.header {
margin-bottom: 30px;
}
.title {
font-size: 24px;
font-weight: 600;
text-align: center;
color: #333333;
}
.section {
margin-bottom: 25px;
}
.align-stretch {
display: flex;
align-items: stretch;
}
.flex-item {
display: flex;
}
.model-type {
display: flex;
justify-content: center;
}
.model-id .van-field__control {
padding-left: 10px;
}
.model-list,
.code_input {
background-color: #fafafa;
padding: 15px;
border-radius: 6px;
border: 1px solid #eaeaea;
flex: 1;
display: flex;
flex-direction: column;
}
.gallery {
padding: 15px;
border-radius: 6px;
flex: 1;
display: flex;
flex-direction: column;
}
.draw {
background-color: #fafafa;
padding: 15px;
border-radius: 6px;
border: 1px solid #eaeaea;
flex: 1;
display: flex;
flex-direction: column;
}
.v-list-item {
padding: 10px 15px;
border-bottom: 1px solid #eaeaea;
flex: none;
}
.v-list-item:last-child {
border-bottom: none;
}
.v-list-item__title {
font-weight: 500;
color: #555555;
}
.v-list-item__subtitle {
color: #888888;
font-size: 14px;
}
.pagination {
display: flex;
justify-content: center;
margin-top: 20px;
flex-shrink: 0;
}
/* 画廊样式 */
.gallery {
padding: 20px 0;
}
.gallery-title {
text-align: center;
margin-bottom: 20px;
font-size: 20px;
color: #333333;
}
.gallery-item {
padding: 10px;
}
.gallery-image {
width: 100%;
height: auto;
border-radius: 4px;
object-fit: cover;
}
</style>
我得到了PreView.vue:88 PixiJS Warning: [Assets] Asset id /src/assets/liuxin/liuxin.png was not found in the Cache
(anonymous) @ PreView.vue:88
Promise.then
(anonymous) @ main.ts:26
Show 25 more frames
PreView.vue:89 PixiJS Warning: [Assets] Asset id /src/assets/liuxin/liuxin.png was not found in the Cache
PreView.vue:140 Failed to fetch model list: TypeError: Cannot read properties of undefined (reading 'source')
at new _Spritesheet2 (chunk-NQFDCHBS.js?v=53b38b7a:1280:34)
at PreView.vue:89:25
ASSISTANT
It seems you're encountering issues with loading assets using PixiJS in your Vue application. The warnings and errors you're seeing indicate that PixiJS is unable to locate or properly load your image and JSON files. Let's break down the problem and work towards a solution.
### Error Analysis
1. **Asset Not Found in Cache Warning:**
```
PreView.vue:88 PixiJS Warning: [Assets] Asset id /src/assets/liuxin/liuxin.png was not found in the Cache
```
This warning suggests that PixiJS cannot find the image asset in its cache when trying to create a texture from it.
2. **TypeError on Reading 'source':**
```
PreView.vue:140 Failed to fetch model list: TypeError: Cannot read properties of undefined (reading 'source')
at new _Spritesheet2 (chunk-NQFDCHBS.js?v=53b38b7a:1280:34)
at PreView.vue:89:25
```
This error occurs when attempting to create a new `Spritesheet`. PixiJS tries to access the `source` property of an undefined object, indicating that the texture or data required for the spritesheet isn't properly loaded.
### Possible Causes
- **Incorrect Asset Paths:**
The paths to your image and JSON files might not be resolving correctly, leading to failed imports.
- **TypeScript Module Declarations:**
TypeScript may not know how to handle imports of `.png` and `.json` files without proper module declarations.
- **Asynchronous Asset Loading:**
PixiJS might be trying to use assets before they are fully loaded, especially if the assets are large or if there's a loading delay.
### Solutions
#### 1. Verify Asset Paths and Imports
Ensure that the paths to your assets are correct. In your code, you're importing assets like this:
```typescript
import liuxinPath from '@/assets/liuxin/liuxin.png';
import liuxinPathJS from '@/assets/liuxin/liuxin.json';
```
- Confirm that the files exist in the specified directory.
- Check if the paths are correct relative to the `@` alias, which usually points to the `src` directory in Vue projects.
#### 2. Add TypeScript Declarations for Non-Code Assets
TypeScript needs to understand how to handle imports of image and JSON files. You can add custom type declarations to help TypeScript and your bundler (like Webpack or Vite) process these files.
- **Create a `types` directory in your `src` folder**, and add a file named `assets.d.ts`:
```typescript
// src/types/assets.d.ts
declare module '*.png' {
const value: string;
export default value;
}
declare module '*.json' {
const value: any;
export default value;
}
```
This tells TypeScript how to handle imports of `.png` and `.json` files.
- **Update the `tsconfig.json` to include the `types` directory**:
```json
{
"compilerOptions": {
// ... existing options ...
"typeRoots": ["./node_modules/@types", "./src/types"]
}
}
```
#### 3. Ensure Assets Are Properly Loaded Before Use
When working with PixiJS, it's crucial that all assets are fully loaded before you attempt to use them.
- **Use PixiJS's Asset Loader**:
Instead of direct imports, use PixiJS's Asset Loader to load your assets. This method ensures that assets are loaded asynchronously and are available in the PixiJS cache when needed.
```typescript
import { Assets } from 'pixi.js';
onMounted(async () => {
// Load assets
const [liuxinTexture, liuxinData] = await Promise.all([
Assets.load('@/assets/liuxin/liuxin.png'),
fetch('@/assets/liuxin/liuxin.json').then((response) => response.json()),
]);
// Create spritesheet
const liuxinSheet = new Spritesheet(liuxinTexture, liuxinData);
await liuxinSheet.parse();
// Continue with your code to create sprites, etc.
});
```
**Note**: Adjust the paths in `Assets.load` and `fetch` to match your project's structure.
#### 4. Verify the Content of Imported JSON
Make sure that the JSON file (`liuxin.json`) contains the correct data for your spritesheet.
- **Log the JSON Data**:
```typescript
console.log('liuxinPathJS:', liuxinPathJS);
```
This will help you verify that the data is correctly imported and contains the expected structure.
#### 5. Adjust the PixiJS Application Initialization
Typically, when initializing a PixiJS `Application`, you pass the options directly without an `init` method.
- **Update Application Creation**:
```typescript
const app = new Application({
background: '#1099bb',
});
```
Remove the `await app.init(...)` line, unless you're using a custom application class that requires initialization.
#### 6. Check for Asynchronous Data Fetching Issues
In your `onMounted` function, you're fetching a model list and then processing it:
```typescript
const httpdata = await Pixihttp.get_model_list();
// ... process data ...
```
If `httpdata` is `undefined` or doesn't have the expected structure, accessing its properties will result in errors.
- **Ensure `Pixihttp.get_model_list()` Returns Data**:
Verify that the `get_model_list` method is functioning correctly and returns the expected data structure.
- **Add Error Handling**:
```typescript
try {
const httpdata = await Pixihttp.get_model_list();
if (httpdata && httpdata.data) {
// Proceed with processing
} else {
console.error('Invalid data received:', httpdata);
}
} catch (error) {
console.error('Error fetching model list:', error);
}
```
### Summary of Steps
1. **Confirm asset paths and ensure that the files exist in the specified locations.**
2. **Add TypeScript declarations for `.png` and `.json` files.**
3. **Use PixiJS's Asset Loader to load assets asynchronously and ensure they're ready before use.**
4. **Verify that your JSON data is correctly imported and has the expected structure.**
5. **Simplify and correct the PixiJS application initialization if necessary.**
6. **Add proper error handling and verify data when fetching the model list.**
### Example Code Adjustment
Here's how you might adjust your `onMounted` function incorporating the above suggestions:
```typescript
import { onMounted, ref, reactive, computed, watch } from 'vue';
import { Application, Sprite, Spritesheet, AnimatedSprite, Assets, Container } from 'pixi.js';
onMounted(async () => {
try {
const canvas = canvasdomref.value;
const app = new Application({
backgroundColor: 0x1099bb,
width: window.innerWidth,
height: window.innerHeight,
});
canvas?.appendChild(app.view);
// Load assets
const [liuxinTexture, liuxinData] = await Promise.all([
Assets.load(liuxinPath),
fetch(liuxinPathJS).then((response) => response.json()),
]);
// Create spritesheet
const liuxinSheet = new Spritesheet(liuxinTexture, liuxinData);
await liuxinSheet.parse();
// Create animated sprite
const liuxinSp = new AnimatedSprite(liuxinSheet.animations['9c0d85519fc29bd805102e958f2e83e5_wps图片']);
liuxinSp.animationSpeed = 0.03;
liuxinSp.width = 300;
liuxinSp.height = 300;
liuxinSp.loop = true;
liuxinSp.anchor.set(0.5);
liuxinSp.play();
const container = new Container();
container.x = app.screen.width / 2;
container.y = app.screen.height / 3;
container.addChild(liuxinSp);
app.stage.addChild(container);
// Fetch model list
const httpdata = await Pixihttp.get_model_list();
if (httpdata && httpdata.data) {
for (let entry of httpdata.data) {
if (entry.model_category === 'stable_diffusion_xl') {
stable_diffusion_xls.push(entry);
} else if (entry.model_category === 'flux') {
fluxs.push(entry);
}
}
// Sort models
stable_diffusion_xls.sort((a, b) => b.api_calls - a.api_calls);
fluxs.sort((a, b) => b.api_calls - a.api_calls);
console.log('Stable Diffusion XL Models:', stable_diffusion_xls);
console.log('Flux Models:', fluxs);
} else {
console.error('Invalid data received:', httpdata);
}
// Initialize gallery images
for (let i = 1; i <= 100; i++) {
images.push('https://example.com/path/to/image.jpg');
}
} catch (error) {
console.error('An error occurred:', error);
}
});
```
### Additional Tips
- **Use Console Logging for Debugging**:
Insert `console.log` statements to verify the values of variables at different stages.
- **Check Network Tab in Developer Tools**:
Ensure that your assets are actually being requested and received by checking the Network tab in your browser's developer tools.
- **Consider Using Absolute Paths**:
Sometimes, using absolute paths can help avoid issues with asset loading.
- **Check Webpack or Vite Configuration**:
Ensure that your project's bundler is configured to handle image and JSON imports correctly.
### References
- [PixiJS Asset Loader](https://pixijs.download/release/docs/PIXI.Loader.html)
- [TypeScript Module Declarations](https://www.typescriptlang.org/docs/handbook/modules.html#ambient-modules)
- [Vue.js Asset Handling](https://cli.vuejs.org/guide/html-and-static-assets.html)
- [Importing JSON in TypeScript](https://www.typescriptlang.org/docs/handbook/modules.html#json-modules)
---
By following these steps, you should be able to resolve the asset loading issues and get your PixiJS application running smoothly within your Vue project.