the industrial

ブログと言うより自分のためのメモ以外の何モノでもないです。でも読んでくださってありがとうございます。

IT 〜それが見えたら終わり〜

f:id:omiend:20171106095639j:plain

ゲロおもしろかった。

1990年に公開されたスティーブン・キング原作のホラー映画のリメイクになるのだけど、どちらかというとジュブナイル映画要素の方が大きいんだよね。「スタンド・バイ・ミー」のホラー版みたいなイメージ。

本作のペニーワイズは1990年版よりも、映像技術の発達でさらに凶暴になってたw

2019年に公開予定の後編(大人編?)も楽しみ。

Rails5 + Cropper.js + carrierwave で作る画像クロップ処理

作ったもの

よく、SNSで利用するようなアイコンをアップロードする際、好きな箇所で切り取る処理を作成してみたのでメモがてら書いていく。

こんな感じの動き。

f:id:omiend:20171003152633g:plain

開発環境について

前回作成した下記エントリーの開発環境をそのまま利用。

omiend.hatenablog.jp

変更点として、users Model と employees Modelの使い方を、思っていたのと間違えていたっぽいので修正。

  • users : deviseで利用するアカウント情報として利用
  • employees : 社員管理

ソース

コチラ に配置しているので、よかったらツッコミおなしゃす。

docker−compose環境があれば、my_strongest_ror/docker/start.sh を叩くだけで動きます(たぶん)。

準備 - Cropperのダウンロード&配置

Cropper.js から cropper.min.jscropper.min.css をダウンロードして、下記に配置。

$ cd my_strongest_ror/
$ tree
.
├── app
│   ├── assets
│   │   ├── javascripts
│   │   │   ├── cropper.min.js
│   │   └── stylesheets
│   │       └── cropper.min.css

Cropper.js本体を アバター編集画面のみで読み込ませたいので、 my_strongest_ror/config/initializers/assets.rb に、下記を追記。

Rails.application.config.assets.precompile += %w(
  *.js        # JSはすべてAsset Pipeline対象とする
  cropper.css # 画像Crop用
)

画面作成

ちょっと適当だけど、下記の様にアバター変更画面を作成。

<h1>アイコン変更画面</h1>

<form>
  <%= hidden_field_tag "employee_id", @employee.id %>
  <%= file_field_tag 'employee[avatar]' %>
  <%= button_tag :submit, :id => "submitBtn" %>
  <% if @employee.persisted? && @employee.avatar? %>
    <%= link_to "削除", delete_avatar_path, method: :delete %>
  <% end %>
  <%= link_to "キャンセル", employees_path %>
  <% if @employee.persisted? && @employee.avatar? %>
    <div id="crop_area_box">
      <%= image_tag @employee.avatar, :id => "crop_image", :html => [:width => "600px"] %>
    </div>
  <% else %>
    <div id="crop_area_box"><img id="crop_image" /></div>
  <% end %>
  <div id="crop_preview"></div>
</form>

<!-- Cropper.jsは、当該ページ個別に読み込む -->
<%= stylesheet_link_tag    'cropper.min' %>
<%= javascript_include_tag 'cropper.min' %>
<%= javascript_include_tag 'edit_avatar' %>

<style>
  #crop_area_box {
    display: block;
    width: 600px;
    height: 600px;
    overflow: hidden;
  }
</style>

Cropper.jsを利用するアバター変更画面用のJSを作成する。

$(function(){

  var fileName;

  // 画像ファイル選択後のプレビュー処理
  $('form').on('change', 'input[type="file"]', function(event) {
    var file = event.target.files[0];
    fileName = file.name;
    var reader = new FileReader();
    var $crop_area_box = $('#crop_area_box');
    // 画像ファイル以外の場合は何もしない
    if(file.type.indexOf('image') < 0){
      return false;
    }
    // ファイル読み込みが完了した際のイベント登録
    reader.onload = (function(file) {
      return function(event) {
        //既存のプレビューを削除
        $crop_area_box.empty();
        // .prevewの領域の中にロードした画像を表示するimageタグを追加
        $crop_area_box.append($('<img>').attr({
          src: event.target.result,
          id: "crop_image",
          title: file.name
        }));
        // プレビュー処理に対して、クロップ出来る処理を初期化設定
        initCrop();
      };
    })(file);
    reader.readAsDataURL(file);
  });

  var cropper;
  function initCrop() {
    cropper = new Cropper(crop_image, {
      dragMode: 'move', // 画像を動かす設定
      aspectRatio: 1 / 1, // 正方形やで!
      restore: false,
      guides: false,
      center: false,
      highlight: false,
      cropBoxMovable: false,
      cropBoxResizable: false,
      toggleDragModeOnDblclick: false,
      minCropBoxWidth: 300,
      minCropBoxHeight: 300,
      ready: function () {
        croppable = true;
      }
    });
    // 初回表示時
    crop_image.addEventListener('ready', function(e){
      cropping(e);
    });
    // 画像をドラッグした際の処理
    crop_image.addEventListener('cropend', function(e){
      cropping(e);
    });
    // 画像を拡大・縮小した際の処理
    crop_image.addEventListener('zoom', function(e){
      cropping(e);
    });
  }

  // クロップ処理した画像をプレビュー領域に表示
  var croppedCanvas;
  function cropping(e) {
    croppedCanvas = cropper.getCroppedCanvas({
      width: 300,
      height: 300,
    });
    // `$('<img>'{src: croppedCanvas.toDataURL()});` 的に書きたかったけど、jQuery力が足りず・・・
    var croppedImage = document.createElement('img');
    croppedImage.src = croppedCanvas.toDataURL();
    crop_preview.innerHTML = '';
    crop_preview.appendChild(croppedImage);
  }

  // Submit時に実行するPOST処理
  $('#submitBtn').on('click', function(event){
    // クロップ後のファイルをblobに変換し、AjaxでForm送信
    croppedCanvas.toBlob(function (blob) {
      const fileOfBlob = new File([blob], fileName);
      var formData = new FormData();
      // `employee[avatar]` は `employee` modelに定義した `mount_uploader :avatar, AvatarUploader` のコト
      formData.append('employee[avatar]', fileOfBlob);
      // EmployeeのID取得
      const employee_id = $('#employee_id').val();
      $.ajax('/avatar/' + employee_id + '/update', {
        method: "PATCH", // POSTの方が良いのかな?
        data: formData,
        processData: false, // 余計な事はせず、そのままSUBMITする設定?
        contentType: false,
        success: function (res) {
          // DOM操作にしたほうがいいのかな?その場合、アップロード後に実行するなどのポーリング処理的なサムシングが必要になりそう・・・
          // なので、とりあえず簡単に`location.reload`しちゃう
          location.reload();
        },
        error: function (res) {
          console.error('Upload error');
        }
      });
    // S3にアップロードするため画質を50%落とす
    }, 'image/jpeg', 0.5);
  });

});

正直...

まだちょっとバギーだし、jQuery使いまくってるし、もうちょっとなんとかしたい感満載。

ローグ・ワン

ローグ・ワン/スター・ウォーズ・ストーリー (吹替版)

今さらなんだけど、読めちゃんと鑑賞。

デス・スターの設計図を盗み出すというミッションをやってのけた「ローグ・ワン」たちの物語。

STARWARSではエピソード3と4の間に位置する話で、すっごく楽しかった!

潜水服は蝶の夢を見る

潜水服は蝶の夢を見る (字幕版)

脳梗塞で「ロックトイン・シンドローム」となり、左目しか動かせなくなった実在の人物、ELLEの編集長、ジャン・ドミニック・ボービーを題材にした映画。

その後、左目の”まばたきだけで”自伝を書き上げたのは本当にすごい。

主演はマチュー・アマルリック」という俳優さんで、グランド・ブダペスト・ホテルなどに出演。

結構泣ける。