Автор этой статьи: ggvswild
1. Предпосылки
Сохранение веб-страниц в виде изображений (далее именуемых снимками) является эффективным средством для пользователей, позволяющим записывать и обмениваться информацией о странице, и особенно распространено на различных страницах активности в форме проверки интереса и маркетинговой рекламы.
Ссылка на снимок обычно находится в конце процесса взаимодействия со страницей, которая обобщает окончательный результат участия пользователя, что напрямую влияет на полное впечатление пользователя от действия. Поэтому создание высококачественных снимков страниц имеет большое значение для распространения кампании и преобразования бренда.
Эта статья основана на соответствующих практиках предыдущих высококачественных действий облачной музыки (таких как «о твоей картине", "Игра престолов"а также"ваше руководство по эксплуатации'и т. д.), из снимкаЦелостность контента,ясностьа такжеЭффективность преобразованияи многие другие аспекты, обсудите практическое изучение преобразования веб-страниц в высококачественные изображения.
2. Применимая сцена
- Он подходит для преобразования страниц в изображения, особенно для сценариев с высокими требованиями к реальному времени.
- Сценарии, в которых вы хотите отображать междоменные ресурсы изображений в моментальных снимках.
- Сценарии, которые ищут эффективные решения таких проблем, как неполный, размытый или медленный процесс преобразования сгенерированных изображений.
3. Принципиальный анализ
3.1 Выбор схемы
В зависимости от того, был ли образ создан устройствомМестное поколениеСнимки можно разделить на два метода: передняя обработка и задняя обработка.
Поскольку решение, создаваемое бэкендом, зависит от сетевого взаимодействия, неизбежно возникают издержки связи и задержки, а также определенные затраты на обслуживание изменений шаблонов и структур данных.
Следовательно, дляв реальном времениа такжегибкостьУчитывая его всесторонне, мы предпочитаем метод передовой обработки.
3.2 Основные принципы
Процесс обработки моментального снимка на стороне внешнего интерфейса по существу представляет собой процесс преобразования информации о представлении, содержащейся в узле DOM, в информацию об изображении. Этот процесс может быть реализован с помощью собственного API холста, который также является основой осуществимости решения.
В частности, процесс преобразования заключается в отрисовке целевого узла DOM на холст холста, а затем холст холста экспортируется как изображение. Его можно просто обозначить как два этапа фазы рисования и фазы экспорта:
-
этап розыгрыша: выберите узел DOM, который вы хотите нарисовать, в соответствии с
nodeType
Вызовите соответствующий API объекта холста, чтобы нарисовать целевой узел DOM на холсте холста (например, для<img>
Использовать рисунокdrawImageметод). - этап экспорта: через холстtoDataURLилиgetImageDataДождитесь появления внешнего интерфейса и, наконец, реализуйте экспорт содержимого холста.
3.3 Нативный пример
В частности, для одного<img>
Элемент может сделать снимок самого себя следующим образом:
HTML:
<img id="target" src="./music-icon.png" />
JavaScript:
// 获取目标元素
const target = document.getElementById('target');
// 新建canvas画布
const canvas = document.createElement('canvas');
canvas.width = 100;
canvas.height = 100;
const ctx = canvas.getContext("2d");
// 导出阶段:从canvas导出新的图片
const exportNewImage = (canvas) => {
const exportImage = document.createElement('img');
exportImage.src = canvas.toDataURL();
document.body.appendChild(exportImage);
}
// 绘制阶段:待图片内容加载完毕后绘制画布
target.onload = () => {
// 将图片内容绘入画布
ctx.drawImage(target, 0, 0, 100, 100);
// 将画布内容导出为新的图片
exportNewImage(canvas);
}
в,drawImage
является методом экземпляра объекта контекста холста, обеспечивающимРазнообразие способовБудуCanvasImageSourceИсходник рисуется на холсте canvas.exportNewImage
Он используется для экспорта информации о представлении на холсте в виде дисплея, содержащего изображения.data URI.
4. Базовое решение
В предыдущей части мы видели соответствующий базовый API, предоставляемый на основе холста, который обеспечивает возможность обработки моментальных снимков страницы на стороне внешнего интерфейса.
Однако конкретные бизнес-приложения часто бывают более сложными, и приведенные выше примеры «младших версий» явно не охватывают большинство практических сценариев, таких как:
- холст
drawImage
метод принимает толькоCanvasImageSource,а такжеCanvasImageSource
не включает в себятекстовый узел,обычныйdiv
подожди, не будет<img>
Рисование элементов на холсте требует специальной обработки. - Иерархическая обработка приоритетов усложняется, когда нужно отрисовать несколько элементов DOM.
- требует внимания
float
,z-index
,position
и другая обработка позиционирования макета. - Расчет рисунка стилевой композиции более сложен.
Поэтому, основываясь на рассмотрении комплексных бизнес-сценариев, мы принимаем схему с высоким признанием в сообществе:html2canvas
а такжеcanvas2image
В качестве базовой библиотеки для реализации функций моментальных снимков.
4.1 html2canvas
Предоставляет возможность рисовать DOM на холсте
Этот артефакт от сообщества упрощает процесс рисования DOM за DOM на холсте для разработчиков. Проще говоря, егоФундаментальныйдля:
- Рекурсивно пройти целевой узел и его дочерние узлы и собрать информацию о стиле узла;
- Рассчитать иерархическую взаимосвязь самих узлов и рисовать узлы на холсте один за другим в соответствии с определенной приоритетной стратегией;
- Этот процесс повторяется, и, наконец, отрисовывается все содержимое целевого узла.
С точки зрения использования,html2canvas
Исполняемая функция предоставляется извне, и ее первый параметр используется для получения целевого узла для рисования (обязательно); второй параметр является необязательным.элемент конфигурации, который используется для установки различных параметров экспорта холста:
// element 为目标绘制节点,options为可选参数
html2canvas(element[,options]);
Простой пример вызова выглядит следующим образом:
import html2canvas from 'html2canvas';
const options = {};
// 输入body节点,返回包含body视图内容的canvas对象
html2canvas(document.body, options).then(function(canvas) {
document.body.appendChild(canvas);
});
4.2 canvas2image
Предоставляет несколько методов для экспорта информации об изображении с холста.
в сравнении сhtml2canvas
Сложный процесс рисования, осуществляемыйcanvas2imageЧто делать гораздо проще.
canvas2image
Он используется только для преобразования и сохранения входного объекта холста в определенном формате.Оба типа операций поддерживают четыре типа изображений: PNG, JPEG, GIF и BMP:
// 格式转换
Canvas2Image.convertToPNG(canvasObj, width, height);
Canvas2Image.convertToJPEG(canvasObj, width, height);
Canvas2Image.convertToGIF(canvasObj, width, height);
Canvas2Image.convertToBMP(canvasObj, width, height);
// 另存为指定格式图片
Canvas2Image.saveAsPNG(canvasObj, width, height);
Canvas2Image.saveAsJPEG(canvasObj, width, height);
Canvas2Image.saveAsGIF(canvasObj, width, height);
Canvas2Image.saveAsBMP(canvasObj, width, height);
по сути,canvas2image
Он просто обеспечивает вторичную инкапсуляцию для базового API холста (например,getImageData,toDataURL), которая сама по себе не зависитhtml2canvas
.
С точки зрения использования, в связи с текущимавторВерсия ES6 не предоставляетсяcanvas2image
(v1.0.5) модуль нельзя импортировать напрямую путем импорта.
Для проектов, поддерживающих современные сборки (например.webpack), разработчики могут самостоятельно клонировать исходный код и вручную добавить экспорт для получения поддержки ESM:
Поддержка экспорта ESM:
// canvas2Image.js
const Canvas2Image = function () {
...
}();
// 以下为定制添加的内容
export default Canvas2Image;
пример вызова:
import Canvas2Image from './canvas2Image.js';
// 其中,canvas代表传入的canvas对象,width, height分别为导出图片的宽高数值
Canvas2Image.convertToPNG(canvas, width, height)
4.3 Комбинированные методы
Далее мы реализуем базовую версию схемы создания моментальных снимков на основе двух вышеупомянутых библиотек инструментов. Он также разделен на два этапа, соответствующих основным принципам раздела 3.2:
- Первый шаг, через
html2canvas
Реализовать отрисовку узла DOM в объект холста; - Второй шаг — передать объект холста, возвращенный на предыдущем шаге, в
canvas2image
, а затем при необходимости экспортируйте информацию об образе снимка.
В частности, мы инкапсулируемconvertToImage
функция для ввода целевого узла иПараметры элемента конфигурации, вывод информации о снимке изображения.
JavaScript
:
// convertToImage.js
import html2canvas from 'html2canvas';
import Canvas2Image from './canvas2Image.js';
/**
* 基础版快照方案
* @param {HTMLElement} container
* @param {object} options html2canvas相关配置
*/
function convertToImage(container, options = {}) {
return html2canvas(container, options).then(canvas => {
const imageEl = Canvas2Image.convertToPNG(canvas, canvas.width, canvas.height);
return imageEl;
});
}
5. Расширенная оптимизация
В качестве примера в предыдущем разделе мы основаныhtml2canvas
а такжеcanvas2image
, что обеспечивает сравнение с нативным решениемобщностьУлучшенная схема моментальных снимков базовой страницы. Однако при реальных сложных сценариях приложений эффекты моментальных снимков, создаваемые вышеуказанными базовыми решениями, часто неудовлетворительны.
эффект снимкаразница, с одной стороны потому чтоhtml2canvas
Экспортированная информация о представлении является результатом составного расчета вторичного рендеринга с помощью различных API DOM и холста (а не растеризации одним щелчком мыши). Таким образом, различия в реализации связанных API-интерфейсов в разных средах хостинга могут привести к многоконечной несогласованности или ненормальному отображению сгенерированных эффектов изображения.
С другой стороны, факторы бизнес-уровня, например, для разработчиковhtml2canvas
Неправильная конфигурация страницы или неправильная компоновка страницы и т. д. также приведут к отклонениям в результатах создания моментального снимка.
Некоторые обсуждения качества сгенерированных снимков также можно увидеть в сообществе, например:
- Почему некоторые материалы выглядят неполными, искаженными, белыми или черными?
- Исходная страница хорошо узнаваема, почему сгенерированное изображение размыто, как матовое стекло?
- Процесс преобразования страницы в изображение очень медленный, что сказывается на последующих связанных операциях, есть ли хороший способ?
- ...
Ниже мы начинаемЦелостность контента,Оптимизация четкостиа такжеЭффективность преобразованиядля дальнейшего изучения высококачественных решений для моментальных снимков.
5.1 целостность контента
Первая проблема: обеспечить полный экспорт информации о представлении целевого узла
Из-за совместимости реальной машинной среды и различных методов реализации бизнеса в некоторых приложенияхhtml2canvas
Во время процесса содержимое моментального снимка часто не соответствует исходному виду. Общие самопроверки с неполным содержаниемchecklist
следующим образом:
- междоменная проблема: есть междоменное изображение, которое загрязняет холст.
- загрузка ресурсов: при создании моментального снимка соответствующие ресурсы не были загружены.
- проблема с прокруткой: в элементе прокрутки на странице есть смещение, из-за чего результирующий снимок имеет пустую верхнюю часть вверху.
5.1.1 Междоменные проблемы
Обычно используется во введении графического материала, относящегося к проекту развертывания.перекрестный доменместо действия. например, развернутый вhttps://st.music.163.com/
На приведенной выше странице источник представлен какhttps://p1.music.126.net
Этот тип изображения является междоменным ресурсом изображения.
Поскольку холст используется для ресурсов изображенияограничение гомологии, если холст содержит междоменные ресурсы изображений, это загрязнит холст (Tainted canvases), вызывая путаницу в содержимом сгенерированного изображения илиhtml2canvas
Метод не выполняется и другие нештатные проблемы.
Для междоменной обработки ресурсов изображений вы можете начать со следующих аспектов:
(1) конфигурация использования CORS
включиhtml2canvas
изuseCORS
Элементы конфигурации, примеры следующие:
// doc: http://html2canvas.hertzen.com/configuration/
const opts = {
useCORS : true, // 允许使用跨域图片
allowTaint: false // 不允许跨域图片污染画布
};
html2canvas(element, opts);
существуетhtml2canvas
в исходном коде дляuseCORS
Элемент конфигурации настроен наtrue
обработка, по сути, целевого узла в<img>
Внедрение теговcrossOriginдляanonymous
атрибут, позволяющий загружать в соответствии сCORSРесурсы канонических изображений.
в,allowTaint
По умолчаниюfalse
Вы не можете быть явно установлены. Даже если наборtrue
, он не может обойти ограничение canvas для междоменных изображений, потому что при вызове canvastoDataURL
все равно будет заблокирован браузером.
(2) конфигурация CORS
предыдущий шагuseCORS
конфиг, просто разреши<img>
Получайте междоменные ресурсы изображений, а чтобы разблокировать рисование и экспорт междоменных изображений на холсте, сами ресурсы изображения должны обеспечивать поддержку CORS.
Вот введение в использование междоменных изображенийCDNПримечания к ресурсам:
Убедитесь, что ресурс изображения поддерживает междоменный код CORS. С помощью инструментов разработчика Chrome вы можете видеть, что заголовок ответа на запрос изображения должен содержатьAccess-Control-Allow-Origin
поле, которое часто упоминается в анекдотическихмеждоменный заголовок.
Например, первый пример ответа от ресурсов изображений CDN:
// Response Headers
access-control-allow-credentials: true
access-control-allow-headers: DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type
access-control-allow-methods: GET,POST,OPTIONS
access-control-allow-origin: *
Различные поставщики услуг CDN по-разному настраивают междоменные заголовки ресурсов.Подробности можно получить у поставщика услуг CDN.
В особых случаях некоторые поставщики CDN могут иметь кэши изображений, которые не содержат междоменных заголовков CORS. Чтобы обеспечить нормальное отображение снимков, рекомендуется сначала обратиться в службу технической поддержки CDN. исходный сайт и биллинг CDN.
(3) Переадресация сервера
В сторонних приложениях, таких как WeChat, пользовательские аватары платформы и другие ресурсы изображений напрямую не обеспечивают поддержку CORS. В настоящее время необходимо использовать сервер для переадресации прокси, чтобы обойти междоменные ограничения.
То есть адрес аватара пользователя платформы запрашивается сервером и пересылается клиенту (браузеру).Конечно, сам интерфейс сервера должен быть того же происхождения, что и страница или поддерживать CORS.
Для краткости предполагается, что внешний и внутренний интерфейсы заключают следующее соглашение о междоменной пересылке изображений, а интерфейс развертывается под тем же доменным именем, что и внешний проект:
адрес запроса | метод запроса | Входящие параметры | возвращенные сообщения |
---|---|---|---|
/api/redirect/image | GET |
перенаправление с указанием исходного адреса изображения |
Content-Type дляimage/png ресурсы изображений |
на странице<img>
путем сращивания/api/redirect/image
и параметры запроса, представляющие исходный адрес изображенияredirect
, выполните запрос GET для ресурса изображения. Поскольку интерфейс имеет то же происхождение, что и страница, междоменное ограничение не сработает:
<img src="/api/redirect/image?redirect=thirdwx.qlogo.cn/somebody/avatar" alt="user-pic" class="avatar" crossorigin="anonymous">
Для реализации интерфейса сервера здесь используетсяkoaПриведен простой пример:
const Koa = require('koa');
const router = require('koa-router')();
const querystring = require('querystring');
const app = new Koa();
/**
* 图片转发接口
* - 接收 redirect 入参,即需要代为请求的图片URL
* - 返回图片资源
*/
router.get('/api/redirect/image', async function(ctx) {
const querys = ctx.querystring;
if (!querys) return;
const { redirect } = querystring.parse(querys);
const res = await proxyFetchImage(redirect);
ctx.set('Content-Type', 'image/png');
ctx.set('Cache-Control', 'max-age=2592000');
ctx.response.body = res;
})
/**
* 请求并返回图片资源
* @param {String} url 图片地址
*/
async function proxyFetchImage(url) {
const res = await fetch(url);
return res.body;
}
const res = await proxyFetchImage(redirect);
app.use(router.routes());
С точки зрения браузера ресурсы изображения, запрошенные страницей, по-прежнему являются ресурсами под тем же доменным именем, и процесс пересылки прозрачен для внешнего интерфейса. Перед разработкой требований рекомендуется понять источник ресурсов изображения и определить, требуется ли поддержка сервера.
Деятельность в первые дни облачной музыки»Игра престолов», аналогичная схема используется для реализации полной отрисовки и экспорта снимков аватаров пользователей на платформе WeChat.
5.1.2 Загрузка ресурсов
Неполная загрузка ресурсов является распространенной причиной неполных моментальных снимков. При создании снимка, если некоторые ресурсы не загружены, сгенерированный контент, естественно, не будет полным.
Помимо установки определенной задержки, если вы хотите убедиться, что ресурс загружается, вы можете основываться наPromise.allвыполнить.
загрузить изображение:
const preloadImg = (src) => {
return new Promise((resolve, reject) => {
const img = new Image();
img.onload = () => {
resolve();
}
img.src = src;
});
}
Обязательно сделайте снимок после того, как все загрузится:
const preloadList = [
'./pic-1.png',
'./pic-2.png',
'./pic-3.png',
];
Promise.all(preloadList.map(src => preloadImg(src))).then(async () => {
convertToImage(container).then(canvas => {
// ...
})
});
Фактически, описанный выше метод предназначен только для решения проблемы отображения изображений страниц. В реальной сцене, даже если изображение на странице отображается полностью, после сохранения снимка может остаться пустое содержимое. Причина в том, что при внутренней обработке библиотеки html2canvas запрос на загрузку ресурса изображения все равно будет сделан; если в это время загрузка не удалась, часть будет пустой после сохранения снимка.
Далее описывается передача ресурса изображенияBlobРешение для обеспечения того, чтобы адрес образа исходил от локального, чтобы избежать ситуации сбоя загрузки во время преобразования моментального снимка. Упомянутый здесь объект Blob представляет собой неизменяемый файлоподобный объект, представляющий необработанные двоичные данные в определенном формате.сцены, которые будут использоватьсябудет использовано.
Ресурс изображения для Blob:
// 返回图片Blob地址
const toBlobURL = (function () {
const urlMap = {};
// @param {string} url 传入图片资源地址
return function (url) {
// 过滤重复值
if (urlMap[url]) return Promise.resolve(urlMap[url]);
return new Promise((resolve, reject) => {
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
const img = document.createElement('img');
img.src = url;
img.onload = () => {
canvas.width = img.width;
canvas.height = img.height;
ctx.drawImage(img, 0, 0);
// 关键👇
canvas.toBlob((blob) => {
const blobURL = URL.createObjectURL(blob);
resolve(blobURL);
});
};
img.onerror = (e) => {
reject(e);
};
});
};
}());
надtoBlobURL
реализация метода загрузится<img>
ссылка на ресурс становитсяblobURL.
Далее, поconvertToBlobImage
метод, который реализует метод для входящего целевого узла<img>
пакетная обработка какBlob
Формат.
// 批量处理
function convertToBlobImage(targetNode, timeout) {
if (!targetNode) return Promise.resolve();
let nodeList = targetNode;
if (targetNode instanceof Element) {
if (targetNode.tagName.toLowerCase() === 'img') {
nodeList = [targetNode];
} else {
nodeList = targetNode.getElementsByTagName('img');
}
} else if (!(nodeList instanceof Array) && !(nodeList instanceof NodeList)) {
throw new Error('[convertToBlobImage] 必须是Element或NodeList类型');
}
if (nodeList.length === 0) return Promise.resolve();
// 仅考虑<img>
return new Promise((resolve) => {
let resolved = false;
// 超时处理
if (timeout) {
setTimeout(() => {
if (!resolved) resolve();
resolved = true;
}, timeout);
}
let count = 0;
// 逐一替换<img>资源地址
for (let i = 0, len = nodeList.length; i < len; ++i) {
const v = nodeList[i];
let p = Promise.resolve();
if (v.tagName.toLowerCase() === 'img') {
p = toBlobURL(v.src).then((blob) => {
v.src = blob;
});
}
p.finally(() => {
if (++count === nodeList.length && !resolved) resolve();
});
}
});
}
export default convertToBlobImage;
С точки зрения использования,convertToBlobImage
Снимок должен быть сгенерирован при вызовеconvertToImage
метод перед выполнением.
5.1.3 Проблемы с прокруткой
- Типичная характеристика: пустое пространство в верхней части сгенерированного снимка.
- Причина: как правило, это вызвано сохранением длинного изображения (более одного экрана), а полоса прокрутки не находится вверху (частоSPAклассное приложение).
- Решение: звонок
convertToImage
Перед этим запишитеscrollTop
, а затем позвонитеwindow.scroll(0, 0)
Переместите страницу вверх. После создания снимка снова вызовите егоwindow.scroll(0, scrollTop)
Восстановите исходное вертикальное смещение.
Пример:
// 待保存的目标节点(按实际修改👇)
const container = document.body;
// 实际的滚动元素(按实际修改👇)
const scrollElement = document.documentElement;
// 记录滚动元素纵向偏移量
const scrollTop = scrollElement.scrollTop;
// 针对滚动元素是 body 先作置顶
window.scroll(0, 0);
convertToImage(container)
.then(() => {
// ...
}).catch(() => {
// ...
}).finally(() => {
// 恢复偏移量
window.scroll(0, scrollTop);
});
В частности, для существованиячастичная прокруткаВ случае макета вы также можете использовать соответствующий элемент прокрутки вверх, чтобы избежать пустой верхней части контейнера.
5.2 Оптимизация резкости
Четкость — это водораздел качества моментальных снимков
Картинка ниже взята из "Игра престолов"Сравнение двух снимков страницы результатов до и после оптимизации. Вы можете видеть левое изображение до оптимизации, будь то края текста или детали изображения, есть четкий и заметный разрыв по сравнению с четкостью после оптимизации.
Четкость финального снимка зависит от четкости холста, преобразованного из DOM на первом этапе.
Вот 5 проверенных способов оптимизации резкости.
5.2.1 Использование единиц измерения пикселей
чтобы датьhtml2canvas
Четкое целочисленное значение расчета, чтобы избежать растяжения и размытия, вызванного десятичным округлением, рекомендуется использовать его в макете%
,vw
,vh
илиrem
Стиль элемента одного и того же юнита изменен для использования единообразноpx
.
good:
<div style="width: 100px;"></div>
bad:
<div style="width: 30%;"></div>
5.2.2 Приоритет использования тега img для отображения изображений
Во многих случаях размытие экспортируемого изображения вызвано тем, что изображение в исходном представлении отображается в качестве фона в CSS.
Потому что background-size не возвращает конкретное значение ширины и высоты, а представляет собой тип масштабирования изображения через значения перечисления, такие как содержание, покрытие и т. д.;<img>
Окончательное изображение, созданное методом метки и фона, будет размытым.
изменить фон на<img>
Произойдет некоторое улучшение четкости изображения. Для сценариев, в которых необходимо использовать фон, см. решение в Разделе 5.25.
good:
<img class="u-image" src="./music.png" alt="icon">
bad:
<div class="u-image" style="background: url(./music.png);"></div>
5.2.3 Настройка холста с большим увеличением
Для экранов с высоким разрешением холст может достичь определенной степени повышения резкости за счет выравнивания пикселей CSS с физическими пикселями экранов с высоким разрешением (здесьДля обоих типов пикселей есть подробные описания и обсуждения).
В конкретной операции создайтеdevicePixelRatioУвеличьте изображение, а затем используйте css, чтобы уменьшить его на тот же коэффициент, эффективно улучшая четкость изображения, нарисованного на холсте.
В использованииhtml2canvas
, мы можем настроить масштабированный холст для рисования импортированных узлов.
// convertToImage.js
import html2canvas from 'html2canvas';
// 创建用于绘制的基础canvas画布
function createBaseCanvas(scale) {
const canvas = document.createElement("canvas");
canvas.width = width * scale;
canvas.height = height * scale;
canvas.getContext("2d").scale(scale, scale);
return canvas;
}
// 生成快照
function convertToImage(container, options = {}) {
// 设置放大倍数
const scale = window.devicePixelRatio;
// 创建用于绘制的基础canvas画布
const canvas = createBaseCanvas(scale);
// 传入节点原始宽高
const width = container.offsetWidth;
const height = container.offsetHeight;
// html2canvas配置项
const ops = {
scale,
width,
height,
canvas,
useCORS: true,
allowTaint: false,
...options
};
return html2canvas(container, ops).then(canvas => {
const imageEl = Canvas2Image.convertToPNG(canvas, canvas.width, canvas.height);
return imageEl;
});
}
5.2.4 Отключить сглаживание
imageSmoothingEnabledдаCanvas 2D API
Свойство, используемое для установки того, является ли изображение гладким,true
означает сглаживание изображения (по умолчанию),false
Указывает, что сглаживание холста отключено.
По умолчанию сглаживание холста включено, а сглаживание можно отключить, чтобы добиться определенной степени резкости изображения и улучшить четкость краев линий.
Соответственно, мы будемcreateBaseCanvas
Метод обновлен до:
// 创建用于绘制的基础canvas画布
function createBaseCanvas(scale) {
const canvas = document.createElement("canvas");
canvas.width = width * scale;
canvas.height = height * scale;
const context = canvas.getContext("2d");
// 关闭抗锯齿
context.mozImageSmoothingEnabled = false;
context.webkitImageSmoothingEnabled = false;
context.msImageSmoothingEnabled = false;
context.imageSmoothingEnabled = false;
context.scale(scale, scale);
return canvas;
}
5.2.5 Повышение резкости определенных элементов
Вдохновленные масштабированием холста, мы также можем использовать аналогичные операции оптимизации для определенных элементов DOM, то есть установить ширину и высоту элемента, который необходимо оптимизировать, в 2 раза илиdevicePixelRatio
раз, а затем контролируйте размер его отображения, чтобы он оставался неизменным с помощью масштабирования css.
Например, для фонового изображения, которое необходимо использоватьbackground
элемент, резкость снимка можно значительно улучшить за счет:
.box {
background: url(/path/to/image) no-repeat;
width: 100px;
height: 100px;
transform: scale(0.5);
transform-origin: 0 0;
}
в,width
а такжеheight
Для фактической ширины и высоты дисплея в 2 раза больше значения, черезtransform: scale(0.5)
Реализовано масштабирование размера элемента,transform-origin
Установите в соответствии с реальной ситуацией.
5.3 Эффективность преобразования
Эффективность преобразования снимков напрямую связана со временем ожидания пользователей. Мы можем оптимизировать его на фазе входящего целевого узла и на этапе экспорта моментального снимка.
5.3.1 Входящая фаза
Чем точнее информация о представлении входящего узла, тем меньше вычислений требуется для создания моментального снимка.
Следующий способ работает для входящей информации о просмотре, чтобы «похудеть»:
- уменьшатьШкала стакана цен,уменьшать
html2canvas
Количество вычислений для рекурсивного обхода. - Чтобы сжать объем самого материала изображения, используйтеtinypngилиImageOptimи другие инструменты для сжатия материала.
- Если вы используете пользовательский шрифт, используйтеfontminИнструмент обрезает текст по запросу, чтобы избежать ввода нескольких мегабайт недопустимых ресурсов.
- пройти в соответствующем
scale
значение для масштабирования холста холста (раздел 5.2.3). В нормальных условиях для общих сценариев достаточно 2-3 раз, и нет необходимости переходить на чрезмерное увеличение. - Преобразование ресурса изображения в большой двоичный объект, упомянутое в разделе 5.1.2, может локализовать ресурс изображения, избежать обработки вторичной загрузки изображения html2canvas при создании моментального снимка, а сгенерированная ссылка на ресурс имеет преимущества более короткой длины URL-адреса.
5.3.2 Оптимизация экспорта
canvas2image
обеспечивает несколькоAPIИспользуется для экспорта информации об изображении, как описано выше. включать:
- convertToPNG
- convertToJPEG
- convertToGIF
- convertToBMP
Различные форматы экспорта больше влияют на размер файла моментальных снимков.
Обычно для графических материалов без требований к прозрачности можно использоватьjpeg
формат экспорта. В нашей родственной практикеjpeg
в сравнении сpng
Он может даже сохранить более 80% размера файла.
Формат экспорта изображения в реальной сцене можно выбрать в соответствии с потребностями бизнеса.
6. Резюме
Эта статья основана наhtml2canvas
а такжеcanvas2image
, представляет решение для создания высококачественных снимков интерфейсных страниц с точки зрения целостности контента, четкости и эффективности преобразования снимков.
Из-за сложности практического применения вышеуказанные решения могут не охватывать все конкретные сценарии Добро пожаловать на обмен и обсуждение.
7. Справочные ссылки
- На основе html2canvas для сохранения веб-страниц в виде изображений и оптимизации четкости изображения.
- Генерация wap-страницы WeChat и обмен плакатами с опытом прохождения ям
- H5 реализует запись карьера для сохранения изображений
- Реализуйте WeChat H5, чтобы реализовать длительное нажатие на веб-странице для сохранения изображений и идентификации QR-кода.
- MDN: Allowing cross-origin use of images and canvas
Эта статья была опубликована сКоманда внешнего интерфейса NetEase Cloud Music, Любое несанкционированное воспроизведение статьи запрещено. Мы всегда нанимаем, если вы готовы сменить работу и вам нравится облачная музыка, тоПрисоединяйтесь к нам!