SQLの窓

2014年05月22日


jQuery + Shadowbox.js + Three.js で『画像を蝶のように飛翔させる』デモ表示

Three.js のネタ元は、canvas_geometry_birds です。あちらは鳥オブジェクトですが、少し変更して平面の画像を使えるように改造しています 

2014/05/22 : 画像のカスタマイズ方法です

結局、open_three.js は、ただ jQuery のプラグインとして IFRAME の中身を作っているだけなので、を外部にする必要は特にありません。以下のように実装すれば、背景画像は簡単に変更する事ができます。

とりあえず画像を変えてみたい場合は、こちらに 3D イラストのフリー素材があるので、画像をクリックして大きく表示して、大きな画像を右クリックして URL を取得して使ってみて下さい。( 下にあるソースでは、15行目で指定しています )

蝶の画像は、背景透過の PNG の必要があるので、フリーフォントで簡単ロゴ作成で作成して、Google のギャラリーにアップロードして使用していただくといいと思います。( 下にあるソースでは、12行目で指定しています )

※ ここでは、jQuery を 1.11.0 にしていますが(4行目)、古い IE だと動作しないかもしれないので、古いバージョンを使用しています。
<script>
// このページに jQuery が無い場合にロード
if ( !window.jQuery ) {
	document.write("<"+"script src=\"//ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js\"></"+"script>");
}
// ▼ 以下は Shadowbox と Three.js のコードロードします
</script>
<script type="text/javascript" src="http://lightbox.on.coocan.jp/sbx33/loadShadowbox.js"></script>
<script type="text/javascript">
// jQuery でボタンのイベントを取得して、好きな画像を飛ばします
$(function(){
	$("#start_button").openThree("http://winofsql.jp/image/s60_2.png");
});
// ここで背景画像を指定します
var img_url = "https://lh4.googleusercontent.com/-n2hqoMHMJfk/U2JsTXjEtbI/AAAAAAAATV0/hQZ5Oc_RIqA/s1200/uf3_001.jpg";
$.fn.extend({
	openThree: function(openThree_Param) {
		$(this).bind('click', function() {

			Shadowbox.open({ 
				player: 'iframe', 
				content: 'about:blank', 
				options: { 
					onFinish: function() {
						setTimeout(  function() {
							var doc = document.getElementById("sb-player").contentWindow.document;
							doc.write("<"+"style> body { background:url("+img_url+"); } </"+"style>");

							doc.write("<"+"script type=\"text/javascript\" src=\"https://lightbox.sakura.ne.jp/demo/three/three.min57.js\"></"+"script>");
							doc.write("<"+"script type=\"text/javascript\">image_url='" + openThree_Param + "';</"+"script>");
							doc.write("<"+"script type=\"text/javascript\" src=\"https://lightbox.sakura.ne.jp/demo/three/birds.js\"></"+"script>");
							doc.close();
						},100 );
					}
				} 
	
			}); 

		});
		return this;
	}
});
</script>

<button id="start_button">開始</button>

※ このコードをオンラインでテストしたい場合は、こちらから実行できます。このソースコードの右上ツールバーの中の左から2番目のアイコンでクリップボードにコピーされますので、リンク先で貼り付けて『新しく開く』ボタンをクリックしていただくとデモ画面が表示されます


以下は元々の記事です

※ 実行のクリックは、ページが完全にロードしてからでないと動作しないので注意して下さい。

ページ上のコンテンツに対して、jQueryのプラグインを作って、さらにそのプラグインでクリックイベントを登録して Three.js のデモ画面を Shadowbox.js が開いた IFRAME のウインドウに表示します
<script>
if ( !window.jQuery ) {
	document.write("<"+"script src=\"//ajax.googleapis.com/ajax/libs/jquery/2.0.3/jquery.min.js\"></"+"script>");

}
</script>
<script type="text/javascript" src="http://lightbox.on.coocan.jp/sbx33/loadShadowbox.js"></script>
<script type="text/javascript" src="https://lightbox.sakura.ne.jp/demo/three/open_three.js"></script>
<script type="text/javascript">
$(function(){
	$("#code140208003926").openThree($("#code140208003926").children("img").attr("src"));
	$("#code140208003927").openThree("http://winofsql.jp/image/s60_2.png");
	$("#code140208003928").openThree($("#code140208003928").attr("src"));
});
</script>

<button id="code140208003926"><img src="http://winofsql.jp/image/s60_1.png" /></button>
<button id="code140208003927"><img src="http://winofsql.jp/image/s60_2.png" /></button>
<input id="code140208003928" type="image" src="http://winofsql.jp/image/s60_3.png" style="border: solid 1px #000000;border-radius:10px;" />

loadShadowbox.js
if ( !window['lightboxTool'] ) {
	window.lightboxTool = {};
}
if ( !window.lightboxTool.initShadowbox ) {
	window.lightboxTool.initShadowbox = function ( ) {
		Shadowbox.init();
	}
}

(function() {
var str;
var userAgent = window.navigator.userAgent.toLowerCase();
if ( !window.Shadowbox ) {

	str="";
	str+="<link rel=\"stylesheet\" type=\"text/css\" href=\"http://lightbox.on.coocan.jp/sbx33/shadowbox.css\"> \n";
	str+="<"+"script type=\"text/javascript\" src=\"http://lightbox.on.coocan.jp/sbx33/shadowbox.js\" charset=\"utf-8\"></"+"script> ";
	document.write(str);

	if (window.attachEvent){
		window.attachEvent('onload', lightboxTool.initShadowbox );
	}
	else {
		window.addEventListener('load', lightboxTool.initShadowbox, false);
	}

}
})();



open_three.js
$.fn.extend({
	openThree: function(openThree_Param) {
		$(this).bind('click', function() {

			Shadowbox.open({ 
				player: 'iframe', 
				content: 'about:blank', 
				options: { 
					onFinish: function() {
						setTimeout(  function() {
							var doc = document.getElementById("sb-player").contentWindow.document;
							doc.write("<"+"style> body { background-color:#fff; } </"+"style>");

							doc.write("<"+"script type=\"text/javascript\" src=\"https://lightbox.sakura.ne.jp/demo/three/three.min57.js\"></"+"script>");
							doc.write("<"+"script type=\"text/javascript\">image_url='" + openThree_Param + "';</"+"script>");
							doc.write("<"+"script type=\"text/javascript\" src=\"https://lightbox.sakura.ne.jp/demo/three/birds.js\"></"+"script>");
							doc.close();
						},100 );
					}
				} 
	
			}); 

		});
		return this;
	}
});

見せたいのは、Three.js の 3D のデモ画面ですが、Three.js の実行はページの一部で実行するのはとても難しい問題があります。しかし、IFRAME 内に表示すればたいていの問題は解決します。



ただ、IFRAME を使う場合殆どの場合は、外部ドメインにページを作っておいて src 属性でその URL を指定するのが通常です。しかし、それではいろいろ管理が面倒で拡張性が無いので JavaScript の document.write で動的に書き出しています。この方法は昔から Google 等が行っていますし、完全なクロスブラウジングです。

書き出すものも、javascript のライブラリにまとめて SCRIPT 要素のまま書き出します。この際少しルールがあり、依存するライブラリは別々の SCRIPT 要素内から書き出す必要があります。それさえ守れば特に問題も無く動作するのですが、書き出す為の文字列を作るのが手作業では無理があるので自作のツールで行っています。

実装そのものは、jQuery のプラグインでまとめています。こうしておくと好きなコンテンツのクリックイベントとしてデモを表示する事ができます。画像は、プラグインの『openThree』の引数として渡すようになっています。

動作環境は、やはり Google Chrome 推奨です。

※ 背景は、ソースコードからは変えてあります


posted by lightbox at 2014-05-22 12:54 | Three.js & typeface | このブログの読者になる | 更新情報をチェックする

2014年02月14日


別ドメインの画像を『テクスチャ』として使った、Three.js(v65) + WebGL キューブアニメーション

実行ページ
( IE は IE11 以上でないと動作しません )


画像を THREE.ImageUtils.loadTexture で読み込んで、3D オブジェクトにテクスチャとして使用します。公式の説明は発見していませんが、Google+ と Picasa(実質 Google+と同じ) の画像データは、access-control-allow-origin: * を返すので、このような処理に適しています。

ここでは、一つの画像を繰り返し貼り付ける事を想定しています。単純に一枚の画像を面にフィットさせる場合は縦・横のサイズは自由ですが、繰り返して貼りつける場合には、64、128、256、512といったサイズである必要があります( 縦と横が同じサイズの正方形である必要はありませんが、正方形以外のサイズはあまり意味がありません )

サイズが自由である事の確認は、リンク先のページで任意の画像( Google+ のどなたの画像でも OK )のURL をセットして、x、y方向の繰り返しを 1 と 1 にして送信ボタンをクリックすると処理されますのでご確認下さい。また、そのサイズで複数繰り返しを行うとうまく処理されないのも確認できます。 







access-control-allow-origin ヘッダ が返されていますが、Three.js の機能として、THREE.ImageUtils.crossOrigin = "*"; を実行する必要があります。

この処理は、ここ最近のバージョンでやっときちんと実装されたものだと思います。いつ変更されたかは確認していませんが、少なくとも r57 のバージョンで実行すると、設定しなくても動作してしまいます。しかし、r65 では設定が必要になっていますので、実装する場合はバージョンに注意する必要があります。( Three.js は仕様変更が頻繁なので、現実的にはバージョンアップで常に確認する必要があります )
<script type="text/javascript" src="http://homepage2.nifty.com/lightbox/three/three.min65.js"></script>
<script type="text/javascript" src="http://homepage2.nifty.com/lightbox/three/user_play1.js"></script>

<div id="three_area" style='width:600px;height:600px;'></div>

<script type="text/javascript"> 
 
var camera, scene, renderer; 
var user_play; 
 
// 処理開始 
build_3d_world(); 
 
function build_3d_world() { 
 
	// カメラ 
	camera = new THREE.PerspectiveCamera( 70, 1, 1, 10000 ); 
 
	// シーン 
	scene = new THREE.Scene(); 

	// MeshBasicMaterial( 影を使わない ) を使用しているのでライトは必要ありませんが、実行してもかまいません
//	scene.add( new THREE.AmbientLight( 0xffffff ) );

	// 別ドメインの場合必要です( access-control-allow-origin: * の例 )
	THREE.ImageUtils.crossOrigin = "*";

	// 画像は、repeat.set で繰り返しで貼り付ける事ができますが、
	// その為には、64、128、256、512といったサイズである必要があります 
	// 別ドメインの場合は、access-control-allow-origin: ヘッダを返す必要がありますが、
	// Google+ や Picasa の画像は全てかえすようです
	var map = THREE.ImageUtils.loadTexture( "https://lh5.googleusercontent.com/-Xgh7ru0xoXs/UvujW9la76I/AAAAAAAASd4/IFWELp7fpA8/s512/st.png" );
	map.wrapS = map.wrapT = THREE.RepeatWrapping = 1000;
	map.repeat.set( 2, 2 );

	object = new THREE.Mesh( new THREE.CubeGeometry( 100, 100, 100, 4, 4, 4 ), new THREE.MeshBasicMaterial( { map: map } ) );

	object.position.set( 0, 0, 0 );
	scene.add( object );
 
	// レンダラー 
	renderer = new THREE.WebGLRenderer();
	// 以前は、div の背景色で設定していましたが、クリアカラーを指定するようになっています
	renderer.setClearColor( 0x444444 );
	renderer.setSize( 600, 600 ); 
 
	// 実装 
	document.getElementById("three_area").appendChild( renderer.domElement ); 
 
	// アニメーション 
	// 150 は回転効果の半径です
	user_play = new THREE.UserPlay1( scene, camera, renderer, animate, 150 ); 
	user_play.start(); 
 
} 
// ループ処理 
function animate() { 
 
	// アニメーションを行う為の次のフレームの呼び出し処理です
	requestAnimationFrame( animate ); 
	// この中で回転効果を処理しています
	user_play.render(); 
 
} 
 
</script>
THREE.ImageUtils.loadTexture で返されるのは THREE.Texture オブジェクトです。ここで最も重要な THREE.Texture の機能は、wrapSwrapT プロパティです。これは、平面における繰り返し方向に対するオプションをセットするプロパティで、それぞれ x 方向と y方向と考えて下さい。( S: 水平, T: 深さ, H: 高さ / 内部で、Vector2 に対応しているので、x と y )

オプションの値は 3つ 用意されていて、以下のようになっています
THREE.RepeatWrapping = 1000;
THREE.ClampToEdgeWrapping = 1001;
THREE.MirroredRepeatWrapping = 1002;
デフォルトは THREE.ClampToEdgeWrapping で、テクスチャを面に対して伸縮してセットする事を意味します。THREE.RepeatWrappingTHREE.MirroredRepeatWrapping は、それぞれテクスチャを繰り返してマッピングするもので、前者は境界毎に同じものが繰り返され、後者は境界毎に反転されたものが使用されます。 ただ、繰り返し処理を使っていても、繰り返す回数を 1 回だけにすると THREE.ClampToEdgeWrapping と同じ結果になります。 ※ map.repeat.set( 1, 1 ); 以下の処理は、Three.js の構築部分のみを明確にするためにアニメーション部分を外に出しています。 user_play1.js
THREE.UserPlay1 = function ( scene, camera, renderer, animate, radius ) {

	this.scene = scene;
	this.camera = camera;
	this.renderer = renderer;
	this.radius = ( radius !== undefined ) ? radius : 600;

	this.theta = 0
	this.animate = animate;


};
THREE.UserPlay1.prototype = {
	constructor: THREE.UserPlay1,
	start: function() {
		this.animate();
	},
	render: function() {
		this.theta += 0.1;

		this.camera.position.x = this.radius * Math.sin( THREE.Math.degToRad( this.theta ) );
		this.camera.position.y = this.radius * Math.sin( THREE.Math.degToRad( this.theta ) );
		this.camera.position.z = this.radius * Math.cos( THREE.Math.degToRad( this.theta ) );

		this.camera.lookAt( this.scene.position );
		this.renderer.render( this.scene, this.camera );
	}

};
これらのコードは、THREE.CanvasRenderer でも動作します。但しその場合はセグメントの境界が表示されてしまうので、THREE.MeshBasicMaterial のオプションとして overdraw: true を追加します。また、キューブのセグメント数( 4, 4, 4 ) は、THREE.CanvasRenderer での処理時に効力を発揮します( セグメント単位の画像のゆがみ表現となるので、セグメント数が少ないと全体としての歪みが大きくなります )

3D の原理の専門的な部分はよく解らないのですが、WebGL では平面のセグメント数が少なくても良いように感じています。『 object = new THREE.Mesh( new THREE.CubeGeometry( 100, 100, 100 ), new THREE.MeshBasicMaterial( { map: map } ) );』

関連する資料

ポリゴンメッシュ



posted by lightbox at 2014-02-14 17:43 | Three.js & typeface | このブログの読者になる | 更新情報をチェックする

2013年04月08日


Three.js( Canvas ) デモコード( 背景画像、前景画像、鳥画像変更可 ) : 200のオブジェクトが舞います。

ボタンを押すと、こんな感じの画像が表示されて、背景と前景の間を 3D オブジェクトが鳥のように舞います。

前景画像は背景透過。
鳥画像は、縦横 60px 推奨( 大きいと無駄にメモリを使うだけなので )
※ オブジェクトは、マウスカーソルを避けようとします。

貼り付け用ソースコード
<input type="button" value="表示開始" onclick='three_canvas_bird()' />
<iframe
	src="about:blank"
	id="birds"
	name="birds"
	scrolling="no"
	width="600"
	height="450"
	marginwidth="0"
	marginheight="0"
	style='display:block;border:solid 1px #000000;'
></iframe>
<script type="text/javascript">
function three_canvas_bird() {
	var background_img = "https://lh3.googleusercontent.com/-FZouzPuFejo/UVSH_NqCE8I/AAAAAAAAMeg/iahQIvqs9k0/s600/_img.jpg";
	var forground_img = "https://lh6.googleusercontent.com/-jwlcFaTFj2g/UVSJlDFpiEI/AAAAAAAAMeo/N5I5-coboAk/s500/_img.png";
	var bird_img = "http://winofsql.jp/image/s60_1.png";

	var doc = document.getElementById("birds").contentWindow.document;
	doc.write("<"+"style> body { background:url("+background_img+") no-repeat; } </"+"style>");

	doc.write("<"+"script type=\"text/javascript\" src=\"http://homepage2.nifty.com/lightbox/three/three.min57.js\"></"+"script>");
	doc.write("<"+"script type=\"text/javascript\">image_url=\""+bird_img+"\";</"+"script>");
	doc.write("<"+"script type=\"text/javascript\" src=\"http://homepage2.nifty.com/lightbox/three/birds.js\"></"+"script>");
	doc.write("<div style='position:absolute;left:0px;top:0px;width:100%;height:100%;background:url("+forground_img+") no-repeat center bottom;'></div>");
	doc.close();
}
</script>




posted by lightbox at 2013-04-08 19:14 | Three.js & typeface | このブログの読者になる | 更新情報をチェックする

2013年03月26日


Three.js + Shadowbox 飛翔する200人の初音ミク

画像は  です。大きい画像を指定しても強制的にこのサイズで描画します。つまり、大きくするとメモリが無駄になるだけです。

実行は、Google Chrome 推奨ですが、Three.js とは言え、Canvas を使用しているので他のブラウザでも動作はします。速度的に Google Chrome 推奨です。( 今日自分の iPhone で見たら物凄く遅いですが、一応動作していました )
<script type="text/javascript" src="http://lightbox.on.coocan.jp/sbx33/loadShadowbox.js" charset="utf-8"></script>
<script type="text/javascript">
function openThree(your_image_60) {
	Shadowbox.open({ 
		player: 'iframe', 
		content: 'about:blank', 
		options: { 
			onFinish: function(target) {
				setTimeout(  function() {
					var doc = document.getElementById("sb-player").contentWindow.document;
					doc.write("<"+"style> body { background-color:#fff; } </"+"style>");

					doc.write("<"+"script type=\"text/javascript\" src=\"https://lightbox.sakura.ne.jp/demo/three/three.min57.js\"></"+"script>");
					doc.write("<"+"script type=\"text/javascript\">image_url='" + your_image_60 + "';</"+"script>");
					doc.write("<"+"script type=\"text/javascript\" src=\"https://lightbox.sakura.ne.jp/demo/three/birds.js\"></"+"script>");
					doc.close();
				},100 );
			}
		} 
	
	}); 
}

</script>
<input type="button" value="飛翔する200人の初音ミク" onclick="openThree('http://lh3.googleusercontent.com/-4Em5315jEAI/T_GVyEMF5BI/AAAAAAAAHBg/s78i3fY94vU/s60/Black_Eagle_Miku_Elf4.png')" />
元の大きな画像はこちらです。左上と右上の部分が座標移動しているだけですが、羽ばたいているように見えると思います。

Three.js のオリジナルはこちらから見る事ができます

ここでは、Three.js の内容では無く、Shadowbox を使って IFRAME 内に動的にページを作成する事が重要です。Three.js では、通常画像の URL を指定する事によってその画像をページ内に大きく表示してくれますが、HTML ページを指定すると IFRAME を使用します。

昨今、他のページを埋め込むのは自分のサイトでもいろいろ難しい問題がありますが、ここでは document.write を使って同一ドメインのページを表示しているのと同等の IFRAME を動的に作成する方法を示しています。

自分で IFRAME を用意してもいいのですが、どうせなので Shadowbox の美しいウインドウを使ってみました。また、表示する内容も Three.js のサンプルを改造して『初音ミク』の画像を飛ばせています。Three.js の部分は全て JavaScript に書き込んで、画像だけを変更可能にしています。

Shadowbox も、自分のサイトにホスティングして、記事毎に動的にロードする方法を示していますが、もしよろしかったらこの部分はご自由にお使い下さい。( ホスティングをそのまま使ってもいいですし、コードを転用なさってもかまいません )


posted by lightbox at 2013-03-26 00:09 | Three.js & typeface | このブログの読者になる | 更新情報をチェックする

2012年05月07日


最新のThree.js(2012/04/22-r49)は、IEで動かないバグがあります。それと、CanvasRenderer からLambert で テクスチャの処理が削除されました

何故か無条件に console.log でリビジョンを表示するようになっているので、IE の場合はF12 で開発者ツールを開かないとエラーで実行されません。そこで先頭で以下のコードを追加しておくといいです。
if(!window["console"]){window["console"]={};window["console"]["log"]=function(){}}
それから、光に対応している MeshLambertMaterial の CanvasRenderer の処理でテクスチャ処理が削除されているので、代わりに MeshBasicMaterial を使用します。もともと、CanvasRendererでは、無理やり Google Chrome でしかまともに動かない darker というものを使っていたのですが、無理が生じてきたものと思われます。結果的に、WebGLRenderer と CanvasRenderer では Materialを分けて使う運用になると思います。

CanvasRenderer で MeshBasicMaterial への移行

実際、ソース上では MeshBasicMaterial として仕様変更されているのですが、他の部分が完全に右へならえになっていないので、CanvasRenderer を使いたい場合は注意が必要です。

★ WEB 実行サンプル


1) 3D モデルをロードしたい場合は、JSONLoader のイベント内で MeshFaceMaterial を使う

mesh = new THREE.Mesh( geometry, new THREE.MeshFaceMaterial());
これは、ポリゴンの3角形データが内部で配列になっていて、それを統括するのが MeshFaceMaterial です。MeshFaceMaterial は定義上名前だけの器として内部にはなにもありません。ただ、さらにデータ内の shading を Basic にする必要がありますし、これらは今後のバージョンアップで仕様変更される可能性もあります。

※ データを変更しない場合、テクスチャが一枚だけならこれでも表示されます

var param = {
	map: THREE.ImageUtils.loadTexture('texture.png'),
	overdraw: true
};
mesh = new THREE.Mesh( geometry, new THREE.MeshBasicMaterial( param ));

2) 単純ポリゴンでは、パラメータでテクスチャを渡して MeshBasicMaterial を直接使う

キュープ等では MeshBasicMaterial でテクスチャは自分でロードします。
var image = new Image()
image.onload = function () {
	var texture = new THREE.Texture( this );
	texture.needsUpdate = true;
	material = new THREE.MeshBasicMaterial({map: texture});
	// キューブ
	cube = new THREE.Mesh(new THREE.CubeGeometry(300, 300, 300), material);
	cube.overdraw = true;
	scene.add(cube);
};
image.src = 'texture.png';



posted by lightbox at 2012-05-07 01:58 | Three.js & typeface | このブログの読者になる | 更新情報をチェックする

2012年03月21日


Three.js r48 で JSONLoader が Opera で動作しない原因と対処方法

IE9 は未確認で、来週まで確認できません。

Google Chrome と Firefox では、XMLHttpRequest オブジェクトに定数が
定義されていて、r48 からその定数を使ってステータスチェックしているの
で Opera では全く動きません。

ですから、以下のような記述を JSONLoader が使われる前に記述して下さい。
<script type="text/javascript">
if( !XMLHttpRequest.DONE ) {
	console.log("setting");
	XMLHttpRequest.prototype.DONE = 4
	XMLHttpRequest.prototype.HEADERS_RECEIVED = 2
	XMLHttpRequest.prototype.LOADING = 3
	XMLHttpRequest.prototype.OPENED = 1
	XMLHttpRequest.prototype.UNSENT = 0
}
</script>
r47 では数字で条件書いておられるのでこれがなくても動作します。

r48 の Three.js の該当部分を直接変更する方法もありますが、どうもこの作者さんは
 WebKit 以外に興味無いようなので、今後も良く起こりそうです。外部から変更したほうが、
多くの人にとって使いやすいものになると思います。




タグ:トラブル
posted by lightbox at 2012-03-21 19:23 | Three.js & typeface | このブログの読者になる | 更新情報をチェックする

2012年03月18日


Three.js で、Blender から出力したデータ(Three.jsフォーマット)の境界線を消す overdraw の適用のさせかた

サンプルやソースを見る限り、オリジナルには実装されていないようなのですが、
メソッドとして material の一覧を取得する事ができるのは内部コードで解った
ので、実装してみました。

もちろん、もともと持っている機能ですが、単純な形状でしか表からは使えない
ようでした。それに、そもそも CanvasRenderer 専用ですし、オリジナルでは
Google Chrome と Safari 以外ではテクスチャがまともに貼られ無いので需要が
全くなかったので必要無いと言えば無いのですが、Win8 で Metro(JS) で動作さ
せる為の確認事項です

適用前

適用後


<div style='margin-left:100px;'>
<input type="button" value="境界線" onclick='toggle_overdraw();'>
<input type="button" value="回転" onclick='toggle_rotation();'>
</div>
<div id="container_three"></div>

<script src="http://winofsql.jp/js/load_three.js"></script>

<script type="text/javascript">
	// ***********************************************************
	// 回転切り替え
	// ***********************************************************
	function toggle_rotation() {

		rt = !rt;

	}
	// ***********************************************************
	// CanvasRenderer : JSONLoader 用 overdraw 切り替え
	// ***********************************************************
	function toggle_overdraw() {

		od = !od;

		var _projector = new THREE.Projector();
		var _renderData = _projector.projectScene( scene, camera, true );
		var _elements = _renderData.elements;
		for ( var e = 0, el = _elements.length; e < el; e++ ) {

			element = _elements[ e ];
			material_x = element.material;
			if ( material_x instanceof THREE.MeshFaceMaterial ) {
				material_x = element.faceMaterial;	
				material_x.overdraw = od;
			}
		}

	}

	var od = false;
	var rt = false;

	var container, stats;
	var camera, scene, renderer;
	var mesh;
	var mouseX = 0, mouseY = 0;
	var material;

	var windowHalfX = window.innerWidth / 2;
	var windowHalfY = window.innerHeight / 2;

	init();
	animate();

	// ***********************************************************
	// 初期処理
	// ***********************************************************
	function init() {

		container = document.getElementById( 'container_three' );

		scene = new THREE.Scene();
		scene.position.y = 150;

		camera = new THREE.PerspectiveCamera( 50, window.innerWidth / window.innerHeight, 1, 10000 );
		camera.position.set( 0, 200, 650 );
		scene.add( camera );

		loader = new THREE.JSONLoader();
		loader.load('http://winofsql.jp/js/three/data/eyes.js', function ( geometry ) {

			material = new THREE.MeshFaceMaterial();
			mesh = new THREE.Mesh( geometry, material );

			mesh.scale.x = 100;
			mesh.scale.y = 100;
			mesh.scale.z = 100;
			scene.add( mesh );

		}, '../js/three/data' );

		renderer = new THREE.CanvasRenderer( );
		renderer.setSize( 700, 500 );

		container.appendChild( renderer.domElement );

		document.addEventListener( 'mousemove', onDocumentMouseMove, false );

	}

	// ***********************************************************
	// マウス位置( カメラ位置として利用 )
	// ***********************************************************
	function onDocumentMouseMove( event ) {

		mouseX = ( event.clientX - windowHalfX );
		mouseY = ( event.clientY - windowHalfY );

	}

	// ***********************************************************
	// 一定期間の実行の繰り返し
	// ***********************************************************
	function animate() {

		requestAnimationFrame( animate );

		render();

	}

	// ***********************************************************
	// 移動データの設定と描画
	// ***********************************************************
	function render() {

		camera.position.x += ( mouseX - camera.position.x ) * 0.05+15;
		camera.position.y += ( - mouseY - camera.position.y ) * 0.05;
		camera.lookAt( scene.position );
		

		if ( mesh ) {
			if ( rt ) {
				mesh.rotation.y -= 0.005;
			}
		}

		renderer.render( scene, camera );

	}


</script>




タグ:Three.js
posted by lightbox at 2012-03-18 00:47 | Three.js & typeface | このブログの読者になる | 更新情報をチェックする

2012年03月17日


動的に typeface.js フォントを適用させる

元のコードでは、ページ全体の適用を renderDocument で一度だけ設定する
ようになっていますが、もう一度 renderDocument を実行すると、既に適用
された要素も対象となるようなので、よろしく無いと思います。

というか、個別の適用はいたって簡単なコードで済みますので狙い撃ちでい
いと思います。但し適用前にかならず対象要素の innerHTML を変更しておく
必要があります( 中に canvas が作成されているので )

※ vml も動作しますが、dummyShape が適用毎に作成されてしまいます





<script src="http://winofsql.jp/js/load_typeface.js"></script>
<script type="text/javascript">
if (_typeface_js && _typeface_js.loadFace)    _typeface_js.loadFace({"glyphs":{"お":{"x_min":198.03125,"x_max":1182.734375,"ha":1389,"o":"m 359 -75 l 238 -18 l 198 122 q 424 489 257 335 l 416 641 l 254 684 l 246 752 l 410 823 q 546 1030 429 971 q 595 839 573 935 l 733 826 l 744 755 l 598 668 l 598 541 q 1076 419 850 533 q 1171 207 1128 316 q 1104 32 1142 116 q 929 -32 1015 -2 l 774 16 l 717 111 l 774 149 q 939 62 847 81 l 1034 105 l 1071 223 q 988 364 1032 297 l 793 427 l 598 359 q 492 -21 568 164 l 359 -75 m 378 27 q 448 166 419 94 l 435 302 l 427 302 l 341 253 q 287 111 311 185 l 306 37 l 375 24 l 378 27 m 1125 668 l 961 809 l 1018 857 l 1182 714 l 1125 668 "},"え":{"x_min":287.546875,"x_max":1142.03125,"ha":1389,"o":"m 915 -37 l 750 89 q 717 240 741 169 l 649 286 q 298 29 454 196 l 287 116 l 576 508 q 373 592 470 546 l 394 660 q 893 722 641 701 l 899 622 l 725 421 q 845 127 861 307 q 1142 40 969 29 l 1142 32 l 1133 -32 l 915 -37 m 766 884 l 486 906 l 486 976 l 519 976 l 801 952 l 801 884 l 766 884 "},"い":{"x_min":203.140625,"x_max":1188.15625,"ha":1389,"o":"m 408 16 l 249 155 l 203 527 q 284 884 198 736 l 317 900 l 333 798 l 311 497 q 410 146 298 297 l 421 143 q 573 294 514 204 l 627 234 l 557 84 l 408 16 m 1101 354 l 1101 356 l 931 728 l 1007 758 l 1188 375 l 1101 354 "},"う":{"x_min":364.859375,"x_max":1029.453125,"ha":1389,"o":"m 627 -67 l 576 8 q 910 389 826 127 l 866 535 l 706 571 l 413 527 l 364 603 q 801 701 576 684 l 958 625 l 1029 386 l 896 81 l 627 -67 m 834 878 q 522 938 674 906 l 541 1011 l 560 1011 l 863 957 l 863 941 l 850 878 l 834 878 "},"あ":{"x_min":211.59375,"x_max":1212.5625,"ha":1389,"o":"m 885 -75 l 842 -8 l 1029 92 l 1098 256 l 1037 413 l 1010 416 l 866 408 q 687 54 747 245 q 375 -56 535 -8 l 257 -10 l 211 161 q 438 636 309 413 l 435 698 l 290 741 l 282 815 l 440 878 l 505 1028 l 581 1055 q 660 878 614 965 l 942 862 l 945 790 l 649 720 l 598 611 l 636 611 q 820 674 744 603 l 874 665 q 1125 473 980 543 l 1212 245 q 1114 18 1166 130 l 885 -75 m 386 46 q 495 174 448 105 l 470 373 l 465 373 l 378 337 l 301 143 l 320 51 l 383 43 l 386 46 m 646 313 l 646 321 l 701 454 l 690 454 l 611 446 l 611 435 l 638 313 l 646 313 "}},"cssFontWeight":"normal","ascender":1194,"underlinePosition":-96,"cssFontStyle":"normal","boundingBox":{"yMin":-165.46875,"xMin":0,"yMax":1120,"xMax":1318.359375},"resolution":1000,"original_font_information":{"postscript_name":"kirieji_1331984570687","version_string":"Version 1.00","vendor_url":"","full_font_name":"kirieji_1331984570687","font_family_name":"kirieji_1331984570687","copyright":"fub","description":"","trademark":"kirieji_1331984570687","designer":"","designer_url":"","unique_font_identifier":"kirieji_1331984570687","license_url":"","license_description":"","manufacturer_name":"","font_sub_family_name":"Regular"},"descender":-196,"familyName":"kirieji_1331984570687","lineHeight":1389,"underlineThickness":48,"loaded":true});

// *****************************************************************
// 動的に typeface フォントを適用させる
// *****************************************************************
function apply_test(no,str) {

	var e = document.getElementById("unit"+no);
	e.innerHTML = str;

	_typeface_js.replaceText(e);
	e.style.visibility = 'visible';
	if (_typeface_js.vectorBackend == 'vml') {
		var dummyShape = document.createElement('v:shape');
		dummyShape.style.display = 'none';
		document.body.appendChild(dummyShape);
	}
}
</script>
<style type="text/css"> 
.typeface-js { 
	font-family: kirieji_1331984570687;
	font-size: 100px; 
} 
</style> 
<div id="test_unit" style='height:110px'>
<input type="button" value="あ" onclick="apply_test(1,'あ')">
<input type="button" value="い" onclick="apply_test(2,'い')">
<input type="button" value="う" onclick="apply_test(1,'う')">
<input type="button" value="え" onclick="apply_test(2,'え')">
<input type="button" value="お" onclick="apply_test(1,'お')">
<input type="button" value="セットのみ" onclick="document.getElementById('unit1').innerHTML='あい';">
<br />
<span id="unit1" class="typeface-js" style="font-family:kirieji_1331984570687;"></span> 
<span id="unit2" class="typeface-js" style="font-family:kirieji_1331984570687;"></span> 
</div>
 



posted by lightbox at 2012-03-17 21:24 | Three.js & typeface | このブログの読者になる | 更新情報をチェックする

2012年03月15日


日本語の .ttf をそのまま変換した大きな typeface.js の内容から必要な文字だけを抜き取るツールを作りました( 現在は 切り絵字/水面字/モフ字/青柳隷書しも )

ドロップシャドウ適用時にエリアを広げるようにしました
青柳隷書しもを追加しました
プレビューを可能にしました
font-family と ドロップシャドウオプションの入力を追加しました
水面字とモフ字を追加しました
こんな感じで
表示されます
以下の画像をクリックすると、処理ページを開きますが、最初のロードで
オリジナルのフォントファイルがインターネットからロードされる為、か
なり時間( 十数秒 ) かかる場合がありますので注意して下さい。

※ 現在、文字選択の都合で句読点や記号類が動作していません。(データ更新しました)
※ 漢字、かたかな、ひらがなは実装しています
※ 半角英数字類は機能していると思います


※ キャッシュにファイルが読み込まれると次からは高速です

そのまま貼り付けるだけになってはいますが、他の CSS とのかねあいで、
そのページ用に追加 CSS が必要になって来ると思います。

※ ここでは、line-height が必要でした




理屈はいたって簡単なので、だれでもできますが、typeface.js のサイト
へ行って変換は必ず必要になりますし、その時の選択を絞らないとエラー
になるのでそこだけが面倒です。

また、実行は localhost で WEBサーバーを置いて実行するのが望ましい
のでこれまた少し手間が必要です。慣れた方なら特に問題は無いとは思い
ますが、手軽にフリーフォントを WEB フォントライクに使う為に、逐一
動作確認しながらフォントの種類を増やして行く予定です
<!doctype html>
<html>
<head>
<meta charset="utf-8">
</head>
<body>
<textarea id="my_typeface" style='width:700px;height:600px;' onclick='this.select();'></textarea>
<script type="text/javascript">
var _typeface_js = {

	faces: {},

	loadFace: function(typefaceData) {

		this.faces = typefaceData;

	}
}
</script>
<script type="text/javascript" src="kirieji_regular.typeface.js" charset="utf-8"></script>


<script type="text/javascript">
var target = '愛してます';
var prop;
for( prop in _typeface_js.faces.glyphs ) {

	if ( target.indexOf( prop.toString() ) >= 0 ) {
	}
	else {
		delete _typeface_js.faces.glyphs[prop];
	}

}
document.getElementById("my_typeface").value = 'if (_typeface_js && _typeface_js.loadFace) _typeface_js.loadFace('+JSON.stringify( _typeface_js.faces )+');';
</script>
</body>
</html>




posted by lightbox at 2012-03-15 21:28 | Three.js & typeface | このブログの読者になる | 更新情報をチェックする

typeface.js(0.15)で、Operaが正しく動作しない理由

Operaは、canvas そのものは動作するのですが、typeface.js が利用している
getComputedStyle というメソッドが正しく動作していません。

typeface.js は、style の定義を読み取る事で対象のエレメントを探すのですが
その時に使われるメソッドが getComputedStyle と言うメソッドで、これはそのエレ
メントが適用されている style の状態を知る事ができるというものです。しかし、
少なくとも typeface.js(0.15)とOpera11.61の組み合わせでそれは正しい定義を
取り出す事ができていません。(具体的には fontFamily に入っていない)

ですから、typeface.js の変更にあたって、Opera でも一応表示できるようにし
た方法が、インラインスタイルで font-family を指定する時に限って正しく表示
されるというものです。getComputedStyle がダメなので、その要素の style 内
を直接見るようにしました。

しかし、Opeara を使っていない人からすれば、これは面倒なだけの処理になるので
『Opera ユーザが動作確認できる』という内容でしかありません。

さらに、Opera だけが typeface.js の為の必要なデータを取り出す処理でフリーズ
してしまいます。おそらく Object を削除する delete ステートメントを大量に実行
した結果だと予想していますが、そもそも動かないので検証はしていません。



タグ:トラブル
posted by lightbox at 2012-03-15 20:07 | Three.js & typeface | このブログの読者になる | 更新情報をチェックする

2012年03月11日


typeface.js を少し変更して、データに値を追加するとドロップシャドウが実装できるようにしました

こんな感じで
IE8 は vml なので対象外です。

とりあえず今は他に思い付きませんが、canvas でできる事ならできそうです。
貼り付ける単位で表現を別にする為に、データ内の kirieji を kirieji2 に
変更しています

関連する記事

日本語の .ttf をそのまま変換した大きな typeface.js の内容から必要な
文字だけを抜き取るツールを作りました( 現在は 切り絵字のみ )

データの設定方法を見る
posted by lightbox at 2012-03-11 12:03 | Three.js & typeface | このブログの読者になる | 更新情報をチェックする

2012年03月10日


自作デザインフォントによる、typeface.js での表示テスト

Three.js を使ってみて存在を知りましたが、必要範囲のみのデータ量にできるのがとても有効だと思います。ブラウザの開発者ツールで実行後のコードを見ると、描画方法として、canvas と vml が用意されていて、IE8 は vml が使われています( IE9 以降は canvas です )。Google Chrome や Firefox は canvas が使われており、canvas ではテキストが選択できるようになっています。

Three.js では、直接 typeface.js のデータを使うようになっているので、データを共有できるので便利です。
AB
<script src="http://winofsql.jp/js/load_typeface.js"></script>
<script src="http://winofsql.jp/js/three/data/lightbox_regular.typeface.js"></script>

<style type="text/css">
.s200 {
	font-size: 200px;
	line-height: 200px;
}
.s400 {
	font-size: 400px;
	line-height: 400px;
}
</style>

<div 
	class="typeface-js" 
	style="font-family: lightbox;">
	<span class="s200">A</span>
	<span class="s400">B</span>
</div>

以下はABのみの自作フォントの内容です
if (_typeface_js && _typeface_js.loadFace) _typeface_js.loadFace({"glyphs":{"A":{"x_min":43.40625,"x_max":651.046875,"ha":694,"o":"m 173 1171 q 254 1209 227 1204 q 303 1217 282 1215 q 363 1220 325 1220 q 434 1215 406 1220 q 493 1199 477 1204 q 531 1177 509 1193 q 569 1144 553 1161 q 618 1079 585 1128 q 645 971 640 1009 q 651 868 651 933 q 640 775 645 802 q 626 721 634 748 q 596 634 618 694 q 564 537 585 591 q 520 444 542 488 q 490 377 499 401 q 472 303 482 352 q 480 246 472 265 q 496 217 488 227 q 520 195 504 206 q 564 173 537 184 q 604 170 591 173 q 651 173 618 168 q 607 119 623 135 q 553 75 591 103 q 434 43 499 43 q 341 51 374 43 q 254 81 309 59 q 187 127 211 108 q 124 184 162 146 q 84 241 97 222 q 59 287 70 260 q 43 401 48 314 l 43 564 l 43 737 q 51 914 43 840 q 73 1030 59 987 q 130 1128 86 1074 q 173 1171 151 1155 m 227 1009 q 184 938 195 965 q 162 868 173 911 q 217 748 151 781 q 282 759 260 737 q 303 824 303 781 l 303 954 q 260 1041 260 954 l 217 998 l 227 1009 m 477 1041 q 390 954 434 954 l 390 824 q 434 737 390 737 q 499 754 477 737 q 542 824 520 770 q 542 900 547 857 q 520 971 531 944 q 477 1041 509 998 "}," ":{"x_min":0,"x_max":0,"ha":694},"B":{"x_min":43.40625,"x_max":694.453125,"ha":694,"o":"m 43 694 l 217 824 l 217 1085 l 477 1128 l 520 954 l 694 1030 l 542 922 l 607 705 q 629 602 618 651 l 640 531 q 651 412 645 472 l 651 303 l 43 130 q 217 265 184 238 q 336 368 249 292 q 406 444 390 423 q 434 520 423 466 q 287 472 336 488 q 173 434 238 455 q 260 564 227 520 l 368 596 q 434 694 423 607 q 358 640 412 661 l 260 607 l 260 651 l 130 607 l 217 781 l 130 737 l 43 694 "}},"cssFontWeight":"normal","ascender":1238,"underlinePosition":0,"cssFontStyle":"normal","boundingBox":{"yMin":43.40625,"xMin":43.40625,"yMax":1220.703125,"xMax":694.453125},"resolution":1000,"original_font_information":{"postscript_name":"","version_string":"Version 1.0","vendor_url":"","full_font_name":"night","font_family_name":"lightbox","copyright":"(c)yuno","description":"","trademark":"","designer":"","designer_url":"","unique_font_identifier":"Untitled_4B250121","license_url":"","license_description":"","manufacturer_name":"","font_sub_family_name":"Regular"},"descender":-301,"familyName":"lightbox","lineHeight":1597,"underlineThickness":0});

関連する記事

自作のデザインフォントを使って、Three.js のテキストオブジェクトテストサンプルです




Three.js : 日本語フォントの立体表示





------------------------------------------------
フォントのデータは、ページを表示した後、開発者ツールで console.dir( _typeface_js.faces.lightbox.normal.normal.glyphs ) とすると確認できます



posted by lightbox at 2012-03-10 02:51 | Three.js & typeface | このブログの読者になる | 更新情報をチェックする
Seesaa の各ページの表示について
Seesaa の 記事がたまに全く表示されない場合があります。その場合は、設定> 詳細設定> ブログ設定 で 最新の情報に更新の『実行ボタン』で記事やアーカイブが最新にビルドされます。

Seesaa のページで、アーカイブとタグページは要注意です。タグページはコンテンツが全く無い状態になりますし、アーカイブページも歯抜けページはコンテンツが存在しないのにページが表示されてしまいます。

また、カテゴリページもそういう意味では完全ではありません。『カテゴリID-番号』というフォーマットで表示されるページですが、実際存在するより大きな番号でも表示されてしまいます。

※ インデックスページのみ、実際の記事数を超えたページを指定しても最後のページが表示されるようです

対処としては、このようなヘルプ的な情報を固定でページの最後に表示するようにするといいでしょう。具体的には、メインの記事コンテンツの下に『自由形式』を追加し、アーカイブとカテゴリページでのみ表示するように設定し、コンテンツを用意するといいと思います。


※ エキスパートモードで表示しています

アーカイブとカテゴリページはこのように簡単に設定できますが、タグページは HTML 設定を直接変更して、以下の『タグページでのみ表示される内容』の記述方法で設定する必要があります

<% if:page_name eq 'archive' -%>
アーカイブページでのみ表示される内容
<% /if %>

<% if:page_name eq 'category' -%>
カテゴリページでのみ表示される内容
<% /if %>

<% if:page_name eq 'tag' -%>
タグページでのみ表示される内容
<% /if %>
この記述は、以下の場所で使用します


Windows
container 終わり

フリーフォントで簡単ロゴ作成
フリーフォントでボタン素材作成
フリーフォントで吹き出し画像作成
フリーフォントではんこ画像作成
ほぼ自由に利用できるフリーフォント
フリーフォントの書体見本とサンプル
画像を大きく見る為のウインドウを開くボタンの作成

Android SDK ポケットリファレンス
改訂版 Webデザイナーのための jQuery入門
今すぐ使えるかんたん ホームページ HTML&CSS入門
CSS ドロップシャドウの参考デモ
PHP正規表現チェッカー
Google Hosted Libraries
cdnjs
BUTTONS (CSS でボタン)
イラストAC
ぱくたそ
写真素材 足成
フリーフォント一覧
utf8 文字ツール
右サイド 終わり
base 終わり