JavaScript: сделать скриншот страницы или его части

Нужно сделать возможность наподобие той, что имеется у гугла - Send feedback, а конкретно часть со скриншотом страницы. Пробовал использовать html2canvas и dom-to-image, так они не умеют работать с svg (я использую fontawesome в своем приложении). Без svg тоже не везде скриншоты создает, часто вываливает ошибку Uncaught (in promise).

Event {isTrusted: true, type: "error", target: null, currentTarget: null, eventPhase: 0, …}
isTrusted: true
type: "error"
target: null
currentTarget: null
eventPhase: 0
bubbles: false
cancelable: false
defaultPrevented: false
composed: false
timeStamp: 8231.119999999919
srcElement: null
returnValue: true
cancelBubble: false
path: [img]

В перспективе, мне в целом не нужны метки, как у гугла, достаточно просто сделать скриншот страницы + кроп изображения по желанию пользователя. Что можно сделать в моей ситуации?

На всякий случай кусочек кода, где создается скриншот, но вряд ли он о чем-то скажет, я пока изучаю возможности:

$("#bugReportTakeScreenshot").click(function() {
    domtoimage.toPng($(".wrapper")[0]).then(function (dataUrl) {
        let image = new Image();
        image.src = dataUrl;
        $("#bugReportModalBlock").append(image);
    });
});

Ответы (1 шт):

Автор решения: WGPavell

Разобрался в чем была проблема, на странице имелись элементы svg, помимо самого fontawesome (сам пак тоже перевел в обычные шрифты, отказавшись от svg), а именно от bootstrap'а (например, иконка для кастомного select, а также иконки прокрутки carousel). Из плагинов остановился на dom-to-image, поскольку с html2canvas страница превращается в какую-то мясорубку. В том же dom-to-image отфильтровал оставшиеся svg элементы, скрывая их на время генерации скриншота. Для кроппинга изображения использовал cropperjs. А еще dom-to-image не любит теги изображений без сурса. В общем, вот что вышло:

let restrictedNodes = [];
domtoimage.toJpeg($('.wrapper')[0], {
    quality: 0.95,
    bgcolor: $("body").css('background-color'),
    filter: function (node) {
        let $node = $(node);
        if ($node.hasClass('custom-select')) {
            $node.css('background-image', 'none');
            restrictedNodes.push($(node));
        } else if ($node.prop('tagName') == 'IMG' && ($node.attr('src') == undefined || $node.attr('src') == '')) {
            return false;
        } else if ($node.hasClass('carousel-control-prev') || $node.hasClass('carousel-control-next')) {
            return false;
        }
        return true;
    }
}).then(function(dataUrl) {
    ...
    for (let node of restrictedNodes) {
        node.css('background-image', '');
    }
}
→ Ссылка