1.change the default color of gallery frame

2.let user can rotate images
3.add playable feature for show page
This commit is contained in:
chiu 2020-01-10 00:14:41 +08:00
parent b6a473042e
commit 17763f2cdc
13 changed files with 329 additions and 82 deletions

View File

@ -1,3 +1,14 @@
function rotate(){
$("#crop_div").dialog("open");
}
function change_degree(degree_change){
var degree_org = parseInt($('#show_degree').text())
degree_org+=degree_change
if (degree_org==360 || degree_org==-360){
degree_org = 0
}
$('#show_degree').text(degree_org)
}
function init_upload(temp_length){ function init_upload(temp_length){
var value = $("input[name='all_upload_length']") var value = $("input[name='all_upload_length']")
if (value.val()==''){ if (value.val()==''){
@ -119,15 +130,22 @@ function batch_crop(){
function select_all() { function select_all() {
$('#imgholder').find("input[type='checkbox']:not(:checked)").trigger('click') $('#imgholder').find("input[type='checkbox']:not(:checked)").trigger('click')
} }
function translate(ele,pretext,text){ function translate(ele,pretext,text,return_flag){
var return_value
if (navigator.onLine) { if (navigator.onLine) {
$.ajax({ $.ajax({
url : "/admin/galleries/translate", url : "/admin/galleries/translate",
dataType : "json", dataType : "json",
type : "post", type : "post",
async: false,
data:{text:text}, data:{text:text},
success:function(data){ success:function(data){
ele.html(pretext + data.translate) if (return_flag){
return_value = data.translate
}
else{
ele.html(pretext + data.translate)
}
}, },
error:function(){ error:function(){
var back = text.split('.')[1].split('_') var back = text.split('.')[1].split('_')
@ -135,7 +153,12 @@ function translate(ele,pretext,text){
for (i=0;i<back.length;i++){ for (i=0;i<back.length;i++){
result.push(back[i].charAt(0).toUpperCase() + back[i].slice(1)) result.push(back[i].charAt(0).toUpperCase() + back[i].slice(1))
} }
ele.html(pretext + result.join(' ')) if (return_flag){
return_value = result.join(' ')
}
else{
ele.html(pretext + result.join(' '))
}
alert('Your server has some problem, please try again later!') alert('Your server has some problem, please try again later!')
} }
}) })
@ -146,9 +169,17 @@ function translate(ele,pretext,text){
for (i=0;i<back.length;i++){ for (i=0;i<back.length;i++){
result.push(back[i].charAt(0).toUpperCase() + back[i].slice(1)) result.push(back[i].charAt(0).toUpperCase() + back[i].slice(1))
} }
ele.html(pretext + result.join(' ')) if (return_flag){
return_value = result.join(' ')
}
else{
ele.html(pretext + result.join(' '))
}
alert('Please connect the network and try again later!') alert('Please connect the network and try again later!')
} }
if (return_flag){
return return_value
}
} }
$(function() { $(function() {
@ -342,7 +373,7 @@ $(function() {
$(".order-edit-notification").slideDown(); $(".order-edit-notification").slideDown();
images_order = $container.sortable( "toArray", { attribute: "data-image-id" }); images_order = $container.sortable( "toArray", { attribute: "data-image-id" });
$container.data("order-edit","1"); $container.data("order-edit","1");
translate(el,'','gallery.save_order') translate(el,'','gallery.save_order',false)
}else{ }else{
var temp = $container.sortable( "toArray", { attribute: "data-image-id" }), var temp = $container.sortable( "toArray", { attribute: "data-image-id" }),
type = $container.attr("id"); type = $container.attr("id");
@ -357,7 +388,7 @@ $(function() {
$(".order-edit-notification").slideUp(); $(".order-edit-notification").slideUp();
$container.sortable("disable"); $container.sortable("disable");
$container.data("order-edit","0"); $container.data("order-edit","0");
translate(el,'','gallery.edit_order') translate(el,'','gallery.edit_order',false)
} }
return false; return false;
}) })
@ -369,7 +400,7 @@ $(function() {
click: function() { click: function() {
$('#fileupload').slideToggle(300, function() { $('#fileupload').slideToggle(300, function() {
if(!$(this).is(':hidden')) { if(!$(this).is(':hidden')) {
translate($('.add-imgs'),'<i class="icons-cross-2"></i> ','gallery.close_panel') translate($('.add-imgs'),'<i class="icons-cross-2"></i> ','gallery.close_panel',false)
$('.rgbody').stop(true, false).animate({'padding-bottom': 280}, 300); $('.rgbody').stop(true, false).animate({'padding-bottom': 280}, 300);
$("#edit-order-btn").hide(); $("#edit-order-btn").hide();
$.ajax({ $.ajax({
@ -381,7 +412,7 @@ $(function() {
last_image_id = d.last_image_id; last_image_id = d.last_image_id;
}) })
} else { } else {
translate($('.add-imgs'),'<i class="icons-plus"></i> ','gallery.add_image') translate($('.add-imgs'),'<i class="icons-plus"></i> ','gallery.add_image',false)
$('.files').empty() $('.files').empty()
$('#file-list').checkListLength(); $('#file-list').checkListLength();
$('.rgbody').stop(true, false).animate({'padding-bottom': 0}, 300); $('.rgbody').stop(true, false).animate({'padding-bottom': 0}, 300);
@ -416,5 +447,43 @@ $(function() {
}) })
} }
var buttons_option={}
var op_fn1 = function() {
var check_img = $('#imgholder').find("input[type='checkbox']:checked").parents('li').find('img');
check_img.each(function(){
check_img.css('transform','rotate('+$('#show_degree').text()+'deg)');
});
}
var op_fn2 = function() {
var confirm_msg = translate('','','gallery.confirm_msg',true)
if ( confirm (confirm_msg) ){
var check_li = $('#imgholder').find("input[type='checkbox']:checked").parents('li');
var image_ids =[];
check_li.each(function(){
image_ids.push($(this).data('image-id'));
});
if (navigator.onLine) {
window.location.href = '/admin/galleries/rotate_images?image_ids=' + image_ids.join(',') +'&rotate_angle=' + $('#show_degree').text()
} else {
alert('Please connect the network and try again later!')
}
console.log(image_ids)
$(this).dialog("close");
}
}
var op_fn3 = function() { $(this).dialog("close"); }
var op1 = translate('','','gallery.review',true)
var op2 = translate('','','gallery.rotate',true)
var op3 = translate('','','gallery.close_panel',true)
buttons_option[op1] = op_fn1
buttons_option[op2] = op_fn2
buttons_option[op3] = op_fn3
$("#crop_div").dialog({
autoOpen: false,
show: "blind",
hide: "explode",
buttons: buttons_option
});
}); });

View File

@ -25,7 +25,12 @@ var GalleryTheater = function(){
gt.thumbStrip = null; gt.thumbStrip = null;
gt.descriptionArea = null; gt.descriptionArea = null;
gt.isTheaterInitialized = false; gt.isTheaterInitialized = false;
var play_flag = false;
var button_left_string = '<button id ="theaterPreviousButton" class="theaterButton">< </button>',
button_right_string = '<button id ="theaterNextButton" class="theaterButton">> </button>',
button_play_string = '<button id ="theaterPlayButton" class="theaterButton">▶ </button>',
button_stop_string = '<button id ="theaterStopButton" class="theaterButton">|| </button>',
playtimeoutID;
var initialize = function(){ var initialize = function(){
gt.stage = $("#gallery-theater-stage"); gt.stage = $("#gallery-theater-stage");
gt.closeBtn = gt.stage.find(".gallery-close"); gt.closeBtn = gt.stage.find(".gallery-close");
@ -49,7 +54,12 @@ var GalleryTheater = function(){
} }
var addButton = function () { var addButton = function () {
$('.theaterButton').remove(); $('.theaterButton').remove();
$('<button id ="theaterPreviousButton" class="theaterButton">' + '<' + ' </button> <button id ="theaterNextButton" class="theaterButton">' + '>' + ' </button>').insertAfter($('img.gal-active')); if (!play_flag){
$(button_left_string+button_play_string+button_right_string).insertAfter($('img.gal-active'));
}
else{
$(button_left_string+button_stop_string+button_right_string).insertAfter($('img.gal-active'));
}
if (!$(".gal-prev").length) { $('#theaterPreviousButton').remove(); } if (!$(".gal-prev").length) { $('#theaterPreviousButton').remove(); }
if (!$(".gal-next").length) { $('#theaterNextButton').remove(); } if (!$(".gal-next").length) { $('#theaterNextButton').remove(); }
@ -59,6 +69,18 @@ var GalleryTheater = function(){
$('#theaterNextButton').click(function () { $('#theaterNextButton').click(function () {
gt.nextPic(); gt.nextPic();
}); });
$('#theaterPlayButton').click(function () {
play_flag = true;
playtimeoutID = window.setInterval(function(){
gt.playallPic();
},3000)
window.onhashchange()
});
$('#theaterStopButton').click(function () {
play_flag = false;
window.onhashchange()
window.clearInterval(playtimeoutID)
});
} }
addButton(); addButton();
@ -198,7 +220,33 @@ var GalleryTheater = function(){
} }
} }
} }
gt.playallPic = function(){
if(loadingProcess == 0){
mainPicLoading = 1;
nextPicLoading = 1;
prevPicLoading = 1;
if(gt.hasNextImage()){
currentPic.image = gt.albumData.images[currentPic.index + 1];
currentPic.index = currentPic.index + 1;
setMainPic("next");
}
else{
currentPic.image = gt.albumData.images[0];
currentPic.index = 0;
setMainPic();
gt.isTheaterInitialized = false;
setTimeout(function(){
loadingProcess = 0;
nextPicLoading = 0;
$('.theaterButton').remove()
$("img.gallery-image.gal-prev.gal-inactive").remove();
img = $("img.gallery-image.gal-active");
img.eq(0).remove();
window.onhashchange()
},100)
}
}
}
gt.previousPic = function(){ gt.previousPic = function(){
@ -310,6 +358,9 @@ var GalleryTheater = function(){
setThumbNavs(); setThumbNavs();
} }
setMainPic(); setMainPic();
if (!$('.theaterButton').length){
window.onhashchange()
}
} }

View File

@ -465,15 +465,18 @@ body {
} }
/* 相本裡的左右控制鍵 */ /* 相本裡的左右控制鍵 */
#theaterPlayButton,#theaterStopButton{
left:30%;
}
.theaterButton{ .theaterButton{
position: absolute; position: absolute;
text-align: center; text-align: center;
width: 45%; width: 35%;
bottom: 50px; bottom: 1.8em;
background-color: transparent; background-color: transparent;
border: none; border: none;
color: white; color: white;
padding: 15px 32px; padding: 0.4em 1em;
text-align: center; text-align: center;
text-decoration: none; text-decoration: none;
display: inline-block; display: inline-block;

View File

@ -39,61 +39,134 @@ class Admin::GalleriesController < OrbitAdminController
end end
end end
def rotate_images
begin
image_ids = params['image_ids'].split(',')
images = AlbumImage.find(image_ids)
count = images.length
rot_ang = params[:rotate_angle].to_i
images.each_with_index do |image,index|
if !(image.album_crops.first.nil?)
w_and_h = image.file.get_w_and_h
cords = image.album_crops.map{|v| [[v.crop_x.to_f,v.crop_y.to_f],
[v.crop_x.to_f,v.crop_y.to_f+v.crop_h.to_f],
[v.crop_w.to_f+v.crop_x.to_f,v.crop_y.to_f],
[v.crop_w.to_f+v.crop_x.to_f,v.crop_y.to_f+v.crop_h.to_f]]}[0]
rot_diff = rot_ang/90
if (rot_diff) % 2 == 1
new_w = (w_and_h[1]).to_f
new_h = (w_and_h[0]).to_f
else
new_w = (w_and_h[0]).to_f
new_h = (w_and_h[1]).to_f
end
rot_times = rot_diff % 4
deg = (90.0*rot_times/180*Math::PI)
cords = cords.collect do |cord|
x = cord[0]-w_and_h[0].to_f/2
y = cord[1]-w_and_h[1].to_f/2
[x*Math.cos(deg)-y*Math.sin(deg)+new_w/2,x*Math.sin(deg)+y*Math.cos(deg)+new_h/2]
end
all_x = cords.collect do |cord|
cord[0]
end
all_y = cords.collect do |cord|
cord[1]
end
image.album_crops.first.update_attributes(crop_x: all_x.min,crop_y: all_y.min,crop_w: all_x.max - all_x.min,crop_h: all_y.max - all_y.min)
end
end
variable = AlbumVariable.first
if variable.nil?
variable = AlbumVariable.new
end
variable.finish = false
variable.save!
Thread.new do
variable = AlbumVariable.first
images.each_with_index do |image,index|
variable.progress_percent = (index*100.0/count).floor.to_s+'%'
image.file.rotate_ang(rot_ang)
all_version = image.file.versions.map{|k,v| k}
begin
variable.progress_filename = image[:file].to_s
all_version.each do |version|
if !(version.to_s == 'resized' && crop_but_no_backup(image))
image.file.recreate_versions! version
image.save!
end
end
rescue => e
variable.progress_filename = e.inspect.to_s
puts e.inspect
end
variable.save!
end
variable.finish = true
variable.save!
end
rescue => e
puts e.inspect
end
redirect_to :controller=> 'images' ,:action => 'crop_process'
end
def save_crop def save_crop
begin begin
images = AlbumImage.all.select{|value| params[:id].include? value.id.to_s} images = AlbumImage.all.select{|value| params[:id].include? value.id.to_s}
id = images.first.album_id.to_s id = images.first.album_id.to_s
x = params['x'] x = params['x']
y = params['y'] y = params['y']
w = params['w'] w = params['w']
h = params['h'] h = params['h']
cords = x.zip(y,w,h) cords = x.zip(y,w,h)
count = cords.length count = cords.length
images.each_with_index do |image,index| images.each_with_index do |image,index|
cord = cords[index] cord = cords[index]
if image.album_crops.first.nil? if image.album_crops.first.nil?
image.album_crops.create(crop_x: cord[0],crop_y: cord[1],crop_w: cord[2],crop_h: cord[3]) image.album_crops.create(crop_x: cord[0],crop_y: cord[1],crop_w: cord[2],crop_h: cord[3])
else else
image.album_crops.first.update_attributes(crop_x: cord[0],crop_y: cord[1],crop_w: cord[2],crop_h: cord[3]) image.album_crops.first.update_attributes(crop_x: cord[0],crop_y: cord[1],crop_w: cord[2],crop_h: cord[3])
end end
end
variable = AlbumVariable.first
if variable.nil?
variable = AlbumVariable.new
end
variable.finish = false
variable.save!
Thread.new do
variable = AlbumVariable.first
images.each_with_index do |image,index|
variable.progress_percent = (index*100.0/count).floor.to_s+'%'
all_version = image.file.versions.map{|k,v| k}
begin
#org_fname = image.file.path
#org_extname = File.extname(org_fname)
#org_fname.slice! org_extname
#FileUtils.cp(org_fname + org_extname, org_fname + '_resized' + org_extname)
variable.progress_filename = image[:file].to_s
all_version.each do |version|
if !(version.to_s == 'resized' && crop_but_no_backup(image))
image.file.recreate_versions! version
image.save!
end
end
rescue => e
variable.progress_filename = e.inspect.to_s
puts e.inspect
end
variable.save!
end end
variable.finish = true variable = AlbumVariable.first
if variable.nil?
variable = AlbumVariable.new
end
variable.finish = false
variable.save! variable.save!
end Thread.new do
rescue => e variable = AlbumVariable.first
puts e.inspect images.each_with_index do |image,index|
end variable.progress_percent = (index*100.0/count).floor.to_s+'%'
redirect_url = "/admin/galleries/crop_process" all_version = image.file.versions.map{|k,v| k}
render :json => {'href' => redirect_url}.to_json begin
#org_fname = image.file.path
#org_extname = File.extname(org_fname)
#org_fname.slice! org_extname
#FileUtils.cp(org_fname + org_extname, org_fname + '_resized' + org_extname)
variable.progress_filename = image[:file].to_s
all_version.each do |version|
if !(version.to_s == 'resized' && crop_but_no_backup(image))
image.file.recreate_versions! version
image.save!
end
end
rescue => e
variable.progress_filename = e.inspect.to_s
puts e.inspect
end
variable.save!
end
variable.finish = true
variable.save!
end
rescue => e
puts e.inspect
end
redirect_url = "/admin/galleries/crop_process"
render :json => {'href' => redirect_url}.to_json
end end
def call_translate def call_translate
text = params['text'] text = params['text']
@ -180,7 +253,7 @@ class Admin::GalleriesController < OrbitAdminController
def index def index
Album.each do |album| Album.each do |album|
if album.album_colors.first.nil? if album.album_colors.first.nil?
album.album_colors.create('color' => '#000000') album.album_colors.create('color' => 'transparent')
end end
end end
@tags = @module_app.tags @tags = @module_app.tags
@ -199,7 +272,7 @@ class Admin::GalleriesController < OrbitAdminController
@color_save = AlbumColor.desc('updated_at').first[:color] @color_save = AlbumColor.desc('updated_at').first[:color]
end end
else else
@color_save = '#000000' @color_save = 'transparent'
end end
if request.xhr? if request.xhr?
render :partial => "album", :collection => @albums render :partial => "album", :collection => @albums

View File

@ -1,5 +1,7 @@
class Admin::ImagesController < OrbitAdminController class Admin::ImagesController < OrbitAdminController
before_filter :setup_vars before_filter :setup_vars
def crop_process
end
def batch_crop def batch_crop
images = params['image_ids'].split(',') images = params['image_ids'].split(',')
@img = [] @img = []
@ -47,7 +49,11 @@ class Admin::ImagesController < OrbitAdminController
images = params['images'] images = params['images']
images.each do |image| images.each do |image|
img = AlbumImage.find(image) img = AlbumImage.find(image)
FileUtils.rm_rf(File.dirname(img.file.path)) begin
FileUtils.rm_rf(File.dirname(img.file.path))
rescue => e
puts ["can't delete",e]
end
img.delete img.delete
end end
if params['delete_cover'] == "true" if params['delete_cover'] == "true"

View File

@ -100,19 +100,39 @@ class GalleryUploader < CarrierWave::Uploader::Base
# rescue ::MiniMagick::Error, ::MiniMagick::Invalid => e # rescue ::MiniMagick::Error, ::MiniMagick::Invalid => e
# raise CarrierWave::ProcessingError.new("Failed to manipulate with MiniMagick, maybe it is not an image? Original Error: #{e}") # raise CarrierWave::ProcessingError.new("Failed to manipulate with MiniMagick, maybe it is not an image? Original Error: #{e}")
# end # end
def optimize (*arg) def get_w_and_h
manipulate! do |img| if have_crop?
return img unless img.mime_type.match /image\/jpeg/ img = MiniMagick::Image.open(model.file.resized.path)
img.strip else
img.combine_options do |c| img = MiniMagick::Image.open(model.file.path)
c.quality "90" end
c.depth "24" [img[:width], img[:height]]
c.interlace "plane" end
end def rotate_ang(angle)
img if have_crop?
end img_path = model.file.resized.path
else
img_path = model.file.path
end
puts img_path
img = MiniMagick::Image.open(img_path)
img.rotate(angle)
puts img
img.write(img_path)
end
def optimize (*arg)
manipulate! do |img|
return img unless img.mime_type.match /image\/jpeg/
img.strip
img.combine_options do |c|
c.quality "90"
c.depth "24"
c.interlace "plane"
end end
private img
end
end
private
def resizer def resizer
size_of_file = size.to_f / (2**20) size_of_file = size.to_f / (2**20)
if size_of_file > 5 if size_of_file > 5

View File

@ -103,7 +103,7 @@ input.minicolors-input{
</div> </div>
<!-- Frame Color Module --> <!-- Frame Color Module -->
<% if @album.album_colors.first.nil? %> <% if @album.album_colors.first.nil? %>
<% @album.album_colors.new('color' => '#000000') %> <% @album.album_colors.new('color' => 'transparent') %>
<% end %> <% end %>
<%= f.fields_for :album_colors do |album_color_form| %> <%= f.fields_for :album_colors do |album_color_form| %>
<div class="tab-pane fade" id="frame_color"> <div class="tab-pane fade" id="frame_color">

View File

@ -16,6 +16,15 @@
<a href="javascript:select_all()" class='btn btn-small'> <%= t('gallery.checked') %></a> <a href="javascript:select_all()" class='btn btn-small'> <%= t('gallery.checked') %></a>
</div> </div>
<div class="action pull-right"> <div class="action pull-right">
<div id="crop_div" style="text-align: center;">
<%= t('gallery.crop_div').html_safe %>
<br>
<span id="show_degree">0</span>°
<br>
<button onclick="change_degree(90)"><%= t('gallery.add_degree') %></button>
<button onclick="change_degree(-90)"><%= t('gallery.reduce_degree') %></button>
</div>
<a href="javascript:rotate()" class="btn btn-small hide crop"><%= t('gallery.rotate_images') %></a>
<a href="javascript:batch_crop()" class="btn btn-small hide crop"><%= t('gallery.batch_crop') %></a> <a href="javascript:batch_crop()" class="btn btn-small hide crop"><%= t('gallery.batch_crop') %></a>
<a href="#" class="btn btn-inverse btn-small deselect hide"><%= t('gallery.deselect') %></a> <a href="#" class="btn btn-inverse btn-small deselect hide"><%= t('gallery.deselect') %></a>
<% if can_edit_or_delete?(@album) %> <% if can_edit_or_delete?(@album) %>

View File

@ -31,6 +31,7 @@
y[0] = e.detail.y y[0] = e.detail.y
w[0] = e.detail.width w[0] = e.detail.width
h[0] = e.detail.height h[0] = e.detail.height
console.log('x:'+x+'y:'+y)
}, },
viewMode: 2, viewMode: 2,
zoomOnWheel: false, zoomOnWheel: false,

View File

@ -4,7 +4,7 @@
<%= javascript_include_tag "theater" %> <%= javascript_include_tag "theater" %>
<% OrbitHelper.render_meta_tags([{"name" => "mobile-web-app-capable","content" => "yes"},{"name" => "apple-mobile-web-app-status-bar-style","content" => "black-translucent"}]) %> <% OrbitHelper.render_meta_tags([{"name" => "mobile-web-app-capable","content" => "yes"},{"name" => "apple-mobile-web-app-status-bar-style","content" => "black-translucent"}]) %>
<div id="gallery-theater-stage"> <div id="gallery-theater-stage">
<div class="gallery"> <div class="gallery" style="margin-top: 2.4em;">
<div class="gallery-loader"> <div class="gallery-loader">
<div class="spinner"> <div class="spinner">
<div class="rect1"></div> <div class="rect1"></div>

View File

@ -6,6 +6,13 @@ en:
show_original_image: Show the original picture show_original_image: Show the original picture
width: Width width: Width
height: Height height: Height
review: Review
rotate: Rotate
confirm_msg: Are you sure to rotate images
add_degree: Add 90 degree
reduce_degree: Reduce 90 degree
crop_div: "Please input the degree you want to rotate.<br>(positive for clockwise)"
rotate_images: Rotate images
batch_crop: Batch crop images batch_crop: Batch crop images
use_set: Use the previously configured color use_set: Use the previously configured color
add_files: Add files add_files: Add files

View File

@ -6,6 +6,13 @@ zh_tw:
show_original_image: 顯示原始圖片 show_original_image: 顯示原始圖片
width: width:
height: height:
review: 預覽
rotate: 旋轉
confirm_msg: 確定要旋轉圖片嗎?
add_degree: 增加90度
reduce_degree: 減少90度
crop_div: "請輸入需要旋轉的角度.<br>(順時針為正)"
rotate_images: 旋轉圖片
batch_crop: 批量裁減圖片 batch_crop: 批量裁減圖片
use_set: 使用先前已設定的顏色 use_set: 使用先前已設定的顏色
add_files: 新增檔案 add_files: 新增檔案

View File

@ -20,6 +20,7 @@ Rails.application.routes.draw do
post "galleries/order" => "images#changeorder" post "galleries/order" => "images#changeorder"
post "galleries/translate" => "galleries#call_translate" post "galleries/translate" => "galleries#call_translate"
post "galleries/save_crop" => "galleries#save_crop" post "galleries/save_crop" => "galleries#save_crop"
get "galleries/rotate_images" => "galleries#rotate_images"
get "galleries/upload_process" => "galleries#upload_process" get "galleries/upload_process" => "galleries#upload_process"
post "galleries/start_upload_process" => "galleries#start_upload_process" post "galleries/start_upload_process" => "galleries#start_upload_process"
post "galleries/init_upload" => "galleries#init_upload" post "galleries/init_upload" => "galleries#init_upload"