首页 > 解决方案 > 无法下载带有过滤器的画布图像

问题描述

我有一个页面,用户可以在其中放置一些过滤器,例如hue-rotate, blur, invert, saturate and sepia. 之后,他们可以通过按保存图片按钮来下载它。问题是图片下载但没有任何过滤器。我使用画布并添加过滤器CanvasRenderingContext2D.filter。当我检查时,console.log()ctx.filter接受了一些过滤器。当按下保存图片按钮时,我尝试使用drawImage()功能重绘文件,它使用过滤器下载,但这是另一个问题,即使过滤器重置,用户放在页面上的当前 img 也会变成过滤器。我的意思是图片似乎用户已经在页面上下载了带有过滤器的图片。有什么建议么?以下代码和页面图片:

window.addEventListener("DOMContentLoaded", () => {
  const filters = document.querySelectorAll(".filters input"),
    btnReset = document.querySelector(".btn.btn-reset"),
    btns = document.querySelectorAll(".btn-container .btn"),
    btnContainer = document.querySelector(".btn-container"),
    btnLoadPicture = document.querySelector(".btn.btn-load #btnInput");
  const canvas = document.querySelector("canvas"),
    ctx = canvas.getContext("2d"),
    saveBtn = document.querySelector(".btn.btn-save");
  const img = new Image();

  // filter change

  function handleUpdate() {
    const suffix = this.dataset.sizing || "";
    document.documentElement.style.setProperty(
      `--${this.name}`,
      this.value + suffix
    );
    this.nextElementSibling.value = this.value;
    filterDownload();
  }
  function filterDownload() {
    let hold = "";
    for (let i = 0; i < filters.length; i++) {
      hold =
        hold +
        filters[i].name +
        "(" +
        filters[i].value +
        filters[i].dataset.sizing +
        ")";
    }
    ctx.filter = hold;
    console.log(ctx);
  }
  
  // load button function

  canvas.dataMaxWidth = canvas.width;
  canvas.dataMaxHeight = canvas.height;
  btnLoadPicture.addEventListener(
    "change",
    (e) => {
      const reader = new FileReader();
      const file = e.target.files[0];

      img.onload = function () {
        let scaled = getScaledDim(
          img,
          ctx.canvas.dataMaxWidth,
          ctx.canvas.dataMaxHeight
        );
        ctx.canvas.width = scaled.width;
        ctx.canvas.height = scaled.height;
        ctx.drawImage(img, 0, 0, ctx.canvas.width, ctx.canvas.height);
      };
      reader.onloadend = function () {
        img.src = reader.result;
      };
      reader.readAsDataURL(file);
      e.target.value = "";
      hideButton();
      highlightButton(2);
    },
    false
  );
  function getScaledDim(img, maxWidth, maxHeight) {
    let scaled = {
      ratio: img.width / img.height,
      width: img.width,
      height: img.height,
    };
    if (scaled.width > maxWidth) {
      scaled.width = maxWidth;
      scaled.height = scaled.width / scaled.ratio;
    }
    if (scaled.height > maxHeight) {
      scaled.height = maxHeight;
      scaled.width = scaled.height / scaled.ratio;
    }
    return scaled;
  }

  // canvas

  let i = 0;
  function setImage() {
    img.setAttribute("crossOrigin", "anonymous");
    const index = i % images.length;
    let currentTime = new Date();
    if (currentTime.getHours() == 6 || currentTime.getHours() < 12) {
      const imageSrc = imageBaseMorning + images[index];
      img.src = imageSrc;
      i++;
    } else if (currentTime.getHours() == 12 || currentTime.getHours() < 18) {
      const imageSrc = imageBaseDay + images[index];
      img.src = imageSrc;
      i++;
    } else if (currentTime.getHours() == 18 || currentTime.getHours() < 24) {
      const imageSrc = imageBaseEvening + images[index];
      img.src = imageSrc;
      i++;
    } else if (currentTime.getHours() == 0 || currentTime.getHours() < 6) {
      const imageSrc = imageBaseNight + images[index];
      img.src = imageSrc;
      i++;
    }

    img.onload = () => {
      canvas.width = img.width;
      canvas.height = img.height;
      ctx.drawImage(img, 0, 0);
    };
  }
  setImage();

  // Save picture function
  saveBtn.addEventListener("click", saveButton);

  function saveButton() {
    const link = document.createElement("a");
    link.download = "download.png";
    link.href = canvas.toDataURL();
    link.style.display = "none";
    link.click();
    link.remove();

  }
});

HTML:

<main class="main">
  <div class="filters">
    <label>
      Blur:
      <input
        name="blur"
        data-sizing="px"
        type="range"
        min="0"
        max="10"
        value="0"
        id="blur"
      />
      <output name="result" for="blur">0</output>
    </label>

    <label>
      Invert:
      <input
        name="invert"
        data-sizing="%"
        type="range"
        min="0"
        max="100"
        value="0"
        id="invert"
      />
      <output name="result">0</output>
    </label>

    <label>
      Sepia:
      <input
        name="sepia"
        data-sizing="%"
        type="range"
        min="0"
        max="100"
        value="0"
        id="sepia"
      />
      <output name="result">0</output>
    </label>

    <label>
      Saturate:
      <input
        name="saturate"
        data-sizing="%"
        type="range"
        min="0"
        max="200"
        value="100"
        id="saturate"
      />
      <output name="result">100</output>
    </label>

    <label>
      Hue rotate:
      <input
        name="hue-rotate"
        data-sizing="deg"
        type="range"
        min="0"
        max="360"
        value="0"
        id="hue"
      />
      <output name="result">0</output>
    </label>
  </div>
  <div class="editor">
    <div class="btn-container">
      <button class="btn btn-reset">Reset</button>
      <button class="btn btn-next btn-active">Next picture</button>
      <label class="btn btn-load" for="btnInput">
        Load picture
        <input
          class="btn-load--input"
          id="btnInput"
          name="upload"
          type="file"
          placeholder="Load picture"
        />
      </label>
      <button class="btn btn-save">Save picture</button>
    </div>
    <canvas width="1600" height="900"></canvas>
  </div>
</main>

在此处输入图像描述

标签: javascripthtmlcanvashtml5-canvas

解决方案


推荐阅读