Image filters with canvas

by bc_rikko

HTML

<div id="app"></div>

CSS

body {
  background-color: white;
}

.canvas {
  margin: 10px;
  border: dashed 4px #666666;
}

JavaScript

/**
 * イメージにいろんなフィルタをかける
 */
 class ImageFilter {
  /**
   * @param {Object} param パラメータ
   * @param {string} param.el 画像を表示する要素のセレクタ
   * @param {string} param.imageSrc 画像ファイルのURL
   * @param {number} param.width Canvasの幅
   * @param {number} param.height Canvasの高さ
   */
  constructor(param) {
    this.el = document.querySelector(param.el);
    this.src = param.imageSrc;
    this.canvasWidth = param.width || 200;
    this.canvasHeight = param.height || 200;

    this.filters = {
      'nofilter'    : this._nofilter.bind(this),
      'grayscale'   : this._grayscale.bind(this),
      'inversion'   : this._inversion.bind(this),
      'binarization': this._binarization.bind(this),
      'gamma'       : this._gamma.bind(this),
      'blur'        : this._blur.bind(this),
      'sharpen'     : this._sharpen.bind(this),
      'median'      : this._median.bind(this),
      'emboss'      : this._emboss.bind(this),
      'mosaic'      : this._mosaic.bind(this)
    };
  }

  /**
   * 初期化
   */
  init() {
    // Canvas
    const original = this._createCanvas('original');
    const preview = this._createCanvas('preview');

    // 描画順調整のため遅延
    setTimeout(() => {
      this.el.appendChild(original);
      this.el.appendChild(preview);

      this.draw(original, this._nofilter);
      this.draw(preview, this._nofilter);
    }, 100);

    // Radios
    const radios = document.createElement('div');
    this.el.appendChild(radios);

    Object.keys(this.filters).forEach(type => {
      const radio = this._createRadios(type, preview);
      radios.appendChild(radio);
    });
  }

  /**
   * ラジオボタンを生成する
   * @param {string} filterType this.filtersのフィルタタイプ
   * @param {HTMLCanvasElement} canvas ラジオボタンがクリックされたときにフィルタを適用するCanvas
   * @return {HTMLLabelElement} labelタグでラップしたラジオボタン
   */
  _createRadios(filterType, canvas) {
    const input = document.createElement('input');
    input.type = 'radio';
    input.name = 'filters';
    input.checked = filterType === 'nofilter';
   ...