/** * Reference-theme poster sharing runtime. * * @package AKSRT */ (function (window, document, $) { 'use strict'; var WIDTH = 768; var HEIGHT = 1168; var FONT = '-apple-system,BlinkMacSystemFont,"Segoe UI","Microsoft YaHei",Arial,sans-serif'; function notice(message, type) { if (typeof window.notyf === 'function') window.notyf(message, type || ''); } function ajaxUrl() { return (window.aksrtData && window.aksrtData.ajaxUrl) || (window._win && window._win.ajax_url) || ''; } function nonce() { return (window.aksrtData && window.aksrtData.nonce) || ''; } function loadImage(sources) { sources = sources.filter(Boolean); return new Promise(function (resolve, reject) { var index = 0; function next() { if (index >= sources.length) { reject(new Error('image unavailable')); return; } var image = new Image(); image.crossOrigin = 'anonymous'; image.onload = function () { resolve(image); }; image.onerror = function () { index += 1; next(); }; image.src = sources[index]; } next(); }); } function qrCodeDataUrl(text) { return new Promise(function (resolve) { if (!text || typeof window.tbquire !== 'function') { resolve(''); return; } window.tbquire(['qrcode'], function () { var host = $('
').css({ position: 'fixed', left: '-9999px', top: '-9999px' }).appendTo('body'); try { host.qrcode({ width: 160, height: 160, correctLevel: 0, text: text, background: '#fff', foreground: '#333' }); var canvas = host.find('canvas').get(0); resolve(canvas ? canvas.toDataURL('image/png') : ''); } catch (error) { resolve(''); } finally { host.remove(); } }); }); } function coverRect(boxWidth, boxHeight, sourceWidth, sourceHeight) { var sx = 0, sy = 0, sw = sourceWidth, sh = sourceHeight; if (sourceWidth / sourceHeight > boxWidth / boxHeight) { sw = boxWidth * sourceHeight / boxHeight; sx = (sourceWidth - sw) / 2; } else { sh = boxHeight * sourceWidth / boxWidth; sy = (sourceHeight - sh) / 2; } return { sx: sx, sy: sy, sw: sw, sh: sh }; } function containRect(x, y, boxWidth, boxHeight, sourceWidth, sourceHeight) { var ratio = Math.min(boxWidth / sourceWidth, boxHeight / sourceHeight); var width = sourceWidth * ratio; var height = sourceHeight * ratio; return { x: x + (boxWidth - width) / 2, y: y + (boxHeight - height) / 2, width: width, height: height }; } function drawLines(ctx, text, maxWidth, maxRows, x, y, lineHeight) { var chars = String(text || '').replace(/[\r\n]+/g, ' ').split(''); var rows = [], line = ''; chars.forEach(function (char) { var next = line + char; if (line && ctx.measureText(next).width > maxWidth) { rows.push(line); line = char; } else line = next; }); if (line) rows.push(line); if (rows.length > maxRows) { rows = rows.slice(0, maxRows); while (rows[maxRows - 1] && ctx.measureText(rows[maxRows - 1] + '...').width > maxWidth) { rows[maxRows - 1] = rows[maxRows - 1].slice(0, -1); } rows[maxRows - 1] += '...'; } rows.forEach(function (row, index) { ctx.fillText(row, x, y + index * lineHeight); }); } function renderPoster(data) { return Promise.all([ loadImage([data.banner, data.banner_default, data.banner_spare]), data.logo ? loadImage([data.logo]).catch(function () { return null; }) : Promise.resolve(null), qrCodeDataUrl(data.url).then(function (src) { return src ? loadImage([src]).catch(function () { return null; }) : null; }) ]).then(function (assets) { var banner = assets[0], logo = assets[1], qr = assets[2]; var canvas = document.createElement('canvas'); canvas.width = WIDTH; canvas.height = HEIGHT; var ctx = canvas.getContext('2d'); var imageHeight = HEIGHT / 2; ctx.fillStyle = '#fff'; ctx.fillRect(0, 0, WIDTH, HEIGHT); var crop = coverRect(WIDTH, imageHeight, banner.width, banner.height); ctx.drawImage(banner, crop.sx, crop.sy, crop.sw, crop.sh, 0, 0, WIDTH, imageHeight); var now = new Date(); ctx.fillStyle = '#fff'; ctx.font = '35px ' + FONT; ctx.fillText('周' + '日一二三四五六'.charAt(now.getDay()), 30, 70); ctx.font = '28px ' + FONT; ctx.fillText((now.getMonth() + 1) + ' / ' + now.getDate(), 30, 115); ctx.strokeStyle = '#00a1ff'; ctx.lineWidth = 7; ctx.lineCap = 'round'; ctx.beginPath(); ctx.moveTo(40, imageHeight + 38); ctx.lineTo(40, imageHeight + 74); ctx.stroke(); ctx.fillStyle = '#424242'; ctx.font = 'bold 35px ' + FONT; drawLines(ctx, data.title, WIDTH - 120, 2, 58, imageHeight + 68, 52); ctx.fillStyle = '#fc4e1f'; ctx.font = '24px ' + FONT; drawLines(ctx, data.tags, WIDTH - 80, 1, 40, imageHeight + 172, 36); ctx.fillStyle = '#585858'; ctx.font = '25px ' + FONT; drawLines(ctx, data.content, WIDTH - 80, 4, 40, imageHeight + 232, 39); ctx.strokeStyle = 'rgba(122,122,122,.2)'; ctx.lineWidth = 2; ctx.strokeRect(30, HEIGHT - 230, WIDTH - 60, 200); if (logo) { var logoRect = containRect(80, HEIGHT - 190, 300, 100, logo.width, logo.height); ctx.drawImage(logo, logoRect.x, logoRect.y, logoRect.width, logoRect.height); } if (qr) ctx.drawImage(qr, WIDTH - 200, HEIGHT - 200, 120, 120); ctx.fillStyle = '#b4b4b4'; ctx.font = '22px ' + FONT; ctx.textAlign = 'center'; ctx.fillText(data.description || '扫一扫 立即查看', WIDTH / 2, HEIGHT - 52); return canvas.toDataURL('image/png'); }); } function modalId(postId) { return 'modal_poster_' + postId; } function createModal(postId) { var id = modalId(postId); var html = ''; $('body').append(html); return $('#' + id); } function showPoster($modal, postId, src) { var $box = $modal.find('.poster-imgbox').empty().append($('', { src: src, alt: '分享海报', class: 'loaded-img' })).addClass('loaded'); $modal.find('.poster-download').attr({ href: src, download: 'poster_' + postId + '.png' }).removeClass('hide'); $modal.find('.loading-mask').fadeOut(160); $modal.find('.modal-content').css({ height: $box.outerHeight(), transition: '.2s' }); window.setTimeout(function () { $modal.find('.modal-content').css({ height: '', overflow: '', transition: '' }); }, 220); } function requestPoster($trigger, postId, $modal) { $.ajax({ type: 'POST', url: ajaxUrl(), dataType: 'json', data: { action: 'aksrt_poster_share_data', id: postId, nonce: nonce() } }).done(function (response) { if (!response || !response.success || !response.data) { notice((response && response.data && response.data.message) || '海报数据加载失败', 'danger'); $modal.modal('hide'); $modal.remove(); return; } renderPoster(response.data).then(function (src) { showPoster($modal, postId, src); }).catch(function () { notice('海报加载失败,请检查图片跨域设置', 'danger'); $modal.modal('hide'); $modal.remove(); }); }).fail(function (xhr) { var message = xhr.responseJSON && xhr.responseJSON.data && xhr.responseJSON.data.message; notice(message || '海报数据加载失败', 'danger'); $modal.modal('hide'); }).always(function () { $trigger.removeAttr('disabled'); }); } $('body').off('click.aksrtPosterShare', '[poster-share]').on('click.aksrtPosterShare', '[poster-share]', function (event) { event.preventDefault(); var $trigger = $(this); var postId = parseInt($trigger.attr('poster-share'), 10) || 0; if (!postId || $trigger.attr('disabled')) return; var $modal = $('#' + modalId(postId)); if ($modal.length) { $modal.modal('show'); return; } $trigger.attr('disabled', 'disabled'); $('.modal').modal('hide'); $modal = createModal(postId); $modal.modal('show'); requestPoster($trigger, postId, $modal); }); })(window, document, window.jQuery);