jQuery」カテゴリーアーカイブ

CakePHP + jQuery webcam plugin

プロフィールの画像を直接取得できればいいかなぁって思い、このプラグインを使ってみました。

最初は、jQueryだけでwebカメラの操作ができるんだって思っていました。
でも実際は、flashとjQueryを組み合わせて使います。

概要

  • ウェブカメラからの画像を画面にキャプチャする(html5 canvas)
  • ウェブカメラからの画像を取得しサーバー上に保存する

※デスクトップキャプチャソフト等も使えます。

完成イメージ

参考サイト

配布元
Ajalog.7z:jQueryでWebカメラを制御する

環境

  • XAMPP
  • CakePHP1.3.5
  • jQuery1.4.3
  • jQuery webcam plugin

準備

  1. 配布元からファイルをDL&展開
  2. 展開してできたファイルを適当な場所に設置(e.g. app/webroot/js/jquery.webcam.js app/webroot/swf/jscam.swf and jscam_canvas_only.swf)
  3. ウェブカメラを接続 or デスクトップキャプチャ等のソフトをインストール

webcam plugin

swfファイル

次の2つがあります。使いたい状況に応じて設定します。

  1. jscam.swf
  2. jscam_canvas_only.swf

1.はすべての機能が使えます。
2.はcanvasに描画する機能のみです。サーバー側にsaveしたい場合は1.を使います。

function

  • capture(delay):delay秒後にcaptureします
  • save(file): キャプチャ画像を保存 mode:”save”時にfile名を設定するとサーバー側に保存
  • getCameraList():有効なカメラリストの取得
  • setCamera(index):getCameraList()のindexでカメラを切り替える

mode

  • callback
  • save
  • stream

の3種類があります。
callbackは各コールバック関数を呼びます。
saveはcallbackと変わりませんが、save(file)を実行するときにデータを指定したファイルパスへ送信します。
streamは配布元を参照して下さい。

他のパラメータは、配布元を参照してください。

キャプチャした画像をcanvasに描画する処理は上記の参考サイトに書いてあるので、ここではサーバー側の処理を行います。

mode:“save”
onSave():画像の保存完了後に呼び出される。
保存画像を表示させるには、
このコールバックの中でページを書き換え処理を入れるか、
リダイレクトを行えばいいと思います。

jQuery関係のファイルは適当な場所で読み込む。
app/views/webcams/upload

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
<strong>Webカメラから画像を設定</strong>
    <div id="jquery_camera"></div>
    <div id="camerastatus" style="margin-left: 10px;">
        <strong>カメラリスト</strong>
        <ul id="cams"></ul>
        <div id="status"></div>
        <button id="btn">キャプチャ</button>
    </div>
    <?php $this->Html->scriptStart(array('inline' => false)); ?>
        $(function(){
            var width = 320;
            var height = 240;
            $("#jquery_camera").webcam({
                width: width, // webcamの横サイズ
                height: height,// webcamの縦サイズ
                mode: "save",
                //swffile: "/swf/jscam_canvas_only.swf",
                swffile: "/swf/jscam.swf",
                // captrue(delay)が実行されたとき、残り時間を引数にもち、
                // 1秒ごとに呼び出される
                // e.g. delay = 5のときは remainが5,4,...,1と変化して呼び出される。
                onTick: function(remain) {
                    if(0 == remain){
                        $("#status").text("Cheese!");
                    }else{
                        $("#status").text(remain + "seconds remaining...");
                    }
                },
                // mode:saveの場合
                // サーバー側での保存が完了し、サーバーからのレスポンスがくると呼ばれる
                onSave : function () {
                    //キャプチャした画像をwebcam.saveメソッドで保存すると呼び出される。
                    $("#status").text("done!!");
                    var url = "リダイレクト先";
                    window.location = url;
                },
                // Capture時に呼び出される
                onCapture: function() {
                    webcam.save('/users/upload/<?= $this->data['User']['id'] ?>');
                },
                // debug用
                debug: function(type, string) {
                    $("#status").html(type + ": " + string);
                },
                // 読み込み完了時
                onLoad: function() {
                    var cams = webcam.getCameraList();
                    for(var i in cams) {
                        $("#cams").append("<li>" + cams[i] + "</li>");
                    }
                    $("#btn").click(function(){
                        webcam.capture();
                    });
                }
            });
        })
<?php $this->Html->scriptEnd(); ?>

CakePHP

app/controllers/webcams_controller.php

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
・・・
    function upload($id = null){
        $this->laout = '';
        $updir = ini_get('upload_tmp_dir');
        $str = file_get_contents("php://input");
        $filepath = $updir . DS . 'user.jpg';
        file_put_contents($filepath, pack("H*", $str));
        // これ以降にDBへの登録処理をおこなう
        // e.g.下の処理はMediaPluginを使った時の処理の例
        $this->data['Picture']['title'] = '';
        $this->data['Picture']['description'] = '';
        $this->data['Picture']['model'] = 'User';
        $this->data['Picture']['foreign_key'] = $id;
        $this->data['Picture']['file'] = $filepath;
        if($this->Picture->save($this->data)){
            @unlink($filepath);
            exit();
        }else{
            //失敗時の処理
        }
・・・

CakePHP + ZendFramework (Gdata)でYouTubeアプリ作成

ZendFramework (Gdata)を使ってYouTubeのデータを操作

ZendFrameworkのGdataを使用して、YouTubeのデータ処理を行ってみました。

概要

YouTubeのAPIには
動画のデータ操作を行うData API
プレイヤーの操作を行うPlayer APIがあります。
この2つのAPIを利用して以下を行います。

  • YouTubeのApiを使って、ほしいデータを検索(Data API)
  • HP上に動画プレイヤーを設置する(Player API)
  • 検索した動画を設置した動画プレイヤーで再生する

他にも動画のアップロード等ができますが、そちらは、参考資料を参考にしてください。
クライアントライブラリはPHPとjavascriptだけではなく、Javaなどのほかの言語でも提供されています。

完成イメージ

環境

参考資料

Zend Gdataの設定

  • 上記のリンクからGdataの圧縮ファイルをDL&展開しておく
  • 展開したなかのlibraryディレクトリの中のZendディレクトリをvendorsまたはapp/vendorsに設置する。i.e.vendors/Zend or app/vendors/Zend
  • ここからZendFrameworkLoader Componentを作成する。i.e. app/contorollers/components/zend.phpを作成

app/contorollers/components/zend.php

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<?php
class ZendComponent extends Object {
 
    /**
     * Controller Startup Initialisation
     * Add APP/vendor to include path
     
     * @throws Exception
     */
    public function startup() {
        $include = get_include_path();
        // Zendディレクトリをapp/vendorsに設置した場合
//      $include.= PATH_SEPARATOR . APP . 'vendors' . DS;
        // Zendディレクトリをvendorsに設置した場合
        $include.= PATH_SEPARATOR . VENDORS;
        $successful = set_include_path($include);
 
...........
 
}
?>

Controllerの作成

app/controllers/youtube_controller.php

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<?php
class YoutubeController extends AppController{
    public $name = 'Youtube';
    public $uses = '';
    public $layout = 'default';
    public $components = array('Zend');
     
    public function index(){
        // YouTubeクラスのロード
        $this->Zend->loadClass('Zend_Gdata_YouTube');
        $yt = new Zend_Gdata_YouTube();
        // Queryの作成
        $query = $yt->newVideoQuery();
        $query->videoQuery = '世界卓球 -パチンコ -AKB';
        $query->startIndex = 1; // 開始番号
        $query->maxResults = 10; // 検索取得数
        $query->orderBy = 'viewCount'; // 閲覧数順
         
        // Feedの取得
        $videoFeed = $yt->getVideoFeed($query);
//      $videoFeed = $yt->getUserFavorites('username'); // ユーザのお気に入りの動画を取得
        // 取得したFeedをView変数に設定する
        $this->set('videoFeed', $videoFeed);
    }
}
?>

ZendFrameworkは使ったことがなかったので、知らなかったのですが、
クラス名はディレクトリの階層をアンダーバー”_”で区切ってつけられています。
たとえば。。
Zend_Gdata_YouTubeクラスは
Zend/Gdata/YouTube.phpにあります。
この命名規約のため階層が深くなれば、newするときのメソッド名が長くなります。
短くするために、上のコードのように
$query = $yt->newVideoQuery();
でnewできるようになっています。
VideoQueryは実際は、
Zend/Gdata/YouTube/VideoQuery.php
にあります。

さらに、$query->startIndexとメンバ変数のように設定している箇所があります。
しかし、クラス、継承しているクラスを見てみると、そのようなメンバ変数はありません。
ここの実際のメソッドはsetStartIndex()です。
setter&getterはメンバ変数のように扱える仕組みになっているようです。

Viewの作成

app/views/layouts/default.ctp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
.....
<head>
    <?php echo $this->Html->charset(); ?>
    <title>
        <?php __('CakePHP: the rapid development php framework:'); ?>
        <?php echo $title_for_layout; ?>
    </title>
    <?php
        echo $this->Html->meta('icon');
 
        // ==============================================
        // CSS
        // ==============================================
        echo $this->Html->css('cake.generic');
         
        // ==============================================
        // javascript
        // ==============================================
        echo $this->Html->script('swfobject');
        echo $this->Html->script('jquery-1.4.3.min');
        echo $scripts_for_layout;
    ?>
</head>
.......

app/views/youtube/index.ctp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
<!-- TEST作成のため、CSSは直接書いている-->
<h1>test</h1>
<div id="yt" style="width: 800px;margin: auto;">
    <div style="float: left;">
        <div id="ytapiplayer">
        You need Flash player 8+ and JavaScript enabled to view this video.
        </div>
    </div>
    <div style="margin-left: 5px; float: left;width:260px; height:375px; overflow: scroll;">
        <?php
        foreach ($videoFeed as $videoEntry) {
            // サムネイルの取得
            $videoThumbnails = $videoEntry->getVideoThumbnails();
            // サムネイルは4つ取得できる(ここでは1つだけ表示した)
            foreach ($videoThumbnails as $thumbnail) {
                echo $this->Html->image($thumbnail['url'], array('height' => 90, 'width' => 120, 'id' => $videoEntry->getVideoId(), 'class' => 'youtube', 'title' => $videoEntry->getVideoTitle(), 'alt' => $videoEntry->getVideoTitle()));
                break;
            }
        }
        ?>
    </div>
</div>
<script type="text/javascript">
    var ytplayer = null;
    // playerの準備が完了後に呼び出されるコールバック
    // playerを制御するには必ず実装が必要
    function onYouTubePlayerReady(playerid){
        // プレイヤーを取得(swfobjectで指定したidを指定する)
        ytplayer = document.getElementById("myytplayer");
//      ytplayer.cueVideoById();
    }
     
    var params = { allowScriptAccess: "always" };
    var atts = { id: "myytplayer" };
    "ytapiplayer", "500", "375", "8", null, null, params, atts);
    $(function(){
        $("img.youtube").click(function(){
            ytplayer.loadVideoById($(this).attr("id"));
        });
        $("img.youtube").hover(function(){
            $(this).css("cursor", "pointer")
                .fadeTo("fast", 0.5);
        },function(){
            $(this).fadeTo("fast", 1);
        })
    });
     
</script>

imgタグのid属性に動画のidを設定しています。
サムネイルがクリックされたときに、その動画が再生されます。

CakePHP + jQuery elFinderでWEB上ファイル管理

web上でファイル管理ができないかなって思っていたところ、elFinderなるものをみつけた。
これをCakePHPに組み込んでみました。別にCakePHPである必要はないのですが。。

作成イメージ

普通に設定すると、クローラーに参照されたり、ファイルのアドレスを直接入力されるとみえてしまいます。
ここでは、ファイルの管理画面にはログインが必要であることを想定します。
保存先のディレクトリにBasic認証をかけて、サイトにログイン状態であれば、Ajaxを利用し自動でBasic認証するようにします。

必要な環境

  • php
  • jQuery,jQuery UI

Download

ここから

ダウンロードしたものをwebrootの適当な場所に配置する。
展開するとjs,css,imageのようなフォルダができるのでそれをそのまま配置していけばOK。

設定

設定は上記のサイトおよび、展開したファイルのに含まれるサンプルのhtmlを参照。

ファイルの保存先

webroot/hoge
.htaccessでBasic認証をかけます。

自動で認証

下記のサイトのライブラリをそのまま使用しました。
Ajaxで基本認証+SSL

/app/view/elfinder/index.ctp

1
2
3
4
5
6
7
8
<script>
    $().ready(function(){
        // 引数には適当な値を入力して下さい。user,passwordがBasic認証に必要なユーザ名とパスワードです。
        sendRequest(callback,data,method,url,async,sload,user,password);
        // 以下、elfindeの処理
        ..........
    });
</script>

ユーザ名とパスワードをそのまま記載するのはあまりよろしくないと思うので、
/app/controllers/elfinder_controller.php

1
2
3
4
5
6
7
8
9
10
.....
function get_basic(){
    $this->layout = 'ajax';
    // ユーザ名とパスワードを返す処理
    // e.g.
    $data = array('user' => 'hogehoge', 'passwd' => '********');
    header('Content-type: application/json; charset=UTF-8’);
    echo json_encode($data);
}
.....

等の処理をPHP側にいれ、ajaxでデータを取得すればよいかと思います。

これでファイルの管理画面にアクセスしたときに、Basic認証のダイアログを出すことなくアクセス出来るようになると思います。

最初に直接ファイルのアドレスを打って、ダイアログが出ることたしかめ、
サイトからアクセスすると出ないことを確認した方がいいかもしれません。

ブラウザを閉じると、Basic認証が解除されるので、再び直接アクセスするとダイアログが表示されるはずです。

もっといい方法を知っている方がいれば教えてください。