// Side previews: reduce the previous fill size by 20%, center the photograph, // then move it down by 5% of its // scaled height. Bake once; never let the native image crop it again. var W = 208.7, H = 184.5; function rectangle(width, height) { if (!(typeof width === 'number' && isFinite(width) && width > 0 && typeof height === 'number' && isFinite(height) && height > 0)) return null; var scale = Math.max(W / width, H / height) * 1.4 * .8; var w = width * scale, h = height * scale; return { left: Math.max(W - w, Math.min(0, (W - w) / 2)), top: (H - h) / 2 + h * .05, width: w, height: h }; } function bake(platform, options) { return new Promise(function (resolve, reject) { var rect = rectangle(options.width, options.height), settled = false; function fail(error) { if (!settled) { settled = true; reject(error || new Error('图片生成失败')); } } function accept(result) { if (settled) return; var src = typeof result === 'string' ? result : result && (result.dataURL || result.dataUrl); if (typeof src !== 'string' || !/^data:image\/(jpeg|png);base64,/.test(src)) { fail(new Error('图片导出失败')); return; } settled = true; resolve(src); } if (!rect || !platform || typeof platform.createCanvasContext !== 'function') { fail(); return; } try { var ctx = platform.createCanvasContext('report-side-zoom-canvas'); if (!ctx || typeof ctx.toDataURL !== 'function') { fail(); return; } // Fixed, mounted canvas; all photo/layer coordinates share this scale. var scale = 4, width = 835, height = 738; ctx.clearRect(0, 0, width, height); ctx.setFillStyle('#F6F6F6'); ctx.fillRect(0, 0, width, height); ctx.drawImage(options.photo, rect.left * scale, rect.top * scale, rect.width * scale, rect.height * scale); if (options.dark) { ctx.setFillStyle('rgba(0,0,0,' + options.dark + ')'); ctx.fillRect(0, 0, width, height); } (options.layers || []).forEach(function (layer) { ctx.drawImage(layer, rect.left * scale, rect.top * scale, rect.width * scale, rect.height * scale); }); ctx.draw(false, function () { if (settled) return; try { var result = ctx.toDataURL({ x: 0, y: 0, width: width, height: height, destWidth: width, destHeight: height, fileType: 'jpg', quality: .95, success: accept, fail: fail }); if (result && typeof result.then === 'function') Promise.resolve(result).then(accept, fail); else if (typeof result === 'string') accept(result); } catch (error) { fail(error); } }); } catch (error) { fail(error); } }); } module.exports = { rectangle: rectangle, bake: bake };