6

フォームがあり、このフォームでユーザーは写真をアップロードできます。代わりに、写真を撮ってアップロードできるようにしてほしい。


ここで、ユーザーがある種のフラッシュ Web カメラ インターフェイスで写真を撮る場合、ユーザーがフォームを完成させる間、その写真をある種の中間メモリに保存する必要があると考えています。

これを回避する方法はありますか?最善の解決策は何ですか?

実際には2つのオプションしかないと思います。

(a) 私が一時的な写真を保持し、フォームが送信されたら再度承認するか、(b) ユーザーが写真を撮り、ローカル マシンにダウンロードして、再度送信するファイルとして選択する必要があります。

これらの解決策はどちらも私にとって本当に満足のいくものではないので、これを行うためのより良い方法があるかどうか知りたいと思っていました.

編集:追加のボーナスとして、実際には関係ありませんが、添付ファイル用のペーパークリップを使用してRailsアプリを作成しています。また、私はjQueryで作業することを好みます...

また、経験豊富な UI Web 開発者からの一般的な意見も歓迎します..

4

2 に答える 2

5

私はこれを使用しました: http://www.xarg.org/project/jquery-webcam-plugin/私のレールアプリケーションで、ウェブカメラから画像をキャプチャします。この jQuery Webcam は、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>

ビュー/写真/キャプチャ.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>

jquery.webcam.js で参照されている「 jscam.swf」ファイルがページに正しくロードされていることを確認してください。

routes.rbで定義できるルートは次のとおりです。

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

ここから、https ://github.com/blueimp/jQuery-File-Uploadを使用して、Ajax フォーム送信を使用してアップロードできます!!

ご不明な点がございましたら、お気軽にお問い合わせください。

于 2012-05-03T20:04:39.580 に答える
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 イベントで名前を変更することを忘れないでください。

于 2014-04-07T07:30:50.427 に答える