У вас есть один проект nodejs, использующий генератор PDF, и вам нужно вставить в него гистограмму, но проект работает на сервере без настольного компьютера.
Есть ли какая-либо библиотека или метод для создания изображения гистограммы на nodejs во время выполнения без веб-браузера для вставки его в файл PDF?
Я использую puppeteer
для создания PDF-файла, но библиотека Chart.js
не может визуализировать холст, например:
await page.setContent(`<!DOCTYPE html>
<html><body>
<canvas id = "chart"></canvas>
<script>
const ctx = document.getElementById('chart');
new Chart(ctx, {
type: 'bar',
data: {
labels: ['Red', 'Blue', 'Yellow', 'Green', 'Purple', 'Orange'],
datasets: [{
label: '# of Votes',
data: [12, 19, 3, 5, 2, 3],
borderWidth: 1
}]
},
options: {
scales: { y: { beginAtZero: true } }
}
});
</script>
</body></html>`,
{ waitUntil: 'domcontentloaded' });
await page.addScriptTag({ url: 'https://cdn.jsdelivr.net/npm/chart.js' })
Результат — пустая страница. Вот почему я ищу лучший вариант — создать простое изображение и вставить его напрямую.
Я также попробовал:
await page.setContent(`<!DOCTYPE html>
<html><body>
<canvas id = "chart"></canvas>
</body></html>`,
{ waitUntil: [ 'load', 'networkidle0' ] });
await page.addScriptTag({ url: 'https://cdn.jsdelivr.net/npm/chart.js' });
await page.addScriptTag({ content: `
const ctx = document.getElementById('chart');
new Chart(ctx, {
type: 'bar',
data: {
labels: ['Red', 'Blue', 'Yellow', 'Green', 'Purple', 'Orange'],
datasets: [{
label: '# of Votes',
data: [12, 19, 3, 5, 2, 3],
borderWidth: 1
}]
},
options: {
scales: { y: { beginAtZero: true } }
}
});
});
Спасибо, я изменил ожидание на waitUntil: ["load","networkidle0"]
и переместил тег сценария на page.addScriptTag
в конец URL-адреса cdn, но это не работает.
Вы пытались запустить точный код в моем ответе? Дайте мне знать, если это сработает для вас. В ["load", "networkidle0"]
нет смысла, поскольку «загрузка» всегда происходит до «networkidle0».
Я обновляю вопрос с изменениями.
Ваше обновление немного сделало мой ответ недействительным, поэтому мне, вероятно, придется откатить его. Можете ли вы сообщить мне, подойдет ли мой ответ вам или нет? Пожалуйста, дословно запустите точный код и убедитесь, что файл test.png записан. Ваша вторая попытка имеет больше смысла, но я бы просто сделал все это за один setContent
вызов, как показано. Если это не сработает, я рассмотрю возможность устранения неполадок при второй попытке.
Вы добавляете скрипт после запуска кодаchart.js, который от него зависит. Попробуйте сначала добавить скрипт:
const puppeteer = require("puppeteer"); // ^22.6.0
const html = `<!DOCTYPE html>
<html><body>
<script src = "https://cdn.jsdelivr.net/npm/chart.js"></script>
<canvas id = "chart"></canvas>
<script>
const ctx = document.getElementById('chart');
new Chart(ctx, {
type: 'bar',
data: {
labels: ['Red', 'Blue', 'Yellow', 'Green', 'Purple', 'Orange'],
datasets: [{
label: '# of Votes',
data: [12, 19, 3, 5, 2, 3],
borderWidth: 1
}]
},
options: {
scales: { y: { beginAtZero: true } },
animation: { duration: 0 },
}
});
</script>
</body></html>`;
let browser;
(async () => {
browser = await puppeteer.launch();
const [page] = await browser.pages();
await page.setContent(html);
await page.pdf({path: "test.pdf"});
})()
.catch(err => console.error(err))
.finally(() => browser?.close());
Обратите внимание, что я также отключаю анимацию, поэтому на снимке экрана отображается окончательная диаграмма, а не ее текущий рендеринг. Если вы все еще видите недостающие части, вы можете подождать, пока не поступят запросы, или использовать более широкий (менее оптимальный) подход, например setContent(html, {waitUntil: "networkidle0"})
.
Когда кажется, что что-то «не отображается» (или что-то еще) в веб-проектах, обязательно посмотрите в инструментах разработчика, нет ли ошибок JS. Ваш исходный код должен содержать Uncaught ReferenceError: Chart is not defined
, что является довольно четким описанием проблемы.
Вопреки первоначальному заголовку вашего поста, мы используем здесь браузер, он просто работает без головы. Полезно открыть его для временной отладки с помощью puppeteer.launch({headless: false})
.
Смотрите также:
Вам нужно добавить тег сценария, а затем установить содержимое страницы. В противном случае вы пытаетесь запуститьchart.js до его загрузки. См. Puppeteer с Chart.js