Paperclip + Jcrop + Railsでサムネイルを正方形に切り抜き
Paperclipで画像アップロードができるアプリケーションを作る際に、
サムネイルを正方形に切り抜きたい場合があります。
Paperclipは勝手にサムネイルを正方形に切り抜いてくれる機能がついてますが、
写真の中心を切り抜く、というものなので、
ユーザーに任意の範囲を切り抜いてもらうにはちと工夫が必要です。
切り抜き範囲をユーザーに指定してもらうために、
JSライブラリのJcropを使用します。
Railscastにわかりやすいチュートリアルがありました。
#182 Cropping Images
http://railscasts.com/episodes/182-cropping-images?view=comments
が、数年前のものなのでこのままだとRails4ではちゃんと動きません。
ちゃんと動いたコードを載せておきます。
環境
- Rails 4.0.1
- Paperclip 4.1.1
- Jcrop 0.9.12
models/User.rb
class User < ActiveRecord::Base # 保存する画像ファイル用のフィールドを定義 # 保存時にsmall(50x50サイズに切り抜き)、large(500x500以下のサイズに等倍縮小) の画像を自動で作成 # 保存時のプロセッサを指定 has_attached_file :photo, :styles => { small: "50x50#", large: "500x500>" }, processors: [:cropper] # ユーザーの指定した切り抜き座標保持用プロパティ attr_accessor :crop_x, :crop_y, :crop_w, :crop_h # 座標を指定されたら、プロセッサを走らせる after_update :reprocess_photo, :if => :cropping? # 画像のバリデーション。 5メガ以下のファイルのみOK validates_attachment_size :photo, less_than: 5.megabytes validates_attachment_content_type :photo, content_type:['image/jpeg', 'image/jpg', 'image/png', 'image/gif'] def cropping? !crop_x.blank? && !crop_y.blank? && !crop_w.blank? && !crop_h.blank? end private def reprocess_photo couple_photo.assign(couple_photo) couple_photo.save end end
lib/paperclip_processors/cropper.rb
transformation_commandをオーバーライドする。
module Paperclip class Cropper < Thumbnail def transformation_command if crop_command # super returns an array like this: ["-resize", "100x", "-crop", "100x100+0+0", "+repage"] crop_command + super.join(' ').sub(/ -crop \S+/, '').split(' ') else super end end def crop_command target = @attachment.instance if target.cropping? ["-crop", "#{target.crop_w}x#{target.crop_h}+#{target.crop_x}+#{target.crop_y}"] end end end end
class UsersController < ApplicationController def edit_photo @user = current_user end def update_photo @user = current_user if @user.update(photo_params) if params[:user][:photo].present? render action: 'crop' else redirect_to user_root_path end end end def photo_params params[:user].permit(:photo, :crop_x, :crop_y, :crop_h, :crop_w) end end