Merge branch 'master' into 'master'

add some feature as description said

1.change the default color of gallery frame
2.let user can rotate images
3.add playable feature for show page

See merge request !11
This commit is contained in:
wmcheng 2020-01-14 01:39:15 +08:00
commit 285c62d5ab
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){
var value = $("input[name='all_upload_length']")
if (value.val()==''){
@ -119,15 +130,22 @@ function batch_crop(){
function select_all() {
$('#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) {
$.ajax({
url : "/admin/galleries/translate",
dataType : "json",
type : "post",
async: false,
data:{text:text},
success:function(data){
ele.html(pretext + data.translate)
if (return_flag){
return_value = data.translate
}
else{
ele.html(pretext + data.translate)
}
},
error:function(){
var back = text.split('.')[1].split('_')
@ -135,7 +153,12 @@ function translate(ele,pretext,text){
for (i=0;i<back.length;i++){
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!')
}
})
@ -146,9 +169,17 @@ function translate(ele,pretext,text){
for (i=0;i<back.length;i++){
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!')
}
if (return_flag){
return return_value
}
}
$(function() {
@ -342,7 +373,7 @@ $(function() {
$(".order-edit-notification").slideDown();
images_order = $container.sortable( "toArray", { attribute: "data-image-id" });
$container.data("order-edit","1");
translate(el,'','gallery.save_order')
translate(el,'','gallery.save_order',false)
}else{
var temp = $container.sortable( "toArray", { attribute: "data-image-id" }),
type = $container.attr("id");
@ -357,7 +388,7 @@ $(function() {
$(".order-edit-notification").slideUp();
$container.sortable("disable");
$container.data("order-edit","0");
translate(el,'','gallery.edit_order')
translate(el,'','gallery.edit_order',false)
}
return false;
})
@ -369,7 +400,7 @@ $(function() {
click: function() {
$('#fileupload').slideToggle(300, function() {
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);
$("#edit-order-btn").hide();
$.ajax({
@ -381,7 +412,7 @@ $(function() {
last_image_id = d.last_image_id;
})
} 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()
$('#file-list').checkListLength();
$('.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.descriptionArea = null;
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(){
gt.stage = $("#gallery-theater-stage");
gt.closeBtn = gt.stage.find(".gallery-close");
@ -49,7 +54,12 @@ var GalleryTheater = function(){
}
var addButton = function () {
$('.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-next").length) { $('#theaterNextButton').remove(); }
@ -59,6 +69,18 @@ var GalleryTheater = function(){
$('#theaterNextButton').click(function () {
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();
@ -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(){
@ -310,6 +358,9 @@ var GalleryTheater = function(){
setThumbNavs();
}
setMainPic();
if (!$('.theaterButton').length){
window.onhashchange()
}
}

View File

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

View File

@ -38,62 +38,135 @@ class Admin::GalleriesController < OrbitAdminController
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
begin
images = AlbumImage.all.select{|value| params[:id].include? value.id.to_s}
id = images.first.album_id.to_s
x = params['x']
y = params['y']
w = params['w']
h = params['h']
cords = x.zip(y,w,h)
count = cords.length
images.each_with_index do |image,index|
cord = cords[index]
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])
else
image.album_crops.first.update_attributes(crop_x: cord[0],crop_y: cord[1],crop_w: cord[2],crop_h: cord[3])
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!
images = AlbumImage.all.select{|value| params[:id].include? value.id.to_s}
id = images.first.album_id.to_s
x = params['x']
y = params['y']
w = params['w']
h = params['h']
cords = x.zip(y,w,h)
count = cords.length
images.each_with_index do |image,index|
cord = cords[index]
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])
else
image.album_crops.first.update_attributes(crop_x: cord[0],crop_y: cord[1],crop_w: cord[2],crop_h: cord[3])
end
end
variable.finish = true
variable = AlbumVariable.first
if variable.nil?
variable = AlbumVariable.new
end
variable.finish = false
variable.save!
end
rescue => e
puts e.inspect
end
redirect_url = "/admin/galleries/crop_process"
render :json => {'href' => redirect_url}.to_json
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
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
def call_translate
text = params['text']
@ -180,7 +253,7 @@ class Admin::GalleriesController < OrbitAdminController
def index
Album.each do |album|
if album.album_colors.first.nil?
album.album_colors.create('color' => '#000000')
album.album_colors.create('color' => 'transparent')
end
end
@tags = @module_app.tags
@ -199,7 +272,7 @@ class Admin::GalleriesController < OrbitAdminController
@color_save = AlbumColor.desc('updated_at').first[:color]
end
else
@color_save = '#000000'
@color_save = 'transparent'
end
if request.xhr?
render :partial => "album", :collection => @albums

View File

@ -1,5 +1,7 @@
class Admin::ImagesController < OrbitAdminController
before_filter :setup_vars
def crop_process
end
def batch_crop
images = params['image_ids'].split(',')
@img = []
@ -47,7 +49,11 @@ class Admin::ImagesController < OrbitAdminController
images = params['images']
images.each do |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
end
if params['delete_cover'] == "true"

View File

@ -100,19 +100,39 @@ class GalleryUploader < CarrierWave::Uploader::Base
# rescue ::MiniMagick::Error, ::MiniMagick::Invalid => e
# raise CarrierWave::ProcessingError.new("Failed to manipulate with MiniMagick, maybe it is not an image? Original Error: #{e}")
# 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
img
end
def get_w_and_h
if have_crop?
img = MiniMagick::Image.open(model.file.resized.path)
else
img = MiniMagick::Image.open(model.file.path)
end
[img[:width], img[:height]]
end
def rotate_ang(angle)
if have_crop?
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
private
img
end
end
private
def resizer
size_of_file = size.to_f / (2**20)
if size_of_file > 5

View File

@ -103,7 +103,7 @@ input.minicolors-input{
</div>
<!-- Frame Color Module -->
<% if @album.album_colors.first.nil? %>
<% @album.album_colors.new('color' => '#000000') %>
<% @album.album_colors.new('color' => 'transparent') %>
<% end %>
<%= f.fields_for :album_colors do |album_color_form| %>
<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>
</div>
<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="#" class="btn btn-inverse btn-small deselect hide"><%= t('gallery.deselect') %></a>
<% if can_edit_or_delete?(@album) %>

View File

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

View File

@ -4,7 +4,7 @@
<%= 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"}]) %>
<div id="gallery-theater-stage">
<div class="gallery">
<div class="gallery" style="margin-top: 2.4em;">
<div class="gallery-loader">
<div class="spinner">
<div class="rect1"></div>

View File

@ -6,6 +6,13 @@ en:
show_original_image: Show the original picture
width: Width
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
use_set: Use the previously configured color
add_files: Add files

View File

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

View File

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