135 lines
4.5 KiB
Plaintext
135 lines
4.5 KiB
Plaintext
// 尝试捕获 Obsidian 原生 Canvas 渲染(通过临时调整视口大小)
|
||
async tryNativeCanvasCapture(canvasFile: TFile): Promise<Uint8Array | null> {
|
||
let uiStyleElement: HTMLStyleElement | null = null;
|
||
let sizeStyleElement: HTMLStyleElement | null = null;
|
||
let activeLeaf: any = null;
|
||
let canvasWrapper: HTMLElement | null = null;
|
||
let originalScrollLeft = 0;
|
||
let originalScrollTop = 0;
|
||
|
||
try {
|
||
console.log('🔍 Step 1: Getting active workspace leaf...');
|
||
|
||
// 获取当前活动的 leaf(不创建新窗口)
|
||
activeLeaf = this.app.workspace.activeLeaf;
|
||
if (!activeLeaf) {
|
||
console.log('❌ No active leaf found');
|
||
return null;
|
||
}
|
||
|
||
console.log('🔍 Step 2: Opening canvas file...');
|
||
await activeLeaf.openFile(canvasFile);
|
||
|
||
console.log('⏳ Step 3: Waiting for canvas render...');
|
||
await this.waitForCanvasRender();
|
||
|
||
console.log('🔍 Step 4: Finding canvas DOM...');
|
||
const canvasDom = this.findCanvasDomElement();
|
||
if (!canvasDom) {
|
||
console.log('❌ Could not find canvas DOM element');
|
||
return null;
|
||
}
|
||
|
||
console.log('✅ Found canvas DOM:', canvasDom.className, 'Size:', (canvasDom as any).offsetWidth, 'x', (canvasDom as any).offsetHeight);
|
||
|
||
console.log('🎨 Step 5: Hiding Canvas UI elements...');
|
||
uiStyleElement = this.hideCanvasUIElements();
|
||
|
||
console.log('📐 Step 6: Calculating canvas content size...');
|
||
const contentSize = this.getCanvasContentSize(canvasDom);
|
||
|
||
// 获取 canvasWrapper
|
||
if ((canvasDom as HTMLElement).classList.contains('canvas-wrapper')) {
|
||
canvasWrapper = canvasDom as HTMLElement;
|
||
} else {
|
||
canvasWrapper = canvasDom.querySelector('.canvas-wrapper') as HTMLElement;
|
||
}
|
||
|
||
if (!canvasWrapper) {
|
||
console.log('❌ Could not find canvas wrapper');
|
||
return null;
|
||
}
|
||
|
||
// 保存原始滚动位置
|
||
originalScrollLeft = canvasWrapper.scrollLeft;
|
||
originalScrollTop = canvasWrapper.scrollTop;
|
||
|
||
console.log(`📏 Original wrapper size: ${(canvasDom as any).offsetWidth}x${(canvasDom as any).offsetHeight}`);
|
||
console.log(`📏 Content size: ${contentSize.width}x${contentSize.height}`);
|
||
|
||
// 临时调整 canvas wrapper 大小以适应所有内容
|
||
console.log('🔧 Temporarily resizing canvas wrapper to fit all content...');
|
||
sizeStyleElement = document.createElement('style');
|
||
sizeStyleElement.id = 'canvas-export-resize';
|
||
sizeStyleElement.textContent = `
|
||
/* 临时调整 canvas wrapper 大小 */
|
||
.canvas-wrapper {
|
||
width: ${contentSize.width + 100}px !important;
|
||
height: ${contentSize.height + 100}px !important;
|
||
max-width: ${contentSize.width + 100}px !important;
|
||
max-height: ${contentSize.height + 100}px !important;
|
||
overflow: visible !important;
|
||
}
|
||
|
||
/* 确保画布内容区域也扩展 */
|
||
.canvas-view-content {
|
||
width: ${contentSize.width + 100}px !important;
|
||
height: ${contentSize.height + 100}px !important;
|
||
}
|
||
`;
|
||
document.head.appendChild(sizeStyleElement);
|
||
|
||
// 等待样式应用
|
||
await new Promise(resolve => setTimeout(resolve, 100));
|
||
|
||
// 重置滚动位置
|
||
canvasWrapper.scrollLeft = 0;
|
||
canvasWrapper.scrollTop = 0;
|
||
|
||
// 等待布局更新
|
||
await new Promise(resolve => setTimeout(resolve, 200));
|
||
|
||
console.log('📸 Step 7: Capturing canvas...');
|
||
// @ts-ignore
|
||
const domToImage = require('dom-to-image-more');
|
||
|
||
const dataUrl = await domToImage.toPng(canvasDom, {
|
||
backgroundColor: '#ffffff',
|
||
quality: 1,
|
||
width: contentSize.width,
|
||
height: contentSize.height,
|
||
cacheBust: true
|
||
});
|
||
|
||
const imageData = this.dataUrlToUint8Array(dataUrl);
|
||
|
||
console.log('✅ Capture successful!');
|
||
|
||
return imageData;
|
||
|
||
} catch (error) {
|
||
console.error('❌ Native canvas capture failed:', error);
|
||
return null;
|
||
} finally {
|
||
// 清理临时调整大小的样式
|
||
if (sizeStyleElement && sizeStyleElement.parentNode) {
|
||
sizeStyleElement.parentNode.removeChild(sizeStyleElement);
|
||
console.log('🧹 Removed temporary resize styles');
|
||
}
|
||
|
||
if (uiStyleElement && uiStyleElement.parentNode) {
|
||
uiStyleElement.parentNode.removeChild(uiStyleElement);
|
||
console.log('🧹 Cleaned up UI hiding styles');
|
||
}
|
||
|
||
// 恢复滚动位置
|
||
if (canvasWrapper) {
|
||
canvasWrapper.scrollLeft = originalScrollLeft;
|
||
canvasWrapper.scrollTop = originalScrollTop;
|
||
console.log('🔄 Restored original scroll position');
|
||
}
|
||
|
||
console.log('🧹 Cleanup complete');
|
||
}
|
||
}
|