elninotech/uppload

View on GitHub
src/helpers/filter.ts

Summary

Maintainability
A
1 hr
Test Coverage
import { UpploadEffect } from "../effect";
import {
  safeListen,
  fitImageToContainer,
  canvasToBlob,
} from "../helpers/elements";
import { IHandlersParams, ITemplateParams, IUpploadFile } from "./interfaces";

export default class UpploadFilterBaseClass extends UpploadEffect {
  canvas: HTMLCanvasElement = document.createElement("canvas");
  originalfileURL = "";
  originalFile: IUpploadFile = { blob: new Blob() };
  cssFilter = "";
  max = 10;
  unit = "px";
  value = 0;
  supports = () =>
    !!(
      this.canvas.getContext &&
      this.canvas.getContext("2d") &&
      typeof this.canvas.getContext("2d")?.filter === "string"
    );

  template = ({ file, translate }: ITemplateParams) => {
    const image = URL.createObjectURL(file.blob);
    this.originalfileURL = image;
    this.originalFile = file;
    return `
      <div class="uppload-hue-image">
        <img style="width: 20px" alt="" src="${image}">
      </div>
      <div class="settings">
        <input type="range" value="${this.value}" min="0" max="${this.max}">
        <span class="value"><span>0</span>${
          translate(`units.${this.unit}`) || this.unit
        }</span>
      </div>
    `;
  };

  imageToCanvasBlob(
    params: IHandlersParams,
    filters: string
  ): Promise<Blob | null> {
    params.uppload.emitter.emit("processing");
    return new Promise(resolve => {
      this.canvas = document.createElement("canvas");
      const image = document.createElement("img");
      image.src = this.originalfileURL;
      image.onload = () => {
        this.canvas.width = image.width;
        this.canvas.height = image.height;
        const context = this.canvas.getContext("2d");
        if (!context) return;
        context.clearRect(0, 0, this.canvas.width, this.canvas.height);
        context.filter = filters;
        context.drawImage(image, 0, 0);
        canvasToBlob(this.canvas).then(blob => {
          params.uppload.emitter.emit("process");
          return resolve(blob);
        });
      };
    });
  }

  handlers = (params: IHandlersParams) => {
    const hueElement = params.uppload.container.querySelector(
      ".uppload-hue-image img"
    ) as HTMLImageElement | null;
    if (hueElement) {
      fitImageToContainer(params, hueElement).then(() => {
        const range = params.uppload.container.querySelector(
          ".settings input[type='range']"
        ) as HTMLInputElement;
        if (range) safeListen(range, "change", this.update.bind(this, params));
      });
    }
  };

  update(params: IHandlersParams) {
    let value = 0;
    const range = params.uppload.container.querySelector(
      ".settings input[type='range']"
    ) as HTMLInputElement;
    if (range) value = parseInt(range.value);
    const displayer = params.uppload.container.querySelector(
      ".settings .value span"
    );
    if (displayer) displayer.innerHTML = value.toString();
    const hueElement = params.uppload.container.querySelector(
      ".uppload-hue-image img"
    ) as HTMLImageElement | null;
    if (!hueElement) return;
    this.imageToCanvasBlob(
      params,
      `${this.cssFilter}(${range.value}${this.unit})`
    ).then(blob => {
      if (!blob) return;
      this.originalFile.blob = blob;
      params.next(this.originalFile);
      const image = URL.createObjectURL(blob);
      hueElement.setAttribute("src", image);
    });
  }
}