2012-04-25 27 views
6

所以我有一個表單,並以這種形式用戶可以上傳圖片。作爲替代,我希望他們能夠拍照並上傳。 攝像頭圖片直接到文件附件


現在我認爲,當用戶使用某種flash網絡攝像頭接口拍攝照片時,該圖片需要在用戶完成其表單時存儲在某種中間存儲器中。

有沒有辦法解決這個問題?什麼是最好的解決方案?

我覺得只有兩種選擇。

要麼是(a)我持有臨時照片,然後在表單提交後再次接受;或者(b)用戶拍攝照片,將其下載到本地機器上,並且必須選擇它作爲文件再次提交。

這兩種解決方案對我來說都不是很滿意,所以我想知道是否有更好的方法來做到這一點。

編輯:作爲一個額外的好處,雖然它並不真正相關,我正在用一個用於文件附件的Paperclip的Rails應用程序。另外,我更喜歡用jQuery工作...

也由經驗豐富的UI web開發者只是一般的看法是不錯..

+0

您可以使用HTML的'canvas'來保存圖片數據從攝像頭採集到一個'div',然後在用戶提交表單時保存。我在接近8到9個月前做過這個。你想要實現代碼?或尋找最佳實踐類型的答案? – Surya 2012-05-03 10:37:21

+0

Facebook/Google已經實施得很好。大概,檢查出來。 – Surya 2012-05-03 10:38:58

+0

@Surya是的,請執行代碼將非常有幫助。 – varatis 2012-05-03 17:55:21

回答

5

我會用這樣的:http://www.xarg.org/project/jquery-webcam-plugin/在我的Rails應用程序,用於捕獲圖像從網絡攝像頭。你可以在這裏下載該jQuery的攝像頭:https://github.com/infusion/jQuery-webcam

這裏是一個大致完成實施,比較遺憾的是亂碼:

class PicturesController < ApplicationController 
    require 'base64' 
    def capture 
     # do something 
     render :layout => "webcam" 
    end 

    def save_image 
     image = params[:capture][:image] 
     File.open("#{Rails.root}/public/path_you_want_to_image/image_name.png", 'wb') do |f| 
     f.write(Base64.decode64(image)) 
     end 
     # Or use paperclip to save image for a model instead!! 
    end 
end 

的意見/佈局/ webcam.html.erb

<!DOCTYPE html> 
<html> 
<head> 
    <title>Application Name</title> 
    <%= stylesheet_link_tag :all %> 
    <%= javascript_include_tag :defaults %> 
    <%= javascript_include_tag "http://www.google-analytics.com/ga.js"%> 
    <%= javascript_include_tag "http://code.jquery.com/jquery-1.4.2.min.js"%> 
    <%= javascript_include_tag "jquery.webcam"%> 
    <script> 
     !window.jQuery && document.write('<script src="jquery-1.4.3.min.js"><\/script>'); 
    </script> 
    <%= csrf_meta_tag %> 
</head> 
<body> 
    <%= yield %> 
</body> 
</html> 

的意見/圖片/ capture.html.erb

<div id="webcam"> 
    <p>Capture image here!</p> 
    </div> 

    <%= form_for(save_image_pictures_path, :method => "post", :remote => true) do |f|%> 
    <%= hidden_field(:item, :sku)%> 
    <div id="capture_images"><input id="capture_image" type="hidden" value="" name="capture[image]"></div> 
    <%= submit_tag "Capture Image", :onClick=>"javascript:capture_image();"%> 
    <% end %>  
    <%= link_to "Back", root_path %> 
    <p> 
    <canvas id="canvas" width="320" height="240"></canvas> 
    </p> 

<script type="text/javascript"> 

var pos = 0; 
var ctx = null; 
var cam = null; 
var image = null; 

var filter_on = false; 
var filter_id = 0; 

function changeFilter() { 
    if (filter_on) { 
     filter_id = (filter_id + 1) & 7; 
    } 
} 

function capture_image(){ 
    webcam.capture(); 
    changeFilter(); 
    void(0); 
    var canvas = document.getElementById('canvas') 
    var context = canvas.getContext("2d"); 
    var img  = canvas.toDataURL("image/png"); 
    var item_image = img.replace(/^data:image\/(png|jpg);base64,/, "") ; 
    document.getElementById('capture_images').innerHTML="<input id=\"capture_image\" type=\"hidden\" value=\""+item_image+"\" name=\"capture[image]\">"; 
} 

function toggleFilter(obj) { 
    if (filter_on =!filter_on) { 
     obj.parentNode.style.borderColor = "#c00"; 
    } else { 
     obj.parentNode.style.borderColor = "#333"; 
    } 
} 

    jQuery("#webcam").webcam({ 

    width: 320, 
    height: 240, 
    mode: "callback", 
    swffile: "/javascripts/jscam_canvas_only.swf", 

    onTick: function(remain) { 

     if (0 == remain) { 
      jQuery("#status").text("Cheese!"); 
     } else { 
      jQuery("#status").text(remain + " seconds remaining..."); 
     } 
    }, 

    onSave: function(data) { 

     var col = data.split(";"); 
     var img = image; 

     if (false == filter_on) { 

      for(var i = 0; i < 320; i++) { 
       var tmp = parseInt(col[i]); 
       img.data[pos + 0] = (tmp >> 16) & 0xff; 
       img.data[pos + 1] = (tmp >> 8) & 0xff; 
       img.data[pos + 2] = tmp & 0xff; 
       img.data[pos + 3] = 0xff; 
       pos+= 4; 
      } 

     } else { 

      var id = filter_id; 
      var r,g,b; 
      var r1 = Math.floor(Math.random() * 255); 
      var r2 = Math.floor(Math.random() * 255); 
      var r3 = Math.floor(Math.random() * 255); 

      for(var i = 0; i < 320; i++) { 
       var tmp = parseInt(col[i]); 

       /* Copied some xcolor methods here to be faster than calling all methods inside of xcolor and to not serve complete library with every req */ 

       if (id == 0) { 
        r = (tmp >> 16) & 0xff; 
        g = 0xff; 
        b = 0xff; 
       } else if (id == 1) { 
        r = 0xff; 
        g = (tmp >> 8) & 0xff; 
        b = 0xff; 
       } else if (id == 2) { 
        r = 0xff; 
        g = 0xff; 
        b = tmp & 0xff; 
       } else if (id == 3) { 
        r = 0xff^((tmp >> 16) & 0xff); 
        g = 0xff^((tmp >> 8) & 0xff); 
        b = 0xff^(tmp & 0xff); 
       } else if (id == 4) { 

        r = (tmp >> 16) & 0xff; 
        g = (tmp >> 8) & 0xff; 
        b = tmp & 0xff; 
        var v = Math.min(Math.floor(.35 + 13 * (r + g + b)/60), 255); 
        r = v; 
        g = v; 
        b = v; 
       } else if (id == 5) { 
        r = (tmp >> 16) & 0xff; 
        g = (tmp >> 8) & 0xff; 
        b = tmp & 0xff; 
        if ((r+= 32) < 0) r = 0; 
        if ((g+= 32) < 0) g = 0; 
        if ((b+= 32) < 0) b = 0; 
       } else if (id == 6) { 
        r = (tmp >> 16) & 0xff; 
        g = (tmp >> 8) & 0xff; 
        b = tmp & 0xff; 
        if ((r-= 32) < 0) r = 0; 
        if ((g-= 32) < 0) g = 0; 
        if ((b-= 32) < 0) b = 0; 
       } else if (id == 7) { 
        r = (tmp >> 16) & 0xff; 
        g = (tmp >> 8) & 0xff; 
        b = tmp & 0xff; 
        r = Math.floor(r/255 * r1); 
        g = Math.floor(g/255 * r2); 
        b = Math.floor(b/255 * r3); 
       } 

       img.data[pos + 0] = r; 
       img.data[pos + 1] = g; 
       img.data[pos + 2] = b; 
       img.data[pos + 3] = 0xff; 
       pos+= 4; 
      } 
     } 

     if (pos >= 0x4B000) { 
      ctx.putImageData(img, 0, 0); 
      pos = 0; 
     } 

    }, 

    onCapture: function() { 
     webcam.save('/product_capture'); 

     jQuery("#flash").css("display", "block"); 
     jQuery("#flash").fadeOut(100, function() { 
      jQuery("#flash").css("opacity", 1); 
     }); 

    }, 

    debug: function (type, string) { 
     jQuery("#status").html(type + ": " + string); 
    }, 

    onLoad: function() { 

     var cams = webcam.getCameraList(); 
     for(var i in cams) { 
      jQuery("#cams").append("<li>" + cams[i] + "</li>"); 
     } 
    } 
}); 

function getPageSize() { 

    var xScroll, yScroll; 

    if (window.innerHeight && window.scrollMaxY) { 
     xScroll = window.innerWidth + window.scrollMaxX; 
     yScroll = window.innerHeight + window.scrollMaxY; 
    } else if (document.body.scrollHeight > document.body.offsetHeight){ // all but Explorer Mac 
     xScroll = document.body.scrollWidth; 
     yScroll = document.body.scrollHeight; 
    } else { // Explorer Mac...would also work in Explorer 6 Strict, Mozilla and Safari 
     xScroll = document.body.offsetWidth; 
     yScroll = document.body.offsetHeight; 
    } 

    var windowWidth, windowHeight; 

    if (self.innerHeight) { // all except Explorer 
     if(document.documentElement.clientWidth){ 
      windowWidth = document.documentElement.clientWidth; 
     } else { 
      windowWidth = self.innerWidth; 
     } 
     windowHeight = self.innerHeight; 
    } else if (document.documentElement && document.documentElement.clientHeight) { // Explorer 6 Strict Mode 
     windowWidth = document.documentElement.clientWidth; 
     windowHeight = document.documentElement.clientHeight; 
    } else if (document.body) { // other Explorers 
     windowWidth = document.body.clientWidth; 
     windowHeight = document.body.clientHeight; 
    } 

    // for small pages with total height less then height of the viewport 
    if(yScroll < windowHeight){ 
     pageHeight = windowHeight; 
    } else { 
     pageHeight = yScroll; 
    } 

    // for small pages with total width less then width of the viewport 
    if(xScroll < windowWidth){ 
     pageWidth = xScroll; 
    } else { 
     pageWidth = windowWidth; 
    } 

    return [pageWidth, pageHeight]; 
} 

window.addEventListener("load", function() { 

    jQuery("body").append("<div id=\"flash\"></div>"); 

    var canvas = document.getElementById("canvas"); 

    if (canvas.getContext) { 
     ctx = document.getElementById("canvas").getContext("2d"); 
     ctx.clearRect(0, 0, 320, 240); 

     var img = new Image(); 
     img.src = "/images/rails.png"; 
     img.onload = function() { 
      ctx.drawImage(img, 129, 89); 
     } 
     image = ctx.getImageData(0, 0, 320, 240); 
    } 

    var pageSize = getPageSize(); 
    jQuery("#flash").css({ height: pageSize[1] + "px" }); 

}, false); 

window.addEventListener("resize", function() { 

    var pageSize = getPageSize(); 
    jQuery("#flash").css({ height: pageSize[1] + "px" }); 

}, false); 
</script> 

只要確保「jscam.swf」在jquery.webcam.js中引用的文件正確加載到頁面上。

路線,你可以在你的的routes.rb定義是:

resources :pictures do 
    collection do 
    get 'capture' 
    post 'save_image' 
    end 
end 

從這裏,你可以使用這個:https://github.com/blueimp/jQuery-File-Upload使用一個Ajax表單提交上傳!

如果您有任何問題,請告訴我。

+0

哇!感謝您的非常完整的答案。我會在即將到來的幾周裏看到它,我一定會通知你的,但這正是我所期待的。 – varatis 2012-05-03 20:23:07

+0

幾個問題:在capture.html.erb結尾處,窗口事件監聽器做了什麼?還onCapture調用webcam.save('/ product_capture'); ....但我沒有看到你的路線。 – varatis 2012-05-04 00:16:57

+0

@varatis我粘貼了只需要的代碼,使這個jQuery網絡攝像頭與您的應用程序一起工作。 onCapture事件中的'webcam.save('/ product_capture')'只是將圖像數據從其回調方法發佈到'product_capture'路徑的測試。但是,那種方式對我來說不起作用。通過爲'product_capture'創建一個後**路由**,檢查該回調方法是否適用於您。別擔心,我在這裏發佈的解決方案正在工作,如果它不適合您,請告訴我,我可以提供我的實際代碼。這是一個很大和凌亂,我做了所有這一切,當我是一個新手到rails ..:P – Surya 2012-05-04 05:13:29

0

錯誤。

替換

def save_image 
    image = params[:canvas][:image] 
    File.open("#{Rails.root}/public/path_you_want_to_image/image_name.png", 'wb') do |f| 
    f.write(Base64.decode64(image)) 
    end 
    # Or use paperclip to save image for a model instead!! 
end 

def save_image 
    image = params[:capture][:image] 
    File.open("#{Rails.root}/public/path_you_want_to_image/image_name.png", 'wb') do |f| 
    f.write(Base64.decode64(image)) 
    end 
    # Or use paperclip to save image for a model instead!! 
end 

function capture_image(){ 
webcam.capture(); 
changeFilter(); 
void(0); 
var canvas = document.getElementById('canvas') 
var context = canvas.getContext("2d"); 
var img  = canvas.toDataURL("image/png"); 
var item_image = img.replace(/^data:image\/(png|jpg);base64,/, "") ; 
document.getElementById('capture_images').innerHTML="<input id=\"capture_image\" type=\"hidden\" value=\""+capture_image+"\" name=\"capture[image]\">";} 

function capture_image(){ 
webcam.capture(); 
changeFilter(); 
void(0); 
var canvas = document.getElementById('canvas') 
var context = canvas.getContext("2d"); 
var img  = canvas.toDataURL("image/png"); 
var item_image = img.replace(/^data:image\/(png|jpg);base64,/, "") ; 
document.getElementById('capture_images').innerHTML="<input id='capture_image' type='hidden' value=\'"+item_image+"\' name='capture[image]'>";} 

之後,一切正常。

PS。如果您得到:「capture_image()不是fn」,請將fn名稱更改爲:「capture_images()」不要忘記onClick事件中的更改名稱

+0

更正了代碼,感謝您提高警惕並伸出援助之手。我很感激。 – Surya 2014-10-27 09:05:26

相關問題