fix(phoneimage): 修复渲染分页截断 - 测高包含margin并等待图片加载

This commit is contained in:
augushong
2026-05-13 12:35:10 +08:00
parent 29dbc7ca55
commit 37259cfb4b

View File

@@ -98,6 +98,9 @@ var PhoneImageEngine = (function () {
// 从预览区读取已预处理的内容
syncPreview();
var previewEl = document.getElementById('render-preview');
// 等待预览区内所有图片加载完成,否则 getBoundingClientRect 测高为0
waitForImages(previewEl).then(function () {
var cleanHtml = previewEl ? previewEl.innerHTML : '';
var blocks = parseHtmlToBlocks(cleanHtml);
@@ -111,7 +114,7 @@ var PhoneImageEngine = (function () {
// 封面页
pages.push(generateCoverPage(sizeConfig));
// 内容分页(使用 captureEditorBlocksT3 会完善截图逻辑)
// 内容分页
captureEditorBlocks(cleanHtml, blocks, contentAreaHeight, sizeConfig).then(function(contentPages) {
pages = pages.concat(contentPages);
@@ -145,6 +148,7 @@ var PhoneImageEngine = (function () {
render._locked = false;
deferred.reject(err);
});
});
return deferred.promise();
}
@@ -204,6 +208,44 @@ var PhoneImageEngine = (function () {
$('#render-preview').html(cleanHtml);
}
/**
* 等待容器内所有图片加载完成
* 图片未加载时 getBoundingClientRect() 高度为0导致分页计算错误
* @param {HTMLElement} containerEl
* @returns {jQuery Deferred}
*/
function waitForImages(containerEl) {
var deferred = $.Deferred();
var imgs = containerEl ? containerEl.querySelectorAll('img') : [];
if (imgs.length === 0) {
return deferred.resolve().promise();
}
var loaded = 0;
var total = imgs.length;
var timer = setTimeout(function () {
// 超时保底3秒后强制继续
deferred.resolve();
}, 3000);
function checkDone() {
loaded++;
if (loaded >= total) {
clearTimeout(timer);
deferred.resolve();
}
}
for (var i = 0; i < imgs.length; i++) {
if (imgs[i].complete && imgs[i].naturalHeight > 0) {
checkDone();
} else {
imgs[i].onload = checkDone;
imgs[i].onerror = checkDone;
}
}
return deferred.promise();
}
/**
* 将HTML解析为块级元素数组
* 每个块: { type, html, estimatedHeight }
@@ -392,30 +434,21 @@ var PhoneImageEngine = (function () {
var previewChildren = Array.prototype.slice.call(previewEl.children);
// 逐组测高
// 逐 block 精确测高(包含 margin否则分页偏小导致内容溢出
for (var gi = 0; gi < groups.length; gi++) {
var group = groups[gi];
var groupHeight = 0;
for (var j = 0; j < group.domIndices.length; j++) {
for (var j = 0; j < group.blocks.length; j++) {
var di = group.domIndices[j];
if (di < previewChildren.length) {
var rect = previewChildren[di].getBoundingClientRect();
groupHeight += Math.round(rect.height);
var el = previewChildren[di];
var rect = el.getBoundingClientRect();
var cs = window.getComputedStyle(el);
var mt = parseFloat(cs.marginTop) || 0;
var mb = parseFloat(cs.marginBottom) || 0;
group.blocks[j].estimatedHeight = Math.round(rect.height + mt + mb);
}
}
if (groupHeight === 0) groupHeight = group.blocks.length * 40;
// 按比例分配测量的实际高度给组内各个 block
var totalEstimated = 0;
for (var k = 0; k < group.blocks.length; k++) {
totalEstimated += (group.blocks[k].estimatedHeight || 40);
}
for (var k = 0; k < group.blocks.length; k++) {
var ratio = (group.blocks[k].estimatedHeight || 40) / (totalEstimated || 1);
group.blocks[k].estimatedHeight = Math.round(groupHeight * ratio);
}
}
// 给尚未设置高度的 block 设默认值