接入画布
This commit is contained in:
@@ -0,0 +1,702 @@
|
||||
/**
|
||||
* 增强版液化管理器
|
||||
* 整合WebGL和CPU实现,智能选择最佳渲染方式
|
||||
*/
|
||||
import { LiquifyWebGLManager } from "./LiquifyWebGLManager";
|
||||
import { LiquifyCPUManager } from "./LiquifyCPUManager";
|
||||
|
||||
export class EnhancedLiquifyManager {
|
||||
/**
|
||||
* 创建增强版液化管理器
|
||||
* @param {Object} options 配置选项
|
||||
*/
|
||||
constructor(options = {}) {
|
||||
this.config = {
|
||||
// 性能阈值:图像超过此尺寸会尝试使用WebGL
|
||||
webglSizeThreshold: options.webglSizeThreshold || 1000 * 1000, // 默认100万像素
|
||||
// 是否强制使用CPU模式
|
||||
forceCPU: options.forceCPU || false,
|
||||
// 是否强制使用WebGL模式
|
||||
forceWebGL: options.forceWebGL || false,
|
||||
// 网格大小
|
||||
gridSize: options.gridSize || 15,
|
||||
// 最大变形强度
|
||||
maxStrength: options.maxStrength || 100,
|
||||
// 平滑迭代次数
|
||||
smoothingIterations: options.smoothingIterations || 2,
|
||||
// 网格弹性因子
|
||||
relaxFactor: options.relaxFactor || 0.25,
|
||||
// WebGL网格精度
|
||||
meshResolution: options.meshResolution || 64,
|
||||
};
|
||||
|
||||
// 性能监控
|
||||
this.performance = {
|
||||
lastOperationTime: 0,
|
||||
renderTimes: [], // 最近的渲染时间记录
|
||||
isPerformanceIssue: false, // 是否存在性能问题
|
||||
operationCount: 0, // 操作计数
|
||||
};
|
||||
|
||||
// 初始化标志
|
||||
this.initialized = false;
|
||||
|
||||
// 当前参数
|
||||
this.params = {
|
||||
size: 50, // 工具尺寸
|
||||
pressure: 0.5, // 压力大小 (0-1)
|
||||
distortion: 0, // 失真程度 (0-1)
|
||||
power: 0.5, // 动力/强度 (0-1)
|
||||
};
|
||||
|
||||
// 液化工具模式
|
||||
this.modes = {
|
||||
PUSH: "push",
|
||||
CLOCKWISE: "clockwise",
|
||||
COUNTERCLOCKWISE: "counterclockwise",
|
||||
PINCH: "pinch",
|
||||
EXPAND: "expand",
|
||||
CRYSTAL: "crystal",
|
||||
EDGE: "edge",
|
||||
RECONSTRUCT: "reconstruct",
|
||||
};
|
||||
|
||||
// 当前模式
|
||||
this.currentMode = this.modes.PUSH;
|
||||
|
||||
// 图像数据和目标对象
|
||||
this.originalImageData = null;
|
||||
this.currentImageData = null;
|
||||
this.targetObject = null;
|
||||
this.targetLayerId = null;
|
||||
|
||||
// 创建渲染器实例
|
||||
this.webglRenderer = null;
|
||||
this.cpuRenderer = null;
|
||||
|
||||
// 当前激活的渲染器
|
||||
this.activeRenderer = null;
|
||||
this.renderMode = "unknown"; // 'webgl', 'cpu', 'unknown'
|
||||
|
||||
// 画布和管理器引用
|
||||
this.canvas = options.canvas || null;
|
||||
this.layerManager = options.layerManager || null;
|
||||
|
||||
// 渲染器状态
|
||||
this.isWebGLAvailable = LiquifyWebGLManager.isSupported();
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化液化管理器
|
||||
* @param {Object} options 配置选项
|
||||
* @returns {Boolean} 是否初始化成功
|
||||
*/
|
||||
initialize(options = {}) {
|
||||
if (options.canvas) this.canvas = options.canvas;
|
||||
if (options.layerManager) this.layerManager = options.layerManager;
|
||||
|
||||
if (!this.canvas || !this.layerManager) {
|
||||
console.error("液化管理器初始化失败:缺少canvas或layerManager");
|
||||
return false;
|
||||
}
|
||||
|
||||
// 记录初始化时间,用于性能监控
|
||||
this.performance.lastInitTime = Date.now();
|
||||
|
||||
// 创建CPU渲染器 (始终创建作为备选)
|
||||
this.cpuRenderer = new LiquifyCPUManager({
|
||||
gridSize: this.config.gridSize,
|
||||
maxStrength: this.config.maxStrength,
|
||||
smoothingIterations: this.config.smoothingIterations,
|
||||
relaxFactor: this.config.relaxFactor,
|
||||
});
|
||||
|
||||
// 检查是否应创建WebGL渲染器
|
||||
if (this.isWebGLAvailable && !this.config.forceCPU) {
|
||||
this.webglRenderer = new LiquifyWebGLManager({
|
||||
gridSize: this.config.gridSize,
|
||||
maxStrength: this.config.maxStrength,
|
||||
meshResolution: this.config.meshResolution,
|
||||
});
|
||||
}
|
||||
|
||||
this.initialized = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 为液化操作准备图像
|
||||
* @param {Object|String} target 目标对象或图层ID
|
||||
* @returns {Promise<Object>} 准备结果
|
||||
*/
|
||||
async prepareForLiquify(target) {
|
||||
if (!this.initialized) {
|
||||
throw new Error("液化管理器未初始化");
|
||||
}
|
||||
|
||||
let targetObject, targetLayerId;
|
||||
|
||||
// 处理传入的是图层ID的情况
|
||||
if (typeof target === "string") {
|
||||
targetLayerId = target;
|
||||
const layer = this.layerManager.getLayerById(targetLayerId);
|
||||
|
||||
// 检查图层是否存在和是否有对象
|
||||
let hasObjects = false;
|
||||
if (layer) {
|
||||
if (layer.type === "background" && layer.fabricObject) {
|
||||
hasObjects = true;
|
||||
targetObject = layer.fabricObject;
|
||||
} else if (layer.fabricObjects && layer.fabricObjects.length > 0) {
|
||||
hasObjects = true;
|
||||
targetObject = layer.fabricObjects[0];
|
||||
}
|
||||
}
|
||||
|
||||
if (!hasObjects) {
|
||||
throw new Error("目标图层为空或不存在");
|
||||
}
|
||||
} else if (typeof target === "object") {
|
||||
// 传入的是对象
|
||||
targetObject = target;
|
||||
const layer = this.layerManager.findLayerByObject(targetObject);
|
||||
if (layer) {
|
||||
targetLayerId = layer.id;
|
||||
} else {
|
||||
throw new Error("无法找到目标对象所属图层");
|
||||
}
|
||||
} else {
|
||||
throw new Error("无效的目标参数");
|
||||
}
|
||||
|
||||
// 检查是否为图像对象
|
||||
if (!targetObject || targetObject.type !== "image") {
|
||||
throw new Error("目标对象不是图像,无法进行液化操作");
|
||||
}
|
||||
|
||||
// 保存目标对象引用
|
||||
this.targetObject = targetObject;
|
||||
this.targetLayerId = targetLayerId;
|
||||
|
||||
// 获取图像数据
|
||||
const imageData = await this._getImageData(targetObject);
|
||||
if (!imageData) {
|
||||
throw new Error("无法获取图像数据");
|
||||
}
|
||||
|
||||
// 保存原始图像数据
|
||||
this.originalImageData = imageData;
|
||||
this.currentImageData = this._cloneImageData(imageData);
|
||||
|
||||
// 检查图像大小,选择适合的渲染器
|
||||
await this._selectRenderer(imageData);
|
||||
|
||||
// 预热选定的渲染器
|
||||
await this._warmupRenderer(imageData);
|
||||
|
||||
return {
|
||||
targetObject: this.targetObject,
|
||||
targetLayerId: this.targetLayerId,
|
||||
imageData: this.currentImageData,
|
||||
originalImageData: this.originalImageData,
|
||||
renderMode: this.renderMode,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据图像大小和设备性能选择渲染器
|
||||
* @param {ImageData} imageData 图像数据
|
||||
* @private
|
||||
*/
|
||||
async _selectRenderer(imageData) {
|
||||
// 计算图像大小
|
||||
const pixelCount = imageData.width * imageData.height;
|
||||
|
||||
console.log(
|
||||
`液化选择渲染器: 图像大小=${pixelCount}像素, WebGL可用=${this.isWebGLAvailable}`
|
||||
);
|
||||
|
||||
// 默认使用CPU渲染器
|
||||
this.activeRenderer = this.cpuRenderer;
|
||||
this.renderMode = "cpu";
|
||||
|
||||
// 如果配置强制使用WebGL
|
||||
if (this.config.forceWebGL && this.isWebGLAvailable && this.webglRenderer) {
|
||||
console.log("液化功能: 强制使用WebGL渲染模式");
|
||||
this.activeRenderer = this.webglRenderer;
|
||||
this.renderMode = "webgl";
|
||||
return;
|
||||
}
|
||||
|
||||
// 如果配置强制使用CPU
|
||||
if (this.config.forceCPU) {
|
||||
console.log("液化功能: 强制使用CPU渲染模式");
|
||||
return;
|
||||
}
|
||||
|
||||
// 根据图像大小和WebGL可用性决定
|
||||
if (
|
||||
pixelCount > this.config.webglSizeThreshold / 2 && // 降低阈值,让更多尺寸的图像使用WebGL
|
||||
this.isWebGLAvailable &&
|
||||
this.webglRenderer
|
||||
) {
|
||||
// 切换到WebGL渲染器
|
||||
console.log("液化功能: 自动选择WebGL渲染模式(基于图像尺寸)");
|
||||
this.activeRenderer = this.webglRenderer;
|
||||
this.renderMode = "webgl";
|
||||
} else {
|
||||
console.log(
|
||||
`液化功能: 使用CPU渲染模式${
|
||||
!this.isWebGLAvailable ? " (WebGL不可用)" : ""
|
||||
}`
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 预热渲染器
|
||||
* @param {ImageData} imageData 图像数据
|
||||
* @private
|
||||
*/
|
||||
async _warmupRenderer(imageData) {
|
||||
// 创建图像元素
|
||||
const img = document.createElement("img");
|
||||
|
||||
// 将ImageData转换为URL
|
||||
const canvas = document.createElement("canvas");
|
||||
canvas.width = imageData.width;
|
||||
canvas.height = imageData.height;
|
||||
const ctx = canvas.getContext("2d");
|
||||
ctx.putImageData(imageData, 0, 0);
|
||||
|
||||
// 使用Promise等待图像加载
|
||||
await new Promise((resolve, reject) => {
|
||||
img.onload = resolve;
|
||||
img.onerror = reject;
|
||||
img.src = canvas.toDataURL();
|
||||
});
|
||||
|
||||
// 初始化当前渲染器
|
||||
if (this.activeRenderer) {
|
||||
if (this.renderMode === "webgl") {
|
||||
this.activeRenderer.initialize(img);
|
||||
} else {
|
||||
this.activeRenderer.initialize(imageData);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置液化模式
|
||||
* @param {String} mode 模式名称
|
||||
*/
|
||||
setMode(mode) {
|
||||
if (Object.values(this.modes).includes(mode)) {
|
||||
this.currentMode = mode;
|
||||
|
||||
// 同步更新当前渲染器
|
||||
if (this.activeRenderer) {
|
||||
this.activeRenderer.setMode(mode);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置液化参数
|
||||
* @param {String} param 参数名称
|
||||
* @param {Number} value 参数值
|
||||
*/
|
||||
setParam(param, value) {
|
||||
if (param in this.params) {
|
||||
this.params[param] = value;
|
||||
|
||||
// 同步更新当前渲染器
|
||||
if (this.activeRenderer) {
|
||||
this.activeRenderer.setParam(param, value);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前参数
|
||||
* @returns {Object} 当前参数对象
|
||||
*/
|
||||
getParams() {
|
||||
return { ...this.params };
|
||||
}
|
||||
|
||||
/**
|
||||
* 重置参数为默认值
|
||||
*/
|
||||
resetParams() {
|
||||
this.params = {
|
||||
size: 50,
|
||||
pressure: 0.5,
|
||||
distortion: 0,
|
||||
power: 0.5,
|
||||
};
|
||||
|
||||
// 同步更新当前渲染器
|
||||
if (this.activeRenderer) {
|
||||
this.activeRenderer.resetParams();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 应用液化变形
|
||||
* @param {Object} target 目标对象
|
||||
* @param {String} mode 液化模式
|
||||
* @param {Object} params 液化参数
|
||||
* @param {Number} x 操作中心点X坐标 (图像像素坐标)
|
||||
* @param {Number} y 操作中心点Y坐标 (图像像素坐标)
|
||||
* @returns {Promise<ImageData>} 处理后的图像数据
|
||||
*/
|
||||
async applyLiquify(target, mode, params, x, y) {
|
||||
// 性能追踪开始
|
||||
const startTime = performance.now();
|
||||
|
||||
// 如果首次调用,先准备环境
|
||||
if (!this.targetObject || this.targetObject !== target) {
|
||||
await this.prepareForLiquify(target);
|
||||
}
|
||||
|
||||
// 更新模式和参数
|
||||
if (mode) this.setMode(mode);
|
||||
if (params) {
|
||||
for (const [key, value] of Object.entries(params)) {
|
||||
this.setParam(key, value);
|
||||
}
|
||||
}
|
||||
|
||||
// 验证坐标是否在图像范围内
|
||||
if (!this.originalImageData) {
|
||||
console.error("缺少原始图像数据");
|
||||
return null;
|
||||
}
|
||||
|
||||
const imageWidth = this.originalImageData.width;
|
||||
const imageHeight = this.originalImageData.height;
|
||||
|
||||
// 坐标边界检查
|
||||
if (x < 0 || x >= imageWidth || y < 0 || y >= imageHeight) {
|
||||
console.warn(
|
||||
`液化坐标超出图像范围: (${x}, ${y}), 图像尺寸: ${imageWidth}x${imageHeight}`
|
||||
);
|
||||
return null;
|
||||
}
|
||||
|
||||
console.log(
|
||||
`应用液化变形: 模式=${mode}, 图像坐标=(${x}, ${y}), 图像尺寸=${imageWidth}x${imageHeight}`
|
||||
);
|
||||
|
||||
// 检查并应用变形
|
||||
if (this.activeRenderer && typeof x === "number" && typeof y === "number") {
|
||||
// 应用变形
|
||||
let result;
|
||||
|
||||
if (this.renderMode === "webgl") {
|
||||
// WebGL渲染器:传入图像像素坐标
|
||||
result = this.activeRenderer.applyDeformation(x, y);
|
||||
} else {
|
||||
// CPU渲染器:传入图像像素坐标
|
||||
result = this.activeRenderer.applyDeformation(x, y);
|
||||
}
|
||||
|
||||
// 更新当前图像数据
|
||||
if (result) {
|
||||
this.currentImageData = result;
|
||||
}
|
||||
|
||||
// 性能追踪结束
|
||||
const endTime = performance.now();
|
||||
this._trackPerformance(endTime - startTime);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
console.error("无法应用液化变形:渲染器未初始化或坐标无效");
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 追踪性能数据
|
||||
* @param {Number} time 操作耗时(毫秒)
|
||||
* @private
|
||||
*/
|
||||
_trackPerformance(time) {
|
||||
this.performance.lastOperationTime = time;
|
||||
this.performance.operationCount++;
|
||||
|
||||
// 维护最近10次操作的耗时记录
|
||||
this.performance.renderTimes.push(time);
|
||||
if (this.performance.renderTimes.length > 10) {
|
||||
this.performance.renderTimes.shift();
|
||||
}
|
||||
|
||||
// 计算平均耗时
|
||||
const avgTime =
|
||||
this.performance.renderTimes.reduce((sum, t) => sum + t, 0) /
|
||||
this.performance.renderTimes.length;
|
||||
|
||||
// 检测性能问题
|
||||
this.performance.isPerformanceIssue = avgTime > 100; // 如果平均耗时超过100毫秒
|
||||
|
||||
// 输出性能信息(调试用)
|
||||
if (this.performance.operationCount % 10 === 0) {
|
||||
console.log(
|
||||
`液化性能数据: 模式=${this.renderMode}, 平均耗时=${avgTime.toFixed(
|
||||
2
|
||||
)}ms, 图像尺寸=${this.originalImageData?.width}x${
|
||||
this.originalImageData?.height
|
||||
}`
|
||||
);
|
||||
}
|
||||
|
||||
// 如果使用WebGL但性能差,可以考虑切换到优化的CPU实现
|
||||
if (
|
||||
this.renderMode === "webgl" &&
|
||||
this.performance.isPerformanceIssue &&
|
||||
this.performance.operationCount > 5
|
||||
) {
|
||||
console.warn("WebGL液化性能不佳,考虑切换到CPU模式");
|
||||
// 注意:这里不自动切换,因为可能会导致中途渲染结果不一致
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 重置液化操作
|
||||
* @returns {ImageData} 重置后的图像数据
|
||||
*/
|
||||
reset() {
|
||||
if (!this.activeRenderer) return null;
|
||||
|
||||
// 使用当前渲染器重置
|
||||
const result = this.activeRenderer.reset();
|
||||
|
||||
// 更新当前图像数据
|
||||
if (result) {
|
||||
this.currentImageData = result;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查图层是否可以液化
|
||||
* @param {String} layerId 图层ID
|
||||
* @returns {Object} 检查结果
|
||||
*/
|
||||
checkLayerForLiquify(layerId) {
|
||||
if (!this.layerManager) {
|
||||
return {
|
||||
valid: false,
|
||||
message: "图层管理器未初始化",
|
||||
needsRasterization: false,
|
||||
isImage: false,
|
||||
isEmpty: true,
|
||||
isGroup: false,
|
||||
};
|
||||
}
|
||||
|
||||
// 获取图层
|
||||
const layer = this.layerManager.getLayerById(layerId);
|
||||
if (!layer) {
|
||||
return {
|
||||
valid: false,
|
||||
message: "图层不存在",
|
||||
needsRasterization: false,
|
||||
isImage: false,
|
||||
isEmpty: true,
|
||||
isGroup: false,
|
||||
};
|
||||
}
|
||||
|
||||
// 检查图层是否为空
|
||||
let objectsToCheck = [];
|
||||
if (layer.isBackground || layer.type === "background") {
|
||||
// 背景图层使用 fabricObject (单数)
|
||||
if (layer.fabricObject) {
|
||||
objectsToCheck = [layer.fabricObject];
|
||||
}
|
||||
} else {
|
||||
// 普通图层使用 fabricObjects (复数)
|
||||
objectsToCheck = layer.fabricObjects || [];
|
||||
}
|
||||
|
||||
if (objectsToCheck.length === 0) {
|
||||
return {
|
||||
valid: false,
|
||||
message: "图层为空,无法进行液化操作",
|
||||
needsRasterization: false,
|
||||
isImage: false,
|
||||
isEmpty: true,
|
||||
isGroup: false,
|
||||
};
|
||||
}
|
||||
|
||||
// 检查是否为单一图像
|
||||
const singleObject = objectsToCheck.length === 1;
|
||||
const isImage =
|
||||
singleObject &&
|
||||
(objectsToCheck[0].type === "image" ||
|
||||
objectsToCheck[0].type === "rasterized-layer");
|
||||
|
||||
// 检查是否为组
|
||||
const isGroup = objectsToCheck.some((obj) => obj.type === "group");
|
||||
|
||||
// 如果不是单一图像,需要栅格化
|
||||
const needsRasterization = !isImage || isGroup;
|
||||
|
||||
return {
|
||||
valid: isImage && !isGroup,
|
||||
message: isImage ? "图层可以进行液化操作" : "需要先将图层栅格化",
|
||||
needsRasterization: needsRasterization,
|
||||
isImage: isImage,
|
||||
isEmpty: false,
|
||||
isGroup: isGroup,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取图像数据
|
||||
* @param {Object} fabricObject Fabric图像对象
|
||||
* @returns {Promise<ImageData>} 图像数据
|
||||
* @private
|
||||
*/
|
||||
async _getImageData(fabricObject) {
|
||||
return new Promise((resolve, reject) => {
|
||||
try {
|
||||
// 创建临时canvas
|
||||
const tempCanvas = document.createElement("canvas");
|
||||
tempCanvas.width = fabricObject.width * fabricObject.scaleX;
|
||||
tempCanvas.height = fabricObject.height * fabricObject.scaleY;
|
||||
const tempCtx = tempCanvas.getContext("2d");
|
||||
|
||||
// 如果对象有图像元素
|
||||
if (fabricObject._element) {
|
||||
tempCtx.drawImage(
|
||||
fabricObject._element,
|
||||
0,
|
||||
0,
|
||||
tempCanvas.width,
|
||||
tempCanvas.height
|
||||
);
|
||||
} else if (fabricObject.getSrc) {
|
||||
// 通过URL创建图像
|
||||
const img = new Image();
|
||||
img.onload = () => {
|
||||
tempCtx.drawImage(img, 0, 0, tempCanvas.width, tempCanvas.height);
|
||||
const imageData = tempCtx.getImageData(
|
||||
0,
|
||||
0,
|
||||
tempCanvas.width,
|
||||
tempCanvas.height
|
||||
);
|
||||
resolve(imageData);
|
||||
};
|
||||
img.onerror = reject;
|
||||
img.src = fabricObject.getSrc();
|
||||
return;
|
||||
} else {
|
||||
reject(new Error("无法获取图像数据"));
|
||||
return;
|
||||
}
|
||||
|
||||
// 获取图像数据
|
||||
const imageData = tempCtx.getImageData(
|
||||
0,
|
||||
0,
|
||||
tempCanvas.width,
|
||||
tempCanvas.height
|
||||
);
|
||||
resolve(imageData);
|
||||
} catch (error) {
|
||||
reject(error);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 克隆图像数据
|
||||
* @param {ImageData} imageData 原始图像数据
|
||||
* @returns {ImageData} 克隆的图像数据
|
||||
* @private
|
||||
*/
|
||||
_cloneImageData(imageData) {
|
||||
if (!imageData) return null;
|
||||
|
||||
// 使用新的浏览器API直接复制
|
||||
if (typeof ImageData.prototype.constructor === "function") {
|
||||
try {
|
||||
return new ImageData(
|
||||
new Uint8ClampedArray(imageData.data),
|
||||
imageData.width,
|
||||
imageData.height
|
||||
);
|
||||
} catch (e) {
|
||||
console.warn("使用备选方法克隆ImageData");
|
||||
}
|
||||
}
|
||||
|
||||
// 备选方法
|
||||
const canvas = document.createElement("canvas");
|
||||
const ctx = canvas.getContext("2d");
|
||||
|
||||
canvas.width = imageData.width;
|
||||
canvas.height = imageData.height;
|
||||
|
||||
ctx.putImageData(imageData, 0, 0);
|
||||
|
||||
return ctx.getImageData(0, 0, imageData.width, imageData.height);
|
||||
}
|
||||
|
||||
/**
|
||||
* 释放资源
|
||||
*/
|
||||
dispose() {
|
||||
// 释放渲染器资源
|
||||
if (this.webglRenderer) {
|
||||
this.webglRenderer.dispose();
|
||||
this.webglRenderer = null;
|
||||
}
|
||||
|
||||
if (this.cpuRenderer) {
|
||||
this.cpuRenderer.dispose();
|
||||
this.cpuRenderer = null;
|
||||
}
|
||||
|
||||
// 清除引用
|
||||
this.activeRenderer = null;
|
||||
this.canvas = null;
|
||||
this.layerManager = null;
|
||||
this.targetObject = null;
|
||||
this.originalImageData = null;
|
||||
this.currentImageData = null;
|
||||
this.initialized = false;
|
||||
this.renderMode = "unknown";
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前状态信息
|
||||
* @returns {Object} 状态信息
|
||||
*/
|
||||
getStatus() {
|
||||
return {
|
||||
initialized: this.initialized,
|
||||
renderMode: this.renderMode,
|
||||
isWebGLAvailable: this.isWebGLAvailable,
|
||||
currentMode: this.currentMode,
|
||||
params: { ...this.params },
|
||||
performance: { ...this.performance },
|
||||
imageSize: this.originalImageData
|
||||
? `${this.originalImageData.width}x${this.originalImageData.height}`
|
||||
: "N/A",
|
||||
};
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user