「HTML5 Exploding Camera Demo」に基づいたZenフレームワークでgetUserMediaおよびを使用する例





バージョン2012.1以降、組み込みZENコンポーネント<canvas>が CachéDBMSに登場しました。

Note: ここから 、CachéDBMSの無料のシングルユーザ版をダウンロードしてください


また、 Opera 12の最新リリースでは、 getUserMedia関数( WebRTC 1.0 :ブラウザー間のリアルタイム通信)の組み込みサポートがあり、Webカメラなどのメディア生成デバイスにアクセスできます。

注:デスクトップおよびモバイルブラウザでの getUserMedia / Stream APIサポートの概要表


これらの機能の両方を実証するために、 CachéDBMSに組み込まれたZENフレームワークを使用して、デモとしてHTML5 Exploding Camera Demoがベースとして選択されました。

注:元のデモはオンラインです。


また、 <canvas>コンポーネントの個々のピクセルでの動作を示すために、Webカメラからの出力ビデオのコードに4つのフィルターが追加されました。



コードは次でテストされました。



  1. Caché2012.2リリース候補(Unicode、x64)。
  2. Opera 12.00リリース。
  3. Chrome 21ベータ。


注:WebRTCは、Chromeブラウザ18.0.1008以降のバージョンのページで有効にすることができます:フラグまたはクロム://フラグ





ZENページクラスコード
クラスdemo.camcanvas Extends%ZEN.Component.page

{



パラメーター JSINCLUDES As STRING = "zenCSLM.js" ;



///このStyleブロックには、ページのCSSスタイル定義が含まれます。

XData スタイル

{

< スタイル タイプ = "text / css" >

* {

マージン:0;

パディング:0;

}

{

色:#99f;

}

#page {

背景:#000;

色:#fff;

フォントファミリー:「Helvetica Neue」、「Free Sans」、「Deja Vu Sans」、Arial、Helvetica、sans-serif。

マージン:0px;

パディング:0px;

}

#main {

色:#fff;

境界線:固体2px#c00;

ボーダー半径:1em;

行の高さ:1.5;

マージン:2em自動;

パディング:1em;

幅:50%;

}

#rs {

背景:#3af;

色:#777;

}

</ スタイル >

}



XData コンテンツ[ XMLNamespace = " www.intersystems.com/zen" ]

{

< xmlns = " www.intersystems.com/zen" title = "HTML5デモ&quot;カメラの爆発&quot;" id = "page" >

< タイマー

id = "タイマー"

タイムアウト = "0"

ontimeout = "zenPage.processFrame();"

/>

< html

id = "main"

align = "center"

hidden = "true" >

< ビデオ

id = "sourcevid"

autoplay = "autoplay"

hidden = "true"

>申し訳ありませんが、お使いのブラウザは &lt;を サポートしていません ビデオ &gt; <a href = "en.opera.com/download/"> Opera </ a >を お試しください 。</ ビデオ >

</ html >

< radioSet

id = "rs"

align = "center"

hidden = "true"

displayList = "ノーマル、エンボス、レッド、インバース、モノクロ"

valueList = "filterNormal、filterEmboss、filterRed、filterInversed、filterGrayscale"

= "filterNormal"

onchange = "zenPage.changeFilter(zenThis.getValue());"

/>

< canvas id = "output" hidden = "true" />

< canvas id = "sourcecopy" hidden = "true" />

</ ページ >

}



ClientMethod changeFilter( strFunction )[ 言語 = javascript]

{

eval( "filter = 'this。" + strFunction + "();'" );

}



ClientMethod filterNormal()[ 言語 = javascript]

{

}



ClientMethod filterInversed()[ 言語 = javascript]

{



var imageData = copy.getImageData( 0、0 、copycanvas.width、copycanvas.height);

var data = imageData.data;



var media = (data [ 0 ] + data [ 1 ] + data [ 2 ]) / 3 >> 0 ;



データ[ 0 ] = メディア。

データ[ 1 ] = メディア。

データ[ 2 ] = メディア。



for var i = 4 、len = data.length; i < len; i + = 4 ){

media = 255- (データ[i] + データ[i +1 ] + データ[i +2 ]) / 3 >> 0 ;



データ[i] = メディア。

データ[i +1 ] = メディア。

データ[i +2 ] = メディア。

}

copy.putImageData(imageData、 0、0 );

}



ClientMethod filterGrayscale()[ 言語 = javascript]

{



var imageData = copy.getImageData( 0、0 、copycanvas.width、copycanvas.height);

var data = imageData.data;



for var i = 0 、len = data.length; i < len; i + = 4 ){

var media = (data [i] + data [i +1 ] + data [i +2 ]) / 3 >> 0 ;



データ[i] = メディア。

データ[i +1 ] = メディア。

データ[i +2 ] = メディア。

}

copy.putImageData(imageData、 0、0 );

}



ClientMethod filterRed()[ 言語 = javascript]

{



var imageData = copy.getImageData( 0、0 、copycanvas.width、copycanvas.height);

var data = imageData.data;



for var i = 0 、len = data.length; i < len; i + = 4 ){

データ[i +1 ] = 0 ;

データ[i +2 ] = 0 ;

}

copy.putImageData(imageData、 0、0 );

}



ClientMethod filterEmboss()[ 言語 = javascript]

{

var imageData = copy.getImageData( 0、0 、copycanvas.width、copycanvas.height);

var data = imageData.data;



var media = (data [ 0 ] + data [ 1 ] + data [ 2 ]) / 3 >> 0 ;

データ[ 0 ] = メディア。

データ[ 1 ] = メディア。

データ[ 2 ] = メディア。



media = (データ[ 4 ] + データ[ 5 ] + データ[ 6 ]) / 3 >> 0 ;

データ[ 4 ] = メディア。

データ[ 5 ] = メディア。

データ[ 6 ] = メディア。



for var i = 8 、len = data.length; i < len; i + = 4 ){

media = (data [i] + data [i +1 ] + data [i +2 ]) / 3 >> 0 ;



データ[i] = メディア。

データ[i +1 ] = メディア。

データ[i +2 ] = メディア。



data [i -8 ] = (data [i -8 ] + 255- media) / 2 >> 0 ;

data [i -7 ] = (data [i -7 ] + 255- media) / 2 >> 0 ;

data [i -6 ] = (data [i -6 ] + 255- media) / 2 >> 0 ;



}

copy.putImageData(imageData、 0、0 );

}



ClientMethod processFrame()[ 言語 = javascript]

{

if isNaN(video.duration)){

if (SOURCERECT.width == 0 ){

SOURCERECT = {x: 0 、y: 0 、幅:video.videoWidth、高さ:video.videoHeight};

copycanvas.width = video.videoWidth;

copycanvas.height = video.videoHeight;





TILE_WIDTH = copycanvas.width / 16 ;

TILE_HEIGHT = copycanvas.height / 16 ;

TILE_CENTER_WIDTH = TILE_WIDTH / 2 >> 0 ;

TILE_CENTER_HEIGHT = TILE_HEIGHT / 2 >> 0 ;



this .createTiles();

zenSetProp( 'output' 'hidden' 、false);

zenSetProp( 'rs' 'hidden' 、false);

}

}

//タイルをコピーします

copy.drawImage(video、 0、0 );

eval(フィルター);

draw.clearRect(PAINTX、PAINTY、PAINTWIDTH、PAINTHEIGHT);



for var i = 0 、len = tiles.length; i < len; i ++ ){

var tile = tiles [i];

if (tile.force > 0.0001 ){

//拡張

var force = tile.force;

tile.moveX * = force;

tile.moveY * = force;

tile.moveRotation * = force;

tile.currentX + = tile.moveX;

tile.currentY + = tile.moveY;

tile.rotation + = tile.moveRotation;

tile.rotation %= 360 ;

tile.force * = 0.9 ;

if (tile.currentX <= 0 || tile.currentX > = PAINTWIDTH){

tile.moveX * = -1 ;

}

if (tile.currentY <= 0 || tile.currentY > = PAINTHEIGHT){

tile.moveY * = -1 ;

}

} else if (tile.rotation != 0 || tile.currentX != tile.originX || tile.currentY != tile.originY){

//折りたたみます

var diffx = (tile.originX - tile.currentX) * 0.2 ;

var diffy = (tile.originY - tile.currentY) * 0.2 ;

var diffRot = 0- tile.rotation) * 0.2 ;



if this .absolute(diffx) < 0.5 ){

tile.currentX = tile.originX;

} else {

tile.currentX + = diffx;

}

if this .absolute(diffy) < 0.5 ){

tile.currentY = tile.originY;

} else {

tile.currentY + = diffy;

}

if this .absolute(diffRot) < 0.5 ){

tile.rotation = 0 ;

} else {

tile.rotation + = diffRot;

}

} else {

tile.force = 0 ;

}

draw.save();

draw.translate(tile.currentX、tile.currentY);

draw.rotate(tile.rotation * RAD);

draw.drawImage(copycanvas、tile.videoX、tile.videoY、TILE_WIDTH、TILE_HEIGHT、 -TILE_CENTER_WIDTH、 -TILE_CENTER_HEIGHT、TILE_WIDTH、TILE_HEIGHT);

draw.restore();

}

zen( 'timer' ).startTimer();

}



ClientMethod successCallback( stream )[ 言語 = javascript]

{

//ビデオ要素のソースをカメラからのストリームに置き換えます

video.src = window.URL.createObjectURL(ストリーム) || ストリーム

video.play();

}



ClientMethod errorCallback( error )[ 言語 = javascript]

{

}



///個々のタイルのコンストラクター

ClientMethod Tile()[ 言語 = javascript]

{

this .originX = 0 ;

this .originY = 0 ;

この .currentX = 0 ;

this .currentY = 0 ;

this .rotation = 0 ;

this .force = 0 ;

この .z = 0 ;

this .moveX = 0 ;

this .moveY = 0 ;

this .moveRotation = 0 ;

this .videoX = 0 ;

this .videoY = 0 ;

}



/// Math.absより高速

ClientMethod 絶対( x )[ 言語 = javascript]

{

return (x <0? -x x);

}



ClientMethod zindexSort(



b )[ 言語 = javascript]

{

return (a.force - b.force);

}



///キャンバスを展開するためのクリック/マウス座標を取得します

ClientMethod dropBomb(

出来事

obj )[ 言語 = javascript]

{

event.preventDefault();

var posx = 0 ;

var posy = 0 ;

var e = イベント || window.event;



if (e.touches){

posx = event.touches [ 0 ] .pageX;

posy = event.touches [ 0 ] .pageY;

} else if (e.pageX || e.pageY){

posx = e.pageX;

posy = e.pageY;

} else if (e.clientX || e.clientY){

posx = e.clientX + ZLM.getPageXOffset() + document.documentElement.scrollLeft;

posy = e.clientY + ZLM.getPageYOffset() + document.documentElement.scrollTop;

}

var canvasX = posx - obj.offsetLeft;

var canvasY = posy - obj.offsetTop;

this .explode(canvasX、canvasY);

}



ClientMethod explode

x

y )[ 言語 = javascript]

{

for var i = 0 、len = tiles.length; i < len; i ++ ){

var tile = tiles [i];



var xdiff = tile.currentX - x;

var ydiff = tile.currentY - y;

var dist = Math.sqrt(xdiff * xdiff + ydiff * ydiff);

var rnd = Math.random();



var randRange = 180+ (rnd * 10 );

var range = randRange - dist;

var force = 3 * (range / randRange);

if (force > tile.force){

tile.force = force;

var radians = Math.atan2(ydiff、xdiff);

tile.moveX = Math.cos(ラジアン);

tile.moveY = Math.sin(ラジアン);

tile.moveRotation = 0.5 - rnd;

}

}

tiles.sort(zindexSort);

this .processFrame();

}



ClientMethod createTiles()[ 言語 = javascript]

{

var offsetX = (TILE_CENTER_WIDTH + (PAINTWIDTH - SOURCERECT.width) / 2 >> 0 );

var offsetY = (TILE_CENTER_HEIGHT + (PAINTHEIGHT - SOURCERECT.height) / 2 >> 0 );

var y = 0 ;

while (y < SOURCERECT.height){

var x = 0 ;

while (x < SOURCERECT.width){

var tile = new this .Tile();

tile.videoX = x;

tile.videoY = y;

tile.originX = offsetX + x;

tile.originY = offsetY + y;

tile.currentX = tile.originX;

tile.currentY = tile.originY;

tiles.push(タイル);

x + = TILE_WIDTH;

}

y + = TILE_HEIGHT;

}

}



ClientMethod onloadHandler()[ 言語 = javascript]

{

TILE_WIDTH = 32 ;

TILE_HEIGHT = 24 ;

TILE_CENTER_WIDTH = TILE_WIDTH / 2 ;

TILE_CENTER_HEIGHT = TILE_HEIGHT / 2 ;

SOURCERECT = {x: 0 、y: 0 、幅: 0 、高さ: 0 };

PAINTX = 0 ;

PAINTY = 0 ;

PAINTWIDTH = ZLM.getViewportWidth();

PAINTHEIGHT = ZLM.getViewportHeight();



RAD = Math.PI / 180 ;



タイル = [];

filter = 'this.filterNormal();' ;

video = document.getElementById( 'sourcevid' );

copycanvas = zen( 'sourcecopy' ).findElement( 'canvas' );

copy = zen( 'sourcecopy' ).getContext();



var outputcanvas = zen( 'output' ).findElement( 'canvas' );

draw = zen( 'output' ).getContext();

outputcanvas.width = PAINTWIDTH;

outputcanvas.height = PAINTHEIGHT -20 ;

var mouse_down = ドキュメント 内の 「createTouch」 「ontouchstart」 「onmousedown」 );

outputcanvas [mouse_down] = function (event){

zenPage.dropBomb(イベント、 これ );

};



// getUserMedia関数を使用してカメラからストリームを取得します

navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia;

window.URL = window.URL || window.webkitURL || window.mozURL || window.msURL;

if (navigator.getUserMedia){

//このオプションの美しいハックは@kanasansoftからのものです:

// http://www.kanasansoft.com/weblab/2012/06/arguments_of_getusermedia.html

var gumOptions = {video:true、toString: function (){ return 'video' ;}};

navigator.getUserMedia(gumOptions、 this .successCallback、 this .errorCallback);



zen( 'timer' ).setProperty( 'timeout' 33 );

zen( 'timer' ).startTimer();

} else {

zenSetProp( 'main' 'content' 'ああ、お使いのブラウザはgetUserMedia関数をサポートしていないようです。<br> <a href="http://en.opera.com/download/">ブラウザをお試しくださいそのようなサポートがあります</a>。

zenSetProp( 'main' 'hidden' 、false);

}

}



}


demo.camcanvasクラスのソース



ソースコードをインポートしてコンパイルし、例を実行します



ソースコード(プロジェクト、クラス、データなど)のインポートは、次を使用して実行できます。





これらのツールはすべて、 Cachéランチャーメニューから利用できます。



便宜上、 Cachéスタジオを使用して例を実行します

注:上記のツールはすべてロシア語のインターフェイスをサポートしていますが、メニュー項目を説明するときは英語版が使用されます。


だから:



  1. Cachéスタジオを開きます
  2. USER領域を選択します。File–> Change Namespaceまたは(F4);
  3. ファイルインポートウィザードを開始します。[ ツール]-> [ローカルにインポート ]または(Ctrl + I)。
  4. ファイル「sources.xml」を選択します。
  5. [ インポート済みアイテムのコンパイル ]ボックスをチェックして、[ OK ]をクリックします。
  6. クラスツリーからクラスdemo.camcanvasのソースコードを開きます。





    増す



  7. Webページに移動します: View-> Web Pageまたは(F5)。


デフォルトでは、ページへのリンクは次のようになります。

  http:// localhost:xxxx / csp / user / demo.camcanvas.cls 
、ここでxxxxは、 CachéDBMSのインストール時に指定したポート番号で、 組み込みのApache Webサーバーが実行されます。



PS: demo.camcanvasクラスは、 CSPCachéServer Pages)テクノロジーに簡単に変換できます。



All Articles