Как сделать скриншот холста, сохраняющего текущий стиль css? - Angular / javascript - PullRequest
0 голосов
/ 20 января 2020

Я хочу сделать скриншот следующего холста:

<div class="A">
    <canvas width="700" height="500" style="filter: brightness(200%)"></canvas>
<div class="A">

У меня есть следующий метод:

    takeSnapshot() {
    const canvas = document.getElementsByClassName('A')[0].childNodes[0] as HTMLCanvasElement;
    console.log(canvas);
    const dataUrl = canvas.toDataURL('png');
    const link = document.getElementsByClassName('link')[0];
    link.setAttribute('download', 'snapshot-' + this.convertTimeStamp(Date.now()) + '.png');
    link.setAttribute('href', dataUrl.replace('image/png', 'image/octet-stream'));
    link.click();
  }

Но стиль style="filter: brightness(200%)" не влияет на png загруженное изображение. Как я могу это сделать?

1 Ответ

0 голосов
/ 21 января 2020

Фильтр пикселей холста

Фильтр, применяемый стилем холста, не влияет на пиксели, удерживаемые холстом. Этот стиль применяется при компоновке холста с остальной частью страницы.

Чтобы изменить пиксели на холсте, необходимо установить CanvasRenderingContext2D filter свойство, а затем отрендерить то, что вы хотите, фильтр применяется

  • Обратите внимание , что filter является экспериментальным, поэтому проверьте поддержку.
  • Обратите внимание , что некоторые фильтры испортят холст и таким образом, не предоставит вам доступ к пикселям, toDataURL выдаст ошибку и вы не сможете скачать холст.

    Это не относится к стандартным именованным CSS фильтрам, таким как функции blur(), brightness(), contrast(), drop-shadow(), grayscale(), hue-rotate(), invert(), opacity(), saturate() и sepia()

Пример

Применение фильтра яркости перед загрузкой содержимого холста.

takeSnapshot() {
    const canvas = document.getElementsByClassName('A')[0].childNodes[0];    
    const ctx = canvas.getContext("2d");

    // Set important canvas state to defaults
    ctx.globalAlpha = 1;
    ctx.setTransform(1, 0, 0, 1, 0, 0);

    // Set the filter function
    ctx.filter = "brightness(200%)";

    // Make sure all pixels are completely replaced. Important if there are transparent pixels
    ctx.globalCompositeOperation = "copy";

    // Copy canvas to itself applying the filter as it does so.
    ctx.drawImage(canvas, 0, 0);

    // Turn off filter
    ctx.filter = "none";

    // Restore default comp op
    ctx.globalCompositeOperation = "source-over";

    // Download
    const link = document.getElementsByClassName('link')[0];
    link.download = 'snapshot-' + this.convertTimeStamp(Date.now()) + '.png';
    link.href = canvas.toDataURL('png').replace('image/png', 'image/octet-stream');
    link.click();
}

Примечание Для этого требуется CanvasRenderingContext2D. Если содержимое холста было создано с использованием другого API, вы не сможете получить 2d-контекст. Таким образом, вам нужно создать временный холст того же размера и нарисовать старый холст на новом (используя тот же метод, что и в примере выше), а затем загрузить новый холст.

Если canvas.getContext("2d") возвращает ноль

Поскольку я не знаю, как был обработан ваш холст, более надежная версия функции проверяет, можно ли получить 2D-контекст, если нет, то скопируйте (используя фильтр) в новый холст и сохраните его.

takeSnapshot() {
    var dlCanvas, ctx;
    const can = document.getElementsByClassName('A')[0].childNodes[0];  
    ctx = can.getContext("2d"); // ctx may be null (eg the canvas was rendered using webGL

    if (!ctx) { // failed to get 2D API create a second canvas to apply the filter
        dlCanvas = Object.assign(document.createElement("canvas"), {
             width: can.width, height: can.height
        });
        ctx = dlCanvas.getContext("2d");
    } else {
        dlCanvas = can;
    }

    ctx.globalAlpha = 1;
    ctx.setTransform(1, 0, 0, 1, 0, 0);
    ctx.filter = "brightness(200%)";
    ctx.globalCompositeOperation = "copy";
    ctx.drawImage(can, 0, 0);
    ctx.filter = "none";
    ctx.globalCompositeOperation = "source-over";

    const link = document.getElementsByClassName('link')[0];
    link.download = 'snapshot-' + this.convertTimeStamp(Date.now()) + '.png';
    link.href = dlCanvas.toDataURL('png').replace('image/png', 'image/octet-stream');
    link.click();
}
...