Заставить HTML Canvas генерировать штриховые рисунки в формате PDF?

У меня есть программа HTML/JavaScript, которая использует холст HTML5 для создания красивого графика:

Я хочу включить этот график в книгу, которую я создаю с помощью LaTeX. К сожалению, когда я печатаю эту страницу в формате PDF, я получаю растровое изображение — вероятно, потому, что холст — это растровое изображение.

Я только что проверил, и, очевидно, если бы я разработал это с помощью SVG вместо холста HTML5, мне было бы хорошо идти. Но я этого не сделал. Итак, есть ли способ создать штриховой рисунок из HTML5 Canvas, или я должен просто стиснуть зубы и повторно реализовать это как SVG?

(Я использовал Canvas вместо svg, потому что думал, что Canvas предпочтительнее, современнее и эффективнее. Я ошибался?)

Обновлено: вот мой JavaScript для рисования каждой стрелки. Я считаю, что могу легко перенести это в SVG, используя svg.js

    /* Draw a Piece at its rotation at the position row,col */
    drawRotatedPiece(p) {
        let x = this.x(p.col);
        let y = this.y(p.row);
        this.ctx.beginPath();
        this.ctx.save();
        this.ctx.translate( x, y);
        this.ctx.fillStyle='white';
        this.ctx.fillRect( -this.radius, -this.radius, this.radius*2, this.radius*2 );
        this.ctx.rotate( p.angle * Math.PI / 180);
        this.ctx.moveTo( 0, -this.radius );
        this.ctx.lineTo( -this.radius, 0 );
        this.ctx.lineTo( +this.radius, 0 );
        this.ctx.closePath( );
        this.ctx.fillStyle='black';
        this.ctx.fill();
        this.ctx.fillRect( -this.radius/2.0, 0, this.radius, this.radius*2/3.0 );
        this.ctx.restore();

    }

Пиксели хороши, когда размер вывода фиксирован. Начните говорить о DPI и размере вывода, как это делается при печати, и вам понадобятся изображения разных размеров для заполнения заданной области. Подумайте о своем выборе LaTeX — вы не пытаетесь сохранить изображения страниц книги, вы пытаетесь сохранить данные, используемые для визуализации изображений текста. Вы должны сделать то же самое с изображениями - сохранить их определение, а не их реализацию. Да, просто перерисовать с помощью SVG.

enhzflep 23.12.2020 00:53

Вам каким-то образом придется воспроизвести вызовы отрисовки API холста HTML5, например, написав класс-оболочку, который обертывает холст HTML5 и преобразует эти вызовы в вызовы, которые записывают команды SVG или PDF. Однако это не совсем просто сделать, в зависимости от того, как вы используете API холста HTML5. Вы должны отредактировать свой вопрос, включив в него код, показывающий, как вы создали графику с помощью API холста HTML5.

Peter O. 23.12.2020 02:30

В любом случае, ваша графика выглядит достаточно просто — всего лишь набор заштрихованных и заполненных контуров — поэтому моя заметка о Основах SVG может помочь вам перевести графику в SVG.

Peter O. 23.12.2020 02:34

Нет, вам не нужен svg.js. Ваш код холста довольно прост. Было бы не слишком сложно вручную портировать его в svg. Просто укуси эту пулю. А если вы не знакомы с svg, то это отличный шанс узнать что-то новое. По сути, вам просто нужно выучить атрибут "d" элемента пути.

hackape 23.12.2020 02:54

Последнее, что я проверял, pdf также не поддерживает svg из коробки. Их векторная графика не была совместима с svg, поэтому вместо преобразования в svg лучше изучите их векторный формат (хотя я считаю, что использовать их графический интерфейс может быть проще).

Kaiido 23.12.2020 02:58

@Kaiido - узнай, чей векторный формат? Я просто попрошу свою веб-силу распечатать в PDF....

vy32 23.12.2020 03:39

@hackape - это для поощрения!

vy32 23.12.2020 03:39

Векторный формат PDF.

Kaiido 23.12.2020 03:46
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
1
8
185
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Ниже приведен код, который генерирует SVG, который воспроизводит повернутую часть, которую вы указали в своем вопросе. Метод drawRotatedPiece(x, y, radius, angle).

// Generate a SVG path command
function xycmd(cmd,x,y){
 return cmd+ x + " " + y;
}

function rectpathxy(x,y,w,h){
   return xycmd("M", x, y) +
          xycmd("L", x+w, y) +
          xycmd("L", x+w, y+h) +
          xycmd("L", x, y+h) +
          "Z";
}

function drawRotatedPiece(x, y, radius, angle){
  trans=[];
  svg = "";
  svg+ = "<path style='stroke:red;fill:white'";
  svg+ = " transform='translate("+x+","+y+")'";
  svg+ = " d='";
  svg+=rectpathxy(-radius, -radius, radius*2, radius*2);
  svg+ = "'/>";
  svg+ = "<path style='stroke:none;fill:black'";
  svg+ = " transform='translate("+x+","+y+") rotate("+angle+")'";
  svg+ = " d='";
  var w=radius;
  var h=radius*2/3.0;
  svg+= xycmd("M", 0, -radius) +
        xycmd("L", -radius, 0) +
        xycmd("L", +radius, 0) +
        "Z" +
        xycmd("M", x,     y) +
        xycmd("L", x+w,   y) +
        xycmd("L", x+w, y+h) +
        xycmd("L", x,   y+h) +
        "Z";
  svg+ = "'/>";
  return svg;
}

Если вам нужно сгенерировать любую другую графику в формате SVG (особенно простую графику, подобную вашей, которая представляет собой просто набор обведенных и заполненных контуров), моя заметка о Essentials of SVG может помочь вам перевести эту графику в SVG.

(знали ли вы, что у svg есть атрибут преобразования?)

Kaiido 23.12.2020 08:41

@Kaiido: Да, но я не был знаком с этим в деталях. Я посмотрю, смогу ли я включить этот атрибут.

Peter O. 23.12.2020 08:59

Вау! Отлично. Но мы хотим использовать transform....

vy32 23.12.2020 16:20

Этот ответ (отредактированная версия) уже генерирует этот атрибут.

Peter O. 23.12.2020 16:36

Так и есть! Я попробую это завтра.

vy32 24.12.2020 05:43

@ПитерО. — Большое спасибо за вашу помощь в этом. Я взял то, что вы написали, очистил его и опубликую, но я приму ваше решение, чтобы вы получили признание. Я считаю, что ваш стиль не ставить ; в конце каждой строки проблематичен, но в остальном ваш код чистый и простой для понимания. Однако я упростил стрелку до одного пути. Я также сделал translate и rotate разные преобразования для разных элементов, чтобы знания о рисовании были отделены от того, где происходит рисование. Вскоре я опубликую полный рабочий пример на GitHub.

vy32 25.12.2020 02:11

Продолжение здесь: stackoverflow.com/questions/65485761/…

vy32 29.12.2020 01:20

Другие вопросы по теме