mirror of
https://gitee.com/ulthon/ulthon_information.git
synced 2026-07-01 16:22:49 +08:00
fix(phone-image): replace estimate-based pagination with DOM-measured heights
This commit is contained in:
@@ -100,7 +100,7 @@ var PhoneImageEngine = (function () {
|
||||
|
||||
/**
|
||||
* 渲染排版预览 - 生成分页后的HTML
|
||||
* 两遍遍历: 先算总页数, 再带页码生成
|
||||
* 管线: preprocess -> parse -> renderContentFlow -> measure -> paginate -> generate -> renderThumbnails
|
||||
* @returns {jQuery Deferred} resolves with pages array
|
||||
*/
|
||||
function render() {
|
||||
@@ -113,36 +113,41 @@ var PhoneImageEngine = (function () {
|
||||
var cleanHtml = preprocessContent(postData.content_html);
|
||||
var blocks = parseHtmlToBlocks(cleanHtml);
|
||||
|
||||
// 封面页
|
||||
pages.push(generateCoverPage(sizeConfig));
|
||||
|
||||
// 内容分页
|
||||
var contentPages = paginateContent(blocks, contentAreaHeight, sizeConfig);
|
||||
pages = pages.concat(contentPages);
|
||||
|
||||
// 尾页
|
||||
pages.push(generateSummaryPage(sizeConfig, pages.length));
|
||||
|
||||
// 两遍遍历: 现在知道了总页数, 给每页补上 N/M 页码
|
||||
var totalPages = pages.length;
|
||||
for (var i = 0; i < pages.length; i++) {
|
||||
if (pages[i].type === 'content') {
|
||||
// 在页脚中添加 N/M 格式页码
|
||||
pages[i].html = pages[i].html.replace(
|
||||
'<span>' + pages[i].pageNum + '</span>',
|
||||
'<span class="page-number-indicator">' + (i + 1) + '/' + totalPages + '</span>'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// 渲染内容流(中间栏)- 同步
|
||||
// 先渲染内容流(DOM) - 用于实测高度
|
||||
renderContentFlow(blocks);
|
||||
|
||||
// 渲染缩略图(右侧)- 异步截图
|
||||
renderThumbnails(sizeConfig).then(function () {
|
||||
deferred.resolve(pages);
|
||||
}).catch(function (err) {
|
||||
deferred.reject(err);
|
||||
// DOM实测高度 - 等待一帧确保渲染完成
|
||||
requestAnimationFrame(function () {
|
||||
measureBlockHeights(blocks);
|
||||
|
||||
// 封面页
|
||||
pages.push(generateCoverPage(sizeConfig));
|
||||
|
||||
// 内容分页(使用实测高度)
|
||||
var contentPages = paginateContent(blocks, contentAreaHeight, sizeConfig);
|
||||
pages = pages.concat(contentPages);
|
||||
|
||||
// 尾页
|
||||
pages.push(generateSummaryPage(sizeConfig, pages.length));
|
||||
|
||||
// 两遍遍历: 现在知道了总页数, 给每页补上 N/M 页码
|
||||
var totalPages = pages.length;
|
||||
for (var i = 0; i < pages.length; i++) {
|
||||
if (pages[i].type === 'content') {
|
||||
// 在页脚中添加 N/M 格式页码
|
||||
pages[i].html = pages[i].html.replace(
|
||||
'<span>' + pages[i].pageNum + '</span>',
|
||||
'<span class="page-number-indicator">' + (i + 1) + '/' + totalPages + '</span>'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// 渲染缩略图(右侧)- 异步截图
|
||||
renderThumbnails(sizeConfig).then(function () {
|
||||
deferred.resolve(pages);
|
||||
}).catch(function (err) {
|
||||
deferred.reject(err);
|
||||
});
|
||||
});
|
||||
|
||||
return deferred.promise();
|
||||
@@ -158,15 +163,28 @@ var PhoneImageEngine = (function () {
|
||||
// 清除空段落
|
||||
html = html.replace(/<p[^>]*>\s*<\/p>/gi, '');
|
||||
|
||||
// 处理图片: 清除内联样式, 强制 max-width:100%
|
||||
// 处理图片: 保留原始尺寸到data属性, 强制 max-width:100%
|
||||
html = html.replace(/<img([^>]*?)>/gi, function (match, attrs) {
|
||||
// 移除 style, width, height 内联属性
|
||||
// 移除内联style
|
||||
attrs = attrs.replace(/\s*style\s*=\s*"[^"]*"/gi, '');
|
||||
attrs = attrs.replace(/\s*style\s*=\s*'[^']*'/gi, '');
|
||||
// 提取原始width/height值, 保存到data属性
|
||||
var widthVal = '';
|
||||
var heightVal = '';
|
||||
var widthMatch = attrs.match(/\swidth\s*=\s*"([^"]*)"/i) ||
|
||||
attrs.match(/\swidth\s*=\s*'([^']*)'/i);
|
||||
var heightMatch = attrs.match(/\sheight\s*=\s*"([^"]*)"/i) ||
|
||||
attrs.match(/\sheight\s*=\s*'([^']*)'/i);
|
||||
if (widthMatch) widthVal = widthMatch[1];
|
||||
if (heightMatch) heightVal = heightMatch[1];
|
||||
// 移除原始width/height属性
|
||||
attrs = attrs.replace(/\s*width\s*=\s*"[^"]*"/gi, '');
|
||||
attrs = attrs.replace(/\s*width\s*=\s*'[^']*'/gi, '');
|
||||
attrs = attrs.replace(/\s*height\s*=\s*"[^"]*"/gi, '');
|
||||
attrs = attrs.replace(/\s*height\s*=\s*'[^']*'/gi, '');
|
||||
// 添加data属性保存原始尺寸(用于比例计算)
|
||||
if (widthVal) attrs += ' data-original-width="' + widthVal + '"';
|
||||
if (heightVal) attrs += ' data-original-height="' + heightVal + '"';
|
||||
return '<img' + attrs + ' style="max-width:100%;height:auto;display:block;margin:10px 0;">';
|
||||
});
|
||||
|
||||
@@ -252,10 +270,20 @@ var PhoneImageEngine = (function () {
|
||||
case 'table':
|
||||
block.type = 'table';
|
||||
block.html = $el[0].outerHTML;
|
||||
block.estimatedHeight = estimateTableHeight($el);
|
||||
block.estimatedHeight = 0;
|
||||
block.needsMeasurement = true;
|
||||
break;
|
||||
case 'img':
|
||||
block.estimatedHeight = estimateImageHeight($el);
|
||||
// 尝试从data属性计算比例高度, 否则标记需要DOM测量
|
||||
var imgW = parseInt($el.attr('data-original-width'), 10);
|
||||
var imgH = parseInt($el.attr('data-original-height'), 10);
|
||||
if (imgW > 0 && imgH > 0) {
|
||||
var imgRatio = getContentWidth() / imgW;
|
||||
block.estimatedHeight = Math.round(imgH * imgRatio) + 20;
|
||||
} else {
|
||||
block.estimatedHeight = 0;
|
||||
block.needsMeasurement = true;
|
||||
}
|
||||
block.$img = $el;
|
||||
break;
|
||||
case 'ul':
|
||||
@@ -347,11 +375,12 @@ var PhoneImageEngine = (function () {
|
||||
}
|
||||
|
||||
/**
|
||||
* 估算表格高度
|
||||
* 估算表格高度 (已废弃 - DOM实测替代)
|
||||
* @deprecated 使用 measureBlockHeights() 替代
|
||||
*/
|
||||
function estimateTableHeight($table) {
|
||||
var rows = $table.find('tr').length;
|
||||
return rows * 36 + 20; // 36px per row (35px content + 1px border) + 20px margin
|
||||
// DOM实测将覆盖此值,返回0作为占位
|
||||
return 0;
|
||||
}
|
||||
|
||||
// ===== 分页核心算法 =====
|
||||
@@ -833,18 +862,22 @@ var PhoneImageEngine = (function () {
|
||||
}
|
||||
|
||||
/**
|
||||
* 渲染到隐藏区域 → 截图 → 显示缩略图
|
||||
* @param {Object} sizeConfig
|
||||
* @returns {jQuery Deferred} resolves with pages array
|
||||
* 共享截图核心逻辑 - 将pages渲染到staging并逐页截图
|
||||
* @param {Object} opts - { scale, outputCanvas, quality, sizeConfig }
|
||||
* scale: html2canvas缩放 (1=缩略图, 2=保存)
|
||||
* outputCanvas: true=输出canvas对象, false=输出dataURL字符串
|
||||
* quality: JPEG质量 (0-1)
|
||||
* sizeConfig: 尺寸配置(用于纯图片页canvas渲染)
|
||||
* @returns {jQuery Deferred} resolves with array of dataURL strings or canvas objects
|
||||
*/
|
||||
function renderThumbnails(sizeConfig) {
|
||||
function doCapturePages(opts) {
|
||||
var deferred = $.Deferred();
|
||||
ensureStaging();
|
||||
|
||||
var $staging = $('#render-staging');
|
||||
$staging.empty();
|
||||
|
||||
// 渲染所有页面到隐藏区域(使用wrapper以便html2canvas正确渲染)
|
||||
// 渲染所有页面到隐藏区域
|
||||
var sizeClass = 'size-' + config.size;
|
||||
var $wrapper = $('<div class="phone-image-container ' + sizeClass + '">');
|
||||
for (var i = 0; i < pages.length; i++) {
|
||||
@@ -852,118 +885,25 @@ var PhoneImageEngine = (function () {
|
||||
}
|
||||
$staging.append($wrapper);
|
||||
|
||||
// 等待一帧确保 DOM 渲染完成
|
||||
requestAnimationFrame(function () {
|
||||
// html2canvas会跳过visibility:hidden的元素,临时切换为可见
|
||||
$staging.css({ visibility: 'visible' });
|
||||
// 先转换代码块为图片
|
||||
convertCodeBlocks().then(function () {
|
||||
return convertTables();
|
||||
}).then(function () {
|
||||
var $pageElems = $staging.find('.phone-image-page');
|
||||
if ($pageElems.length === 0) {
|
||||
$staging.css({ visibility: 'hidden' });
|
||||
displayThumbnails([], sizeConfig);
|
||||
deferred.resolve(pages);
|
||||
return;
|
||||
}
|
||||
// 等待字体和DOM就绪
|
||||
var fontsReady = (typeof document.fonts !== 'undefined' && document.fonts.ready)
|
||||
? document.fonts.ready
|
||||
: $.Deferred().resolve().promise();
|
||||
|
||||
// 串行截图每一页
|
||||
var thumbnailDataUrls = [];
|
||||
var idx = 0;
|
||||
var total = $pageElems.length;
|
||||
|
||||
function captureNext() {
|
||||
if (idx >= total) {
|
||||
$staging.empty();
|
||||
$staging.css({ visibility: 'hidden' });
|
||||
displayThumbnails(thumbnailDataUrls, sizeConfig);
|
||||
deferred.resolve(pages);
|
||||
return;
|
||||
}
|
||||
|
||||
var $elem = $pageElems.eq(idx);
|
||||
// 纯图片页优化: 跳过html2canvas,直接用原图src
|
||||
if (isPureImagePage($elem)) {
|
||||
var pureSrc = getPureImageSrc($elem);
|
||||
if (pureSrc) {
|
||||
thumbnailDataUrls.push(pureSrc);
|
||||
idx++;
|
||||
captureNext();
|
||||
return;
|
||||
}
|
||||
}
|
||||
html2canvas($elem[0], {
|
||||
scale: 1,
|
||||
useCORS: true,
|
||||
backgroundColor: '#ffffff',
|
||||
width: $elem.outerWidth(),
|
||||
height: $elem.outerHeight(),
|
||||
logging: false
|
||||
}).then(function (canvas) {
|
||||
thumbnailDataUrls.push(canvas.toDataURL('image/jpeg', 0.85));
|
||||
idx++;
|
||||
captureNext();
|
||||
}).catch(function (err) {
|
||||
$staging.css({ visibility: 'hidden' });
|
||||
deferred.reject('截图失败(第' + (idx + 1) + '页): ' + err);
|
||||
fontsReady.then(function () {
|
||||
requestAnimationFrame(function () {
|
||||
// html2canvas会跳过visibility:hidden的元素,临时切换为可见
|
||||
$staging.css({ visibility: 'visible' });
|
||||
// 先转换代码块为图片
|
||||
convertCodeBlocks().then(function () {
|
||||
return convertTables();
|
||||
}).then(function () {
|
||||
runCaptureLoop($staging, opts, deferred);
|
||||
}).catch(function () {
|
||||
// 代码块转换失败,继续转换表格并截图流程
|
||||
convertTables().then(function () {
|
||||
runCaptureLoop($staging, opts, deferred);
|
||||
});
|
||||
}
|
||||
|
||||
captureNext();
|
||||
}).catch(function () {
|
||||
// 代码块转换失败,继续转换表格并截图流程
|
||||
convertTables().then(function () {
|
||||
var $pageElems = $staging.find('.phone-image-page');
|
||||
if ($pageElems.length === 0) {
|
||||
$staging.css({ visibility: 'hidden' });
|
||||
displayThumbnails([], sizeConfig);
|
||||
deferred.resolve(pages);
|
||||
return;
|
||||
}
|
||||
|
||||
var thumbnailDataUrls = [];
|
||||
var idx = 0;
|
||||
var total = $pageElems.length;
|
||||
|
||||
function captureNext() {
|
||||
if (idx >= total) {
|
||||
$staging.empty();
|
||||
$staging.css({ visibility: 'hidden' });
|
||||
displayThumbnails(thumbnailDataUrls, sizeConfig);
|
||||
deferred.resolve(pages);
|
||||
return;
|
||||
}
|
||||
|
||||
var $elem = $pageElems.eq(idx);
|
||||
// 纯图片页优化: 跳过html2canvas,直接用原图src
|
||||
if (isPureImagePage($elem)) {
|
||||
var pureSrc = getPureImageSrc($elem);
|
||||
if (pureSrc) {
|
||||
thumbnailDataUrls.push(pureSrc);
|
||||
idx++;
|
||||
captureNext();
|
||||
return;
|
||||
}
|
||||
}
|
||||
html2canvas($elem[0], {
|
||||
scale: 1,
|
||||
useCORS: true,
|
||||
backgroundColor: '#ffffff',
|
||||
width: $elem.outerWidth(),
|
||||
height: $elem.outerHeight(),
|
||||
logging: false
|
||||
}).then(function (canvas) {
|
||||
thumbnailDataUrls.push(canvas.toDataURL('image/jpeg', 0.85));
|
||||
idx++;
|
||||
captureNext();
|
||||
}).catch(function (err) {
|
||||
$staging.css({ visibility: 'hidden' });
|
||||
deferred.reject('截图失败(第' + (idx + 1) + '页): ' + err);
|
||||
});
|
||||
}
|
||||
|
||||
captureNext();
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -971,6 +911,117 @@ var PhoneImageEngine = (function () {
|
||||
return deferred.promise();
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行串行截图循环
|
||||
* @param {jQuery} $staging - staging元素
|
||||
* @param {Object} opts - 截图选项
|
||||
* @param {jQuery Deferred} deferred - 外部deferred
|
||||
*/
|
||||
function runCaptureLoop($staging, opts, deferred) {
|
||||
var $pageElems = $staging.find('.phone-image-page');
|
||||
if ($pageElems.length === 0) {
|
||||
$staging.css({ visibility: 'hidden' });
|
||||
if (opts.outputCanvas) {
|
||||
deferred.reject('没有可渲染的页面');
|
||||
} else {
|
||||
deferred.resolve([]);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
var results = [];
|
||||
var idx = 0;
|
||||
var total = $pageElems.length;
|
||||
|
||||
function captureNext() {
|
||||
if (idx >= total) {
|
||||
$staging.empty();
|
||||
$staging.css({ visibility: 'hidden' });
|
||||
deferred.resolve(results);
|
||||
return;
|
||||
}
|
||||
|
||||
var $elem = $pageElems.eq(idx);
|
||||
|
||||
// 纯图片页优化
|
||||
if (isPureImagePage($elem)) {
|
||||
var pureSrc = getPureImageSrc($elem);
|
||||
if (pureSrc) {
|
||||
if (opts.outputCanvas) {
|
||||
// 保存模式: 高质量绘制原图到canvas
|
||||
renderPureImageToCanvas(pureSrc, opts.sizeConfig.width, opts.sizeConfig.height).then(function (canvas) {
|
||||
results.push(canvas);
|
||||
idx++;
|
||||
captureNext();
|
||||
}).catch(function () {
|
||||
// 加载失败,回退到html2canvas
|
||||
capturePageViaHtml2Canvas($elem, $staging, opts, results, idx, total, deferred, captureNext);
|
||||
});
|
||||
return;
|
||||
} else {
|
||||
// 缩略图模式: 直接用src
|
||||
results.push(pureSrc);
|
||||
idx++;
|
||||
captureNext();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
capturePageViaHtml2Canvas($elem, $staging, opts, results, idx, total, deferred, captureNext);
|
||||
}
|
||||
|
||||
captureNext();
|
||||
}
|
||||
|
||||
/**
|
||||
* 用html2canvas截图单页
|
||||
*/
|
||||
function capturePageViaHtml2Canvas($elem, $staging, opts, results, idx, total, deferred, captureNext) {
|
||||
html2canvas($elem[0], {
|
||||
scale: opts.scale,
|
||||
useCORS: true,
|
||||
backgroundColor: '#ffffff',
|
||||
width: $elem.outerWidth(),
|
||||
height: $elem.outerHeight(),
|
||||
logging: false
|
||||
}).then(function (canvas) {
|
||||
if (opts.outputCanvas) {
|
||||
results.push(canvas);
|
||||
} else {
|
||||
results.push(canvas.toDataURL('image/jpeg', opts.quality));
|
||||
}
|
||||
idx++;
|
||||
captureNext();
|
||||
}).catch(function (err) {
|
||||
$staging.css({ visibility: 'hidden' });
|
||||
deferred.reject('截图失败(第' + (idx + 1) + '页): ' + err);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 渲染到隐藏区域 -> 截图 -> 显示缩略图
|
||||
* @param {Object} sizeConfig
|
||||
* @returns {jQuery Deferred} resolves with pages array
|
||||
*/
|
||||
function renderThumbnails(sizeConfig) {
|
||||
var deferred = $.Deferred();
|
||||
|
||||
doCapturePages({
|
||||
scale: 1,
|
||||
outputCanvas: false,
|
||||
quality: 0.85,
|
||||
sizeConfig: sizeConfig
|
||||
}).then(function (dataUrls) {
|
||||
displayThumbnails(dataUrls, sizeConfig);
|
||||
deferred.resolve(pages);
|
||||
}).catch(function (err) {
|
||||
deferred.reject(err);
|
||||
});
|
||||
|
||||
return deferred.promise();
|
||||
}
|
||||
|
||||
/**
|
||||
* 在右侧显示缩略图
|
||||
* @param {Array} dataUrls - base64 图片数据
|
||||
@@ -1021,171 +1072,35 @@ var PhoneImageEngine = (function () {
|
||||
* @returns {jQuery Deferred} resolves with canvas array
|
||||
*/
|
||||
function capturePagesFromStaging() {
|
||||
var deferred = $.Deferred();
|
||||
ensureStaging();
|
||||
|
||||
var $staging = $('#render-staging');
|
||||
$staging.empty();
|
||||
|
||||
var sizeConfig = config.sizes[config.size] || config.sizes.xiaohongshu;
|
||||
|
||||
// 添加 size class wrapper
|
||||
var sizeClass = 'size-' + config.size;
|
||||
var $wrapper = $('<div class="phone-image-container ' + sizeClass + '">');
|
||||
for (var i = 0; i < pages.length; i++) {
|
||||
$wrapper.append(pages[i].html);
|
||||
}
|
||||
$staging.append($wrapper);
|
||||
|
||||
requestAnimationFrame(function () {
|
||||
// html2canvas会跳过visibility:hidden的元素,临时切换为可见
|
||||
$staging.css({ visibility: 'visible' });
|
||||
// 先转换代码块为图片
|
||||
convertCodeBlocks().then(function () {
|
||||
return convertTables();
|
||||
}).then(function () {
|
||||
var $pageElems = $staging.find('.phone-image-page');
|
||||
if ($pageElems.length === 0) {
|
||||
$staging.css({ visibility: 'hidden' });
|
||||
deferred.reject('没有可渲染的页面');
|
||||
return;
|
||||
}
|
||||
|
||||
var canvases = [];
|
||||
var idx = 0;
|
||||
var total = $pageElems.length;
|
||||
|
||||
function captureNext() {
|
||||
if (idx >= total) {
|
||||
$staging.empty();
|
||||
$staging.css({ visibility: 'hidden' });
|
||||
deferred.resolve(canvases);
|
||||
return;
|
||||
}
|
||||
|
||||
var $elem = $pageElems.eq(idx);
|
||||
// 纯图片页优化: 直接绘制原图到canvas
|
||||
if (isPureImagePage($elem)) {
|
||||
var pureSrc = getPureImageSrc($elem);
|
||||
if (pureSrc) {
|
||||
renderPureImageToCanvas(pureSrc, sizeConfig.width, sizeConfig.height).then(function (canvas) {
|
||||
canvases.push(canvas);
|
||||
idx++;
|
||||
captureNext();
|
||||
}).catch(function () {
|
||||
// 加载失败,回退到html2canvas
|
||||
html2canvas($elem[0], {
|
||||
scale: 2,
|
||||
useCORS: true,
|
||||
backgroundColor: '#ffffff',
|
||||
width: $elem.outerWidth(),
|
||||
height: $elem.outerHeight(),
|
||||
logging: false
|
||||
}).then(function (canvas) {
|
||||
canvases.push(canvas);
|
||||
idx++;
|
||||
captureNext();
|
||||
}).catch(function (err) {
|
||||
$staging.css({ visibility: 'hidden' });
|
||||
deferred.reject('截图失败(第' + (idx + 1) + '页): ' + err);
|
||||
});
|
||||
});
|
||||
return;
|
||||
}
|
||||
}
|
||||
html2canvas($elem[0], {
|
||||
scale: 2,
|
||||
useCORS: true,
|
||||
backgroundColor: '#ffffff',
|
||||
width: $elem.outerWidth(),
|
||||
height: $elem.outerHeight(),
|
||||
logging: false
|
||||
}).then(function (canvas) {
|
||||
canvases.push(canvas);
|
||||
idx++;
|
||||
captureNext();
|
||||
}).catch(function (err) {
|
||||
$staging.css({ visibility: 'hidden' });
|
||||
deferred.reject('截图失败(第' + (idx + 1) + '页): ' + err);
|
||||
});
|
||||
}
|
||||
|
||||
captureNext();
|
||||
}).catch(function () {
|
||||
// 代码块转换失败,继续转换表格并截图流程
|
||||
convertTables().then(function () {
|
||||
var $pageElems = $staging.find('.phone-image-page');
|
||||
if ($pageElems.length === 0) {
|
||||
$staging.css({ visibility: 'hidden' });
|
||||
deferred.reject('没有可渲染的页面');
|
||||
return;
|
||||
}
|
||||
|
||||
var canvases = [];
|
||||
var idx = 0;
|
||||
var total = $pageElems.length;
|
||||
|
||||
function captureNext() {
|
||||
if (idx >= total) {
|
||||
$staging.empty();
|
||||
$staging.css({ visibility: 'hidden' });
|
||||
deferred.resolve(canvases);
|
||||
return;
|
||||
}
|
||||
|
||||
var $elem = $pageElems.eq(idx);
|
||||
// 纯图片页优化: 直接绘制原图到canvas
|
||||
if (isPureImagePage($elem)) {
|
||||
var pureSrc = getPureImageSrc($elem);
|
||||
if (pureSrc) {
|
||||
renderPureImageToCanvas(pureSrc, sizeConfig.width, sizeConfig.height).then(function (canvas) {
|
||||
canvases.push(canvas);
|
||||
idx++;
|
||||
captureNext();
|
||||
}).catch(function () {
|
||||
// 加载失败,回退到html2canvas
|
||||
html2canvas($elem[0], {
|
||||
scale: 2,
|
||||
useCORS: true,
|
||||
backgroundColor: '#ffffff',
|
||||
width: $elem.outerWidth(),
|
||||
height: $elem.outerHeight(),
|
||||
logging: false
|
||||
}).then(function (canvas) {
|
||||
canvases.push(canvas);
|
||||
idx++;
|
||||
captureNext();
|
||||
}).catch(function (err) {
|
||||
$staging.css({ visibility: 'hidden' });
|
||||
deferred.reject('截图失败(第' + (idx + 1) + '页): ' + err);
|
||||
});
|
||||
});
|
||||
return;
|
||||
}
|
||||
}
|
||||
html2canvas($elem[0], {
|
||||
scale: 2,
|
||||
useCORS: true,
|
||||
backgroundColor: '#ffffff',
|
||||
width: $elem.outerWidth(),
|
||||
height: $elem.outerHeight(),
|
||||
logging: false
|
||||
}).then(function (canvas) {
|
||||
canvases.push(canvas);
|
||||
idx++;
|
||||
captureNext();
|
||||
}).catch(function (err) {
|
||||
$staging.css({ visibility: 'hidden' });
|
||||
deferred.reject('截图失败(第' + (idx + 1) + '页): ' + err);
|
||||
});
|
||||
}
|
||||
|
||||
captureNext();
|
||||
});
|
||||
});
|
||||
return doCapturePages({
|
||||
scale: 2,
|
||||
outputCanvas: true,
|
||||
quality: 0.92,
|
||||
sizeConfig: sizeConfig
|
||||
});
|
||||
}
|
||||
|
||||
return deferred.promise();
|
||||
/**
|
||||
* DOM实测高度 - 从#content-flow中读取每个块的实际渲染高度
|
||||
* @param {Array} blocks - parseHtmlToBlocks 返回的块数组
|
||||
*/
|
||||
function measureBlockHeights(blocks) {
|
||||
var $flow = $('#content-flow');
|
||||
if (!$flow.length) return;
|
||||
|
||||
for (var i = 0; i < blocks.length; i++) {
|
||||
var block = blocks[i];
|
||||
if (block.type === 'page-break') continue;
|
||||
|
||||
var $blockEl = $flow.find('.content-flow-block[data-index="' + i + '"]');
|
||||
if ($blockEl.length) {
|
||||
var actualHeight = Math.round($blockEl[0].getBoundingClientRect().height);
|
||||
if (actualHeight > 0) {
|
||||
block.estimatedHeight = actualHeight;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user