CẮT ẢNH VỚI CARRIER WAVE TRONG RAILS (CROPPING IMAGES)
Bài đăng này đã không được cập nhật trong 6 năm
Chúng ta thương thấy khi upload một ảnh (thường là avatar có kích thước quá lớn) các trang web thường cung cấp tùy chỉnh ảnh hay còn gọi là copping. Kỹ thuật cropping được áp dụng rất nhiều trong thực tế, vậy trong rails chúng ta làm thế nào? Sau đây là bài hướng dẫn cropping images trong rails thông qua thư viện Jcrop. Trước tiên chúng ta phải thêm gem rmagick và carrierwave vào trong gem file:
gem 'rmagick'
gem 'carrierwave'
Tạo model User với hai trường name và avatar đều để dạng string:
rails g model user name:string avatar:string
rails db:migrate
Tạo file uploader của gem carrierwave bằng câu lệnh sau:
rails generate uploader Avatar
Cài đặt carrierwave uploader cho trường avatar trong User model:
class User < ApplicationRecord
mount_uploader :avatar, AvatarUploader
end
Tạo users_controller:
rails g controller users
Định nghĩa các action trong routes:
Rails.application.routes.draw do
resources :users
root to: 'users#index'
end
Tại file uploaders/avatar_uploader.rb thêm các phiên bản kích cỡ của ảnh mà bạn muốn tùy chỉnh:
class AvatarUploader < CarrierWave::Uploader::Base
include CarrierWave::RMagick
storage :file
# Override the directory where uploaded files will be stored.
# This is a sensible default for uploaders that are meant to be mounted:
def store_dir
"uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
end
version :large do
resize_to_limit(600, 600)
end
version :thumb do
process :crop
resize_to_fill(100, 100)
end
def crop
if model.crop_x.present?
resize_to_limit(600, 600)
manipulate! do |img|
x = model.crop_x.to_i
y = model.crop_y.to_i
w = model.crop_w.to_i
h = model.crop_h.to_i
img.crop!(x, y, w, h)
end
end
end
end
Thêm file crop.html.erb vào trong thư mục app/views/users nhằm mục đích tùy chỉnh images sau khi user tạo avatar:
<h1>Crop Avatar</h1>
<%= image_tag @user.avatar_url(:large), id: "cropbox" %>
<h4>Preview</h4>
<div style="width:100px; height:100px; overflow:hidden">
<%= image_tag @user.avatar.url(:large), :id => "preview" %>
</div>
<%= form_for @user do |f| %>
<% %w[x y w h].each do |attribute| %>
<%= f.hidden_field "crop_#{attribute}" %>
<% end %>
<div class="actions">
<%= f.submit "Crop" %>
</div>
<% end %>
Thêm action: create, update trong users_controller nhằm mục đích xử lý việc cắt ảnh:
def update
@user = User.find(params[:id])
if @user.update_attributes(allowed_params)
if params[:user][:avatar].present?
render :crop
else
redirect_to @user, notice: "Successfully updated user."
end
else
render :new
end
end
def create
@user = User.new(allowed_params)
if @user.save
if params[:user][:avatar].present?
render :crop
else
redirect_to @user, notice: "Successfully created user."
end
else
render :new
end
Để cắt ảnh chúng ta sẽ sử dụng một thư viện của js có tên là Jcop, bạn có thể download jcop tại đây. Copy jquery.Jcrop.css vào thư mục vendor/assets/stylesheets và jquery.Jcrop.js vào thư mục vendor/assets/javascripts. Tại application.js, thêm dòng:
//= require jquery.Jcrop
Tại application.css, thêm dòng:
*= require jquery.Jcrop
Tại file crop.js nhằm tùy chỉnh lại giao diện cắt ảnh:
var AvatarCropper,
bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };
jQuery(function() {
return new AvatarCropper();
});
AvatarCropper = (function() {
function AvatarCropper() {
this.updatePreview = bind(this.updatePreview, this);
this.update = bind(this.update, this);
$('#cropbox').Jcrop({
aspectRatio: 1,
setSelect: [0, 0, 600, 600],
onSelect: this.update,
onChange: this.update
});
}
AvatarCropper.prototype.update = function(coords) {
$('#user_crop_x').val(coords.x);
$('#user_crop_y').val(coords.y);
$('#user_crop_w').val(coords.w);
$('#user_crop_h').val(coords.h);
return this.updatePreview(coords);
};
AvatarCropper.prototype.updatePreview = function(coords) {
return $('#preview').css({
width: Math.round(100 / coords.w * $('#cropbox').width()) + 'px',
height: Math.round(100 / coords.h * $('#cropbox').height()) + 'px',
marginLeft: '-' + Math.round(100 / coords.w * coords.x) + 'px',
marginTop: '-' + Math.round(100 / coords.h * coords.y) + 'px'
});
};
return AvatarCropper;
})();
Và đây là thành quả của chúng ta:
Link tham khảo:
https://rubyplus.com/articles/3951-Cropping-Images-using-jCrop-jQuery-plugin-in-Rails-5
All rights reserved