diff --git a/croppi.rb b/croppi.rb index 392cba6..0a5c558 100644 --- a/croppi.rb +++ b/croppi.rb @@ -3,15 +3,38 @@ require 'sinatra' require 'base64' require 'kconv' +require 'net/http' +require 'uri' # reloader -#require 'sinatra/base' -#require 'sinatra/reloader' if development? +require 'sinatra/base' +require 'sinatra/reloader' if development? + + +before do + p "@@@@@@@@@@@" + if params[:url] then + uri = URI.parse(URI.encode(params[:url])) + Net::HTTP.start(uri.host) {|http| + res = http.request_get(uri.path) + @api_dataURL = "data:" + res['content-type'] + ";base64," + Base64.encode64(res.body) + } + @api_fileName = File.basename(uri.path).tosjis + end +end + + get '/' do erb :index end + + + + + + post '/' do #適当なチェック unless params[:imagedata] && params[:filename] @@ -39,3 +62,9 @@ #send_fileは内部でhaltするので最後に書く。 send_file("tmp/#{filename}", :disposition => "attachment") end + + + + +#@@@@ マッチしないリクエストは'/'にリダイレクト。 + diff --git a/public/croppi.css b/public/croppi.css index c8c6f64..cdfe772 100644 --- a/public/croppi.css +++ b/public/croppi.css @@ -1,4 +1,4 @@ -#c1 { +#canvas { display: none; position: fixed; bottom: 100px; @@ -14,6 +14,7 @@ #zo { position: relative; + padding-right: 8px; /*大きな画像の場合に右端が少しだけ見えるように*/ } #area { @@ -49,12 +50,19 @@ height: 6px; } +::selection { + background: translate; +} +::-moz-selection { + background: translate; +} -#footer_menu { - width: 510px; +#footerMenu { + width: 488px; + height: 35px; display: none; position: fixed; - bottom: 10px; + bottom: 15px; z-index: 300; border-radius: 10px; -webkit-border-radius: 10px; @@ -68,11 +76,9 @@ -o-box-shadow: 5px 5px 5px #000; -box-shadow: 5px 5px 5px #000; background-image: url(images/content_bg.gif); - -moz-user-select: none; - -webkit-user-select: none; } -#footer_menu > div { +#footerMenu > div { float: left; } diff --git a/public/croppi.js b/public/croppi.js index 5290725..0ca8779 100644 --- a/public/croppi.js +++ b/public/croppi.js @@ -1,26 +1,33 @@ $(function(){ -//IE用 +//IE用? if(!window.addEventListener) return; -var api; +var api, +cimg = $('#cimg'), +canvas = $('#canvas'), +area = $('#area'), +footerMenu = $('#footerMenu'); + init(); + function init() { - $('#cimg').css({width:"300px", height:"280px", "background":"url('dropme" + (1+Math.floor(Math.random()*2)) + ".gif')"}); - $("#inputFile").val("").change(function(e){ - handleFile(this.files[0]); - }); + handleEvents(); + apiInterface(); +} - window.addEventListener("dragover", dragover, true); - window.addEventListener("drop", drop, true); - sliderEvent(); +function apiInterface() { + var api_fileName = decodeURIComponent($('#api_fileName').val()); + var api_dataURL = $('#api_dataURL').val(); + if(api_dataURL) + loadImage(api_dataURL, api_fileName); } function drop(e) { var dt = e.dataTransfer; - //dropされたファイルじゃないのは無視 + //dropされたファイル以外は無視 if(!dt.files.length || !isImageFile(dt.files[0])) return e.preventDefault(); @@ -37,11 +44,13 @@ function isImageFile(file) { } function handleFile(dt) { + if(!isImageFile(dt)) + return alert("It's not good to eat it."); + var reader = new FileReader(); reader.readAsDataURL(dt); reader.onload = function() { var dataURI = reader.result; - loadImage(dataURI, dt.name); }; } @@ -55,139 +64,142 @@ function changeTitle(name) { } //ページ読み込み後、一回実行。 -function sliderEvent() { +function handleEvents() { + cimg.css({width:"300px", height:"280px", "background":"url('dropme" + (1+Math.floor(Math.random()*2)) + ".gif')"}); + + window.addEventListener("dragover", dragover, true); + window.addEventListener("drop", drop, true); + + $("#inputFile").val("").change(function(e){ + handleFile(this.files[0]); + }); + $("#slider").slider({value:100, min:1}).bind("slide", function(event, ui) { - var d = $.data($('#cimg')[0], "croppi"); - - //倍率に応じた画像サイズにする。$.width()の四捨五入に合わせてMath.roundを使う。 + var d = $.data(cimg[0], "croppi"); + + //倍率に応じたサイズに。$.width()の四捨五入に合わせてMath.roundを使う。 var cw = Math.round(d.width * ui.value * 0.01); var ch = Math.round(d.height * ui.value * 0.01); - - $('#cimg').width(cw).height(ch); - + + cimg.width(cw).height(ch); $("#scale").text(ui.value+"%"); //倍率を変えた後、垂直方向の中央に - $('#area').css({"top": ((d.height - $('#cimg').height())*0.5) - d.height}) + area.css({"top": ((d.height - cimg.height())*0.5) - d.height}) .width(cw); ///slide時にページの高さが伸び縮みする対策 }) .bind("slidestart", function(event, ui) { api.destroy(); - - //水平方向の中央にする - $('#area').css("left", 0); }) .bind("slidestop", function(event, ui) { api = setCrop('#cimg'); - //水平方向の中央にする - $('#area').css("left", ($('#area').width() - $('#cimg').width()) * 0.5); - if($('#checkBtn').attr('checked')) setCropSize(); }); -} -function loadImage(data, fileName) { - //dataURIを流し込む前に隠す - $(document.body).css({"opacity":0}); + //前回cropして保存されたdataURIと選択領域の消去 + $('#form_imagedata').val(""); + $.data(canvas[0], "croppi", {}); + + $('#inputWidth, #inputHeight').bind('keyup change.spinbox', function(e){ + setTimeout(function(){changeCropSize()},250); + }).spinbox(); - //dataURI流し込み完了load時に実行されるように。 - $('#cimg').attr('src', data).one("load",function(e){ + $('#checkBtn').change(function(){ + if (this.checked) + setCropSize(); + else { + //api.release()しても選択領域の情報は残ってるので + //格納したデータを書き換えて選択のリセットとする + api.release(); + var d = $.data(canvas[0], "croppi"); + $.data(canvas[0], "croppi", {x: d.x, y: d.y, w: 0, h: 0}); + } + }); - $(this).css("background",""); + $('#cropBtn').click(function(){ + var d = $.data(canvas[0], "croppi"); + var nowSelect = api.tellSelect(); - //footerへ移動をやめて非表示 - $("#inputFile").css("display","none"); - $("#footer_menu").css("display","block"); + //選択領域が無い場合は中止 + if (!d.w || (d.w * d.h) == 0 || (nowSelect.w * nowSelect.h) == 0) + return; - //スライダー初期化 - $('#slider').slider("value", 100); - $('#scale').text("100%"); + var ctx = canvas[0].getContext('2d'); + ctx.drawImage(cimg[0], d.x, d.y, d.w, d.h, 0, 0, d.w, d.h); - //width,heightを"auto"にした後、画像の元サイズを格納 - $(this).width("auto").height("auto"); - $.data($(this)[0], "croppi", {width: $(this).width(), height: $(this).height()}); + var dataURI = canvas[0].toDataURL(); + $('#form_imagedata').val(dataURI); + this.form.submit(); + }); - ///slide時にページの高さが伸び縮みする対策の味付け。 - $('#area').height($('#footer_menu').outerHeight()+20); + //操作パネルを中央に + $(window).resize(function(){ + footerMenu.css("left",(window.innerWidth - footerMenu.outerWidth())/2); + }); - //backと位置合わせ。リサイズしたときにtopが効いてくる - $('#area').width($(this).width()).css("top", $(this).height()*-1); + $('#checkBtn').button(); +} - //画像のオリジナルサイズを#backに記録 - $('#back').width($(this).width()).height($(this).height()); +function loadImage(data, fileName) { + $(document.body).css({"opacity":0}); - changeTitle(fileName); - $('#about').hide(); + //dataURI流し込み完了load時に実行されるように。 + cimg.attr('src', data).one("load",function(e){ - if(api) api.destroy(); - api = setCrop('#cimg'); - - if($('#checkBtn').attr('checked')) - setCropSize(); + $(this).css("background",""); - //設定が済んで表示 - $(document.body).animate({opacity:1}); - }); + //footerへ移動をやめて非表示 + $("#inputFile").css("display","none"); + footerMenu.css("display","block"); - //前回cropして保存されたdataURIと選択領域の消去 - $('#form_imagedata').val(""); - $.data($('#c1')[0], "croppi", {}); + //スライダー初期化 + $('#slider').slider("value", 100); + $('#scale').text("100%"); - $('#inputWidth, #inputHeight').bind('keyup change.spinbox', function(e){ - setTimeout(function(){changeCropSize()},250); - }).spinbox(); + //width,heightを"auto"にした後、画像の元サイズを格納 + $(this).width("auto").height("auto"); + $.data($(this)[0], "croppi", {width: $(this).width(), height: $(this).height()}); - $('#checkBtn').change(function(){ - if (this.checked) - setCropSize(); - else { - api.release(); + ///slide時にページの高さが伸び縮みする対策の味付け。 + area.height(footerMenu.outerHeight()+20) + //backと位置合わせ。リサイズしたときにtopが効いてくる + .width($(this).width()) + .css("top", -$(this).height()); - //api.release()しても選択領域の情報は残ってるので - //格納したデータを書き換えて選択のリセットしたことにする - var d = $.data($('#c1')[0], "croppi"); - $.data($('#c1')[0], "croppi", {x: d.x, y: d.y, w: 0, h: 0}); - } - }); + //画像のオリジナルサイズを#backに記録 + $('#back').width($(this).width()).height($(this).height()); - $('#cropBtn').click(function(){ - var d = $.data($('#c1')[0], "croppi"); - var nowSelect = api.tellSelect(); + //widthが決まるこのタイミングでmarginをセット + $('#zo').width($('#back').width()).css("margin","0 auto"); + + //操作パネルを中央に + footerMenu.css("left",(window.innerWidth - footerMenu.outerWidth())/2); - //選択領域がなかったらsubmitしない - if (!d.w || (d.w * d.h) == 0 || (nowSelect.w * nowSelect.h) == 0) - return; + changeTitle(fileName); + $('#about').hide(); - var ctx = $('#c1').get(0).getContext('2d'); - ctx.drawImage($('#cimg').get(0), d.x, d.y, d.w, d.h, 0, 0, d.w, d.h); + if(api) + api.destroy(); - var dataURI = $('#c1').get(0).toDataURL(); - $('#form_imagedata').val(dataURI); - this.form.submit(); - }); + api = setCrop('#cimg'); + if($('#checkBtn').attr('checked')) + setCropSize(); - //操作パネルを中央に - $('#footer_menu').css("left",(($(window).width() - $('#footer_menu').width())/2)-15); - $(window).resize(function(){ - if($(window).width() > $('#footer_menu').width()) - $('#footer_menu').css("left",(($(window).width() - $('#footer_menu').width())/2)-15); - else - $('#footer_menu').css("left", 0); - }); - - $('#checkBtn').button(); + //設定が済んで表示 + $(document.body).animate({opacity:1}); + }); } function saveSelectInfo(c) { - var canvas = $('#c1').attr({width: c.w, height:c.h}); + canvas.attr({width: c.w, height:c.h}); var scale = $('#slider').slider("value"); - var ctx = canvas.get(0).getContext('2d'); + var ctx = canvas[0].getContext('2d'); ctx.scale(scale/100, scale/100); var x = Math.round(c.x*(100/scale)); @@ -195,7 +207,7 @@ function saveSelectInfo(c) { var w = Math.round(c.w*(100/scale)); var h = Math.round(c.h*(100/scale)); - $.data($('#c1')[0], "croppi", {x: x, y: y, w: w, h: h}); + $.data(canvas[0], "croppi", {x: x, y: y, w: w, h: h}); } function setCropSize() { @@ -204,7 +216,6 @@ function setCropSize() { var sW = select.width; var sH = select.height; - var cimg = $('#cimg'); //center position var x = Math.round((cimg.width() * 0.5) - (sW * 0.5)); diff --git a/views/index.erb b/views/index.erb index f7d32b7..16740d1 100644 --- a/views/index.erb +++ b/views/index.erb @@ -85,9 +85,9 @@ - -