ホームページ  >  記事  >  ウェブフロントエンド  >  JavaScript_javascriptスキルで実現した映像3D表示空間(3DRoom)

JavaScript_javascriptスキルで実現した映像3D表示空間(3DRoom)

WBOY
WBOYオリジナル
2016-05-16 18:18:481351ブラウズ

プログラムはそのような 3 次元空間をシミュレートし、内部の画像は 3 次元座標に従ってこの空間に表示されます。
私は昔、複雑な計算を使用して実現された 3DRoom エフェクトを見ました。
前の記事 画像変換 で CSS3 変換を学習した後、それを実装するより簡単な方法を考えました。
互換性: ie6/7/8、firefox 3.6.8、opera 10.6、safari 5.0.1、chrome 5.0

エフェクトプレビュー
JavaScript_javascriptスキルで実現した映像3D表示空間(3DRoom)
3DRoom
JavaScript_javascriptスキルで実現した映像3D表示空間(3DRoom)
手順の説明

【実施原理】

3D 効果の鍵は、奥行きの実現です。
3D コンテナは、深さが異なる複数のレイヤーで構成される空間として考えてください。これらのレイヤーの寸法は、デフォルトではコンテナと同じです。
深度の画像がレイヤーに配置され、各レイヤーは深度の変化に応じて拡大縮小および変形され、視覚的な深度の違いが生じます。
スケーリング変換の比率は、最も近い点を 1、最も遠い点を 0 として徐々に変化します。
重要な点は、レイヤー内の画像のサイズと座標をレイヤーと同時に変換する必要があるということです。これは CSS3 変換によって簡単に実現できます。
この方法では、画像のサイズを設定し、レイヤーとの相対的な位置を設定するだけで済み、深度の変化に応じて画像のサイズと位置を常に調整する手間が省けます。


【画像読み込み】

プログラムが初期化された後、add メソッドを呼び出して画像を追加できます。
add メソッドには、イメージ アドレスとパラメーター オブジェクトの 2 つのパラメーターがあり、イメージ操作オブジェクトも返します。
操作オブジェクトには、ピクチャの操作を容易にする次の属性とメソッドが含まれています:
img: ピクチャ要素
src: ピクチャアドレス
options: パラメータオブジェクト
show: 表示ピクチャメソッド
remove : 画像を削除するメソッド
オプションで次の属性を設定できます:
属性: デフォルト値 // 説明
x: 0, // 水平方向の変位
y: 0, // 垂直方向の変位
z: 0,//Depth
width: 0,//Width
height: 0,//Height
scaleW: 1,//幅スケーリング
scaleH: 1//高さスケーリング
このうち、x と y はそれぞれ水平座標と垂直座標の変位パラメータであり、座標原点はコンテナの底面中央、水平座標は右、垂直座標は上になります。単位はピクセルです。
Z はスケールの計算に使用される深さであり、方向は近点から原点に向かう方向です。
座標系は次のとおりです。


画像が正常に読み込まれた後、_load 画像読み込みプログラムが実行されます。
まずパラメータに従って画像スタイルを設定します:

コードをコピーします コードは次のとおりです:

img.style.cssText = "position:absolute;border:0;padding:0;margin:0;-ms-interpolation-mode:nearest-neighbor;" :" (99999 - z) ";width:" width "px;height:" height "px;"
"left:" (((clientWidth - width) / 2 opt.x) / clientWidth * JavaScript_javascriptスキルで実現した映像3D表示空間(3DRoom))。 toFixed(5) "%; "
"top:" ((clientHeight - height - opt.y) / clientHeight * JavaScript_javascriptスキルで実現した映像3D表示空間(3DRoom)).toFixed(5) "%;";
絶対位置決めが必要で、幅と高さはパラメータに従って設定できます。
左と上は座標パラメータに基づいて計算され、パーセント形式で表現する必要があります。これについては後で詳しく説明します。
簡単に呼び出せるように、画像に _z 属性を追加して深度を記録します。
最後にzに対応するレイヤーを挿入し、レイヤーを再表示します。




【レイヤー変換】


画像が読み込まれた後、_insertLayer プログラムを使用して画像を対応するレイヤーに挿入します。 _insertLayer には、画像要素と Z 深度の 2 つのパラメーターがあります。 プログラムは _layers オブジェクトを使用して、z をキーワードとして対応するレイヤー要素を記録します。

この深度でレイヤーが作成されていない場合は、自動的に作成されます:





コードをコピーします
コードは次のとおりです。 layer = document.createElement("div"); layer.style.cssText = "position:absolute;border:0;padding:0;margin: 0;left:0;top :0;visibility:hidden;background:transparent;width:" this._clientWidth "px;height:" this._clientHeight "px;";

挿入された画像の座標はコンテナを基準にして定義され、より使いやすくなるため、レイヤーの座標とサイズはコンテナと一致している必要があります。
レイヤーに含まれる画像の数を記録するために _count 属性も追加され、最終的にコンテナーに挿入されて _layers オブジェクトに記録されます。
レイヤーオブジェクトを取得したら、レイヤーに画像を挿入し、_countに1を加えます。

その後、_showLayer プログラムを使用して、深さに応じて対応するレイヤーを表示できます。
プログラムには、コンテナの 3 次元座標のオフセットを表す 3 つの座標属性 _x、_y、_z が含まれています。
まず、_getScale メソッドを通じて Z 深度のスケールを取得します。
比率が 1 より大きい場合、画像は視覚的な奥行きの背後にあり、理論的には表示されないことを意味します。そのため、0 より小さい場合は、小さすぎて見えないことを意味します。隠されています。

_x オフセットと _y オフセットも深度に基づいて再計算する必要があります。プログラムには、遠点固定と近点固定の 2 つのオフセット方法があります。
遠点固定は、平面変位オフセットが深度に応じて徐々に小さくなることを意味し、その結果、最も遠い点を固定点の移動方向として使用する効果が得られます。
この効果を実現するには、変位オフセットも比例に応じて変化する限り、つまり、遠い点が固定されている場合、オフセットはその比率に比例し、遠い点が固定されている場合、オフセットは反比例します。 :

コードをコピー コードは次のとおりです:

var moveScale = this。 fixFar ?scale : (1 -scale);

次に、これらのパラメータを _show プログラムに渡して処理し、効果を表示します。

レイヤー要素を最大限に活用するために、プログラムは、画像のないレイヤーを _remove 画像削除プログラムの _invalid 破棄レイヤー コレクションに置きます。レイヤーを挿入する必要がある場合、最初に _invalid から取得されます。


【スケール比率】

上で述べたように、スケーリング率は最も近い点を 1、最も遠い点を 0 として徐々に変化する必要があります。
プログラムはデフォルトで次の式に基づいて計算します:

function(z){ return 1 - z / JavaScript_javascriptスキルで実現した映像3D表示空間(3DRoom)0 }
;

しかし、この公式を使用して 3DRoom 効果を実現すると、比率の変化が速すぎて、この 3DRoom ほど滑らかではないことがわかります。

コードを調べた結果、使用されている式は次のとおりであることがわかりました。

this.r = FL / (FL (z * Z));

ここで、FL と Z は定数です。つまり、式は次のように表すことができます。

関数(z){ return 1/ (1 z/ 定数) }

この式によれば、深さが0の場合はスケールが1、深さが一定の場合はスケールが0.5、深さが無限大の場合はスケールが0となります。

エフェクトを変更するには、次の手順を参照できます:


[Ctrl A すべて選択 注: 外部 Js を導入する必要がある場合は、更新して実行する必要があります
]

ご覧のとおり、拡大率がデフォルトの式では均等に変化しますが、3DRoom 式では最初は速く、次に遅くなり、徐々に遅くなるため、滑らかな感触になります。 実際の状況に応じて、1 と 0 の間で変化する限り、適切な数式を自分で設計することもできます。


[css3 モード]


プログラムには 3 つのズーム変換メソッドがあります: css3、zoom、base モードのプログラム構造は前のものと似ています。

スケーリング変換の目的は、渡された比率と位置オフセットに基づいてスケーリング効果を表示し、最終的な 3D 効果を実現することです。


css3 モードでは、CSS3 変換を使用します。前回の記事では、スケーリングと回転に変換行列を使用することを紹介しました。今回は、位置変換に次の 2 つのパラメーターも必要です。 最後の 2 つのパラメータの単位の設定に注意してください。これについては MDC の -moz-transform
で説明されています。
Gecko (Firefox) は tx と
値を受け入れます。 ty.
Safari (WebKit) と Opera は現在、tx と ty に対して単位のない をサポートしています。

これは、Firefox ではディスプレイスメント パラメータ tx と ty に単位が必要であることを意味しますが、WebKit と Opera では数値のみが必要です。 (単位なし、デフォルトのピクセル)。

プログラムはブラウザに従って単位を設定します。

css3 モードを使用すると、_r arc 属性を変更して回転することもできます。

最後に、変換を実装する行列を設定します: コードをコピーします
コードは次のとおりです:


layer.style [ css3Transform ] = "matrix("
( Cos * スケール).toFixed(5) "," (Sin * スケール).toFixed(5) ","
(-Sin * スケール).toFixed(5 ) "," (Cos * スケール).toFixed(5) ", "
Math.round(x) 単位 ", " Math.round(y) 単位 ")"; >

ここで注意すべきもう 1 つの問題があります。計算された比率は非常に長い小数になる可能性があり、文字のスペルに問題が発生します。
たとえば、alert(0.0000001) を実行すると、JS はこの結果を使用して文字を綴り、間違った結果を取得します。 したがって、数字と文字を結合するときは、整数を使用できるものを最初に整数に変換し、小数も toFixed を使用して変換する必要があります。


【ズームモード】


IE はまだ変換をサポートしていませんが、同様の効果を実現できるズーム スタイルがあります。

ズームすると大きさが変わってしまうので、左右の動きを正しい位置に修正する必要があります。


ie に加えて、webkit (chrome/safari) もズームをサポートしていますが、ie6/7、ie8 と webkit の実装はまったく同じではありません。 幅:JavaScript_javascriptスキルで実現した映像3D表示空間(3DRoom)px;高さ:JavaScript_javascriptスキルで実現した映像3D表示空間(3DRoom)px;位置:#0CF;左:50px; ; 高さ:50px;位置:絶対;左:25px;背景:#CCC;}

test

ie6/7 では期待通りの効果が得られますが、Webkit で表示される位置が間違っています。
その理由は、ズームを使用した後、要素の左と上も拡大縮小されるため、比率に従って再計算するだけで済みます。
上の例のように、左と上を 50/0.5、つまり JavaScript_javascriptスキルで実現した映像3D表示空間(3DRoom) に変更するだけで正しくなります。

ie8 はさらに厄介です。内部のコンテンツはズームに応じて拡大縮小されますが、左と上は元のサイズのままです。
私は長い間この問題に悩まされてきましたが、最終的にパーセンテージの配置を使用することで解決できることがわかりました。これが、画像をロードするときに左と上にパーセンテージを使用する理由です。
たとえば、この例では、左と上を変更し、最も内側の div の左を 25% に変更するだけです。
IE8 でも問題が発生しました。ズーム後、コンテンツは縮小されましたが、幸いなことに、これは画像の表示には影響しませんでした。位置決めに困らないように上部と。
また、ズーム要素のサイズがパーセンテージで設定されている場合、要素のサイズはズームに応じて拡大縮小されません。

計算する際の注意点がもう一つありますが、webkitやie8では、スケールがある程度0に近づくと、左と上をスケールで割って補正する必要があります。インフィニティ(無限大)。
Infinity を使用して操作を実行するとエラーが発生します:

この問題は修正する必要があります。
left = Math.min(MAX, Math.max( -MAX, left )) | 0;
top
= Math.min(MAX, Math. max(-MAX, トップ )) | 0;

ここで、MAX は Number.MAX_VALUE (js が表現できる最大数) です。


【基本モード】

従来の方法、つまり拡大縮小率に基づいて各画像のサイズと位置を計算して設定する、すべてのブラウザーと互換性のある基本モードもあります。
表示されるたびに、レイヤー内の画像が走査され、設定が 1 つずつ計算されます。
計算には画像の元の位置とサイズが必要です。最初の計算では、データは _original 属性に保存されます:

var オリジナル = img._original = img._original || {
幅: img.offsetWidth、高さ: img.offsetHeight、
左: img.offsetLeft、上: img.offsetTop
};

相対的なレイヤーのスケーリングを計算することに加えて、サイズをスケールするだけで済みます。これは、ズーム モードでの計算と同じです。
レイヤー変換の方法を理解すれば、これを理解することは難しくありません。


[zIndex]

拡大縮小と位置決めに加えて、深さには適切な前後のカバーも必要です。
前面と背面のマスキングは、画像またはレイヤーに設定できる
zIndex を使用して実装する必要があります。
最初の最も簡単な方法は、レイヤーに設定することです:

コードをコピーします コードは次のとおりです:



JavaScript_javascriptスキルで実現した映像3D表示空間(3DRoom)

JavaScript_javascriptスキルで実現した映像3D表示空間(3DRoom)



一般的な 3D 効果を実現するには、次のように設定できます。
しかし、テストをクリックすると、ff と webkit の前のものはトリガーできますが、後ろのものはトリガーできません。一方、ie と opera は前後の両方でトリガーできます。
追記: img を div に置き換えると、ie と opera の背後にある要素をトリガーできません。理由はまだ不明です。
このように、3DRoomのような画像イベントをトリガーしたい場合、レイヤーにzIndexを設定することはできません。
画像に設定することもできます:

コードをコピーします コードは次のとおりです:



JavaScript_javascriptスキルで実現した映像3D表示空間(3DRoom)


JavaScript_javascriptスキルで実現した映像3D表示空間(3DRoom)

这样图片在所有浏览器都能正常触发,但在ie6/7层叠的效果失效了,看来在ie6/7只能在层用zIndex。
还有一个问题,如果给div加上变换效果:
div{-moz-transform:scale(1);-webkit-transform:scale(1);-o-transform:scale(1);}
那图片上的zIndex就会失效,那css3模式就只能在层设置zIndex了。

总结一下:
在css3模式肯定要在层设置zIndex,但图片也不能触发事件。
在zoom和base模式,应该在图片设置zIndex,但在ie6/7就要在层设置。
这样至少在base模式层叠和图片触发事件都是正常的。


【msInterpolationMode】

开始做的时候,效果在ie8下会很卡,但这个3DRoom却不会卡,最后发现是使用了-ms-interpolation-mode。
这个东西在aoao的文章中看过,但没想到可以用在这里。

在MSDN有msInterpolationMode的介绍:
Gets or sets the interpolation (resampling) method used to stretch images.
即获取或设置用于拉伸图像的插值(重采样)方法。
它有两个值:
nearest-neighbor:使用近邻插值模式。
bicubic:使用高品质的双三次插值模式。
这些名词比较专业,我们只要知道使用nearest-neighbor效率高但效果差,而bicubic效果好效率低就够了。
程序把它设为nearest-neighbor提高效率,这样在ie8中也不会卡了。


【拖动方向变换/滚轮深度变换】

程序扩展了拖动视觉变换和滚轮深度变换。
拖动和滚动的做法跟上一个的做法差不多,这里拖动是实现方向的变换,滚轮是实现深度的变换。
移动是通过修改_x和_y属性来实现,缩放是通过修改_z来实现。
修改属性之后再调用show方法显示效果。


使用技巧

【3DRoom】

在3DRoom效果中,因为要实现图片的触发事件,所以不能用css3模式,原因是上面提到的层叠问题。
上面也提到在ie8被zoom的元素尺寸不会改变,导致触发范围错误,所以也不用zoom模式。
使用base模式就不会有问题了。

在点击图片时,视觉会移动到图片上面,这个通过点击图片后根据本身的三维参数修改_x/_y/_z来实现:

img.onclick = function(){
    i3D._z 
= -options.z | 0;
    i3D._x 
= -options.x | 0;
    i3D._y 
= options.y | 0;
    i3D.show();
}


The picture will display a border when mouseover. In order to prevent the picture from being displaced after adding a border, a "-1px" margin is added and removed when mouseout.
There is still a gap between the effects of 3DRoom and the reference here. This article is mainly about the implementation and research of 3D effects.

【Mode Selection】

CSS3 mode is stable and supported by most browsers except IE.
Zoom mode has poor compatibility, but IE supports it.
base is the slowest, but has good compatibility and no bugs.
Generally, css3 mode should be used first, then zoom, and finally base. However, in cases like 3DRoom, the actual choice must be made.
When designing, IE planned to use Matrix filters, but some problems were discovered during development and the efficiency was too low, so it was not considered.


Instructions for use

When instantiating, there must be a container as a parameter:

var i3D = new Image3D( container , options );

Then call the i3D method to add the image:

i3D.add( src, options );


Optional parameters are used to set the default attributes of the system, including:
Attribute: Default value // Description
mode: "css3|zoom|base", //Mode
x: 0,//Horizontal offset value
y: 0,//Vertical offset value
z: 0,//Depth offset value
r: 0,//Rotation angle (css3 support)
fixedFar: false,//Whether the far point is fixed
getScale: function(z){ return 1 - z / JavaScript_javascriptスキルで実現した映像3D表示空間(3DRoom)0; },//Get the scale method
onError: function(err){}//Error Execute when

The optional parameters of the add method have been explained in image loading.

also provides the following methods:
add: add pictures;
show: display effects;
reset: reset the default state;
dispose: destroy the program.

After adding the drag direction transformation or wheel depth transformation extension, the transformation range can be defined by setting relevant parameters.

Package download addresshttp://demo.jb51.net/js/Image3D/index.htm
Demo address/201010/yuanma/Image3D.rar

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。