2012-04-25 30 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

相关问题