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(); syncPreview();
var previewEl = document.getElementById('render-preview'); var previewEl = document.getElementById('render-preview');
// 等待预览区内所有图片加载完成,否则 getBoundingClientRect 测高为0
waitForImages(previewEl).then(function () {
var cleanHtml = previewEl ? previewEl.innerHTML : ''; var cleanHtml = previewEl ? previewEl.innerHTML : '';
var blocks = parseHtmlToBlocks(cleanHtml); var blocks = parseHtmlToBlocks(cleanHtml);
@@ -111,7 +114,7 @@ var PhoneImageEngine = (function () {
// 封面页 // 封面页
pages.push(generateCoverPage(sizeConfig)); pages.push(generateCoverPage(sizeConfig));
// 内容分页(使用 captureEditorBlocksT3 会完善截图逻辑) // 内容分页
captureEditorBlocks(cleanHtml, blocks, contentAreaHeight, sizeConfig).then(function(contentPages) { captureEditorBlocks(cleanHtml, blocks, contentAreaHeight, sizeConfig).then(function(contentPages) {
pages = pages.concat(contentPages); pages = pages.concat(contentPages);
@@ -145,6 +148,7 @@ var PhoneImageEngine = (function () {
render._locked = false; render._locked = false;
deferred.reject(err); deferred.reject(err);
}); });
});
return deferred.promise(); return deferred.promise();
} }
@@ -204,6 +208,44 @@ var PhoneImageEngine = (function () {
$('#render-preview').html(cleanHtml); $('#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解析为块级元素数组 * 将HTML解析为块级元素数组
* 每个块: { type, html, estimatedHeight } * 每个块: { type, html, estimatedHeight }
@@ -392,30 +434,21 @@ var PhoneImageEngine = (function () {
var previewChildren = Array.prototype.slice.call(previewEl.children); var previewChildren = Array.prototype.slice.call(previewEl.children);
// 逐组测高 // 逐 block 精确测高(包含 margin否则分页偏小导致内容溢出
for (var gi = 0; gi < groups.length; gi++) { for (var gi = 0; gi < groups.length; gi++) {
var group = groups[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]; var di = group.domIndices[j];
if (di < previewChildren.length) { if (di < previewChildren.length) {
var rect = previewChildren[di].getBoundingClientRect(); var el = previewChildren[di];
groupHeight += Math.round(rect.height); 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 设默认值 // 给尚未设置高度的 block 设默认值