JavaScript implementation of the picture 3D display Space (3DRoom) _javascript tips

Source: Internet
Author: User
Tags constant cos sin
The program is to simulate such a three-dimensional space, inside the picture will be based on three-dimensional coordinates displayed in this space.
I've seen a 3DRoom effect a long time ago, it's done with complex computations.
After the previous image transformation studied CSS3 's transform, a simpler way was realized.
Compatible: IE6/7/8, Firefox 3.6.8, opera 10.6, Safari 5.0.1, Chrome 5.0

Effect Preview

3DRoom

Program Description

"Principle of implementation"

The key to 3D effect is the realization of depth.
The 3D container is viewed as a space consisting of layers of different depths, which default to the container.
Layer inside the depth of the picture, and each layer will be based on the depth of the change to do scaling transformation, from the visual depth of the difference.
The scaling transformation is proportional to the nearest point of 1, the farthest point is 0, and gradually changes.
The key place is that the dimensions and coordinates of the picture in the layer must be transformed at the same time as the layer, which is very simple to achieve through the CSS3 transform.
Such a picture only need to set a good size and then the relative level of the line, to avoid the changes with the depth of the picture size and positioning of the trouble to constantly adjust.


"Picture Load"

After the program is initialized, you can call the Add method to add the picture.
The Add method has two parameters: a picture address and a Parameter object, and a picture action object is returned.
The Action object contains the following properties and methods to facilitate the operation of the picture:
IMG: Picture elements
SRC: Picture Address
Options: Parameter objects
Show: Display picture methods
Remove: Removing picture methods
Where options can set the following properties:
Properties: Default value//description
x:0,//Horizontal Displacement
y:0,//Vertical Displacement
z:0,//depth
width:0,//width
height:0,//height
scalew:1,//Width Scaling ratio
scaleh:1//Height Scaling ratio
where x, y are horizontal and vertical coordinates of the displacement parameters, coordinate the origin of the container at the bottom of the middle, horizontal coordinates to the right, ordinate upward, the unit is PX.
And z is the depth, the calculation of the scale, the direction from the near point to the origin point.
The coordinate system is shown below:


After the picture has been successfully loaded, the _load picture loader is executed.
First set the picture style according to the parameters:

Copy Code code as follows:

Img.style.cssText = "Position:absolute;border:0;padding:0;margin:0;-ms-interpolation-mode:nearest-neighbor;"
+ "Z-index:" + (99999-z) + "; width:" + width + "px;height:" + height + "px;"
+ "Left:" + (((clientwidth-width)/2 + opt.x)/clientwidth *). toFixed (5) + "%;"
+ "Top:" + ((CLIENTHEIGHT-HEIGHT-OPT.Y)/clientheight *). toFixed (5) + "%;";

Absolute positioning is required, and the width and height are set according to the parameters.
Left and top are calculated in terms of the coordinate parameters, which need to be expressed as percentages, followed by a detailed description.
Also add a _z attribute record depth to the picture for easy invocation.
Finally, the layer that corresponds to Z is inserted, and the layer is displayed again.


"Layer Transformation"

After the picture is loaded, the picture is inserted into the corresponding layer using the _insertlayer program.
_insertlayer has two parameters: Picture element and Z depth.
The program uses the _layers object to record the corresponding layer element with Z as the keyword.
If the layer has not yet been created at this depth, one is automatically created:

Copy Code code as follows:

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;";

The coordinates and dimensions of the layer are consistent with the container, because the coordinates of the inserted picture are defined relative to the container, which is convenient to use.
A _count property is added, the number of pictures that the record layer contains, and finally inserted into the container and recorded in the _layers object.
After you get the Layer object, insert the picture into the layer and add the _count count to 1.

You can then display the corresponding layer based on the depth of the _showlayer program.
The program contains three coordinate properties: _x, _y, _z, representing the offset of the container's three-dimensional coordinates.
First, the scaling scale of z depth is obtained by _getscale the proportional method.
The ratio is greater than 1, indicating that the image behind the visual depth, theoretically should not see, so hidden, less than 0, is too small to see also hidden.

The _x and _y offsets also need to be recalculated based on depth, and there are two ways in which programs can be offset: a far-point fix and a near-point fix.
A far-point fixed meaning is that the displacement of the plane shift with the depth gradually smaller, resulting in the furthest point for the fixed point of moving direction of the effect, near-point fixation is just the opposite.
To achieve this effect, as long as the displacement offset also follow the proportional change on the line, that is, far-point fixed offset is proportional to the ratio, far-point fixed is inversely proportional:

Copy Code code as follows:

var Movescale = This.fixedfar? Scale: (1-scale);

These parameters are then presented to the _show Program for processing and display effects.

In order to maximize the use of layer elements, the program will be in the _remove picture removal program, the layer of no picture into the _invalid waste layer collection, when the need to insert layer, priority from the _invalid to obtain.


"Zoom ratio"

As has been said above, the scaling should be based on the nearest point of 1, the farthest point of 0, gradually change.
The program is calculated by default by using the following formula:

function (z) { return 1 - z / 1000;}

But with this formula to achieve 3DRoom effect, you will find that the proportion of change is too rapid, not as stable as this 3DRoom.

After studying the code, it turns out that the formula used is this:

This. R = fl / (fl + (z * z));

where FL and z are a constant, that is, the formula can be expressed as:

function(z) { return 1/(1+z/ constant);}

According to this formula, the depth is 0 o'clock, the ratio is 1, the depth is constant when the ratio is 0.5, and the depth is infinity when the ratio is 0.

The change effect can refer to the following program:

<div id= "Idchart" ></div> formula: <input id= "Idformula" type= "text"/> <input id= "Idfrun" value= "Execute" typ e= "button"/> <input id= "idfclear" value= "clear" type= "button"/> <input id= "Idfdefault" value= "Default formula" Type= " Button "/> <input id=" idf3droom value= "3DRoom formula" type= "button"/> <script> (function () {var $$ = Functio N (ID) {return document.getElementById (ID)}, FML = $$ ("Idformula"); function Chart () {try{var a = [], left, top, fun = function (z) {return eval (fml.value);}; for (var i = 0; i < a i++) {left = (i-1), top = Math.ceil ((1-fun (i)) *200); A.push (' <div + Left + ' px;top: ' + top + ' px; " ><\/div> '); } a.push (' <div + (top-20) + ' px; " > ' + fml.value + ' <\/div> ', ' <div >0<\/div> ', ' <div >1<\/div> ', ' <div >550<\/ Div> '); $$ ("Idchart"). InnerHTML + = A.join (""); }catch (e) {alert ("Formula Error")}} $$ ("Idfdefault"). onclick = function () {fml.value = "1-z/550"; Chart (); }$$ ("Idf3droom"). onclick = function () {fml.value = "1/(1+z/100)"; Chart (); } $$ ("Idfrun"). onclick = Chart; $$ ("Idfclear"). onclick = function () {$$ ("Idchart"). InnerHTML = "";}}) () </script>
[Ctrl + A All SELECT Note: If the need to introduce external JS need to refresh to perform]

As you can see, the scaling in the default formula is uniform change, and the 3DRoom formula is first fast and slow, and is gradually slow, so there is that kind of smooth feeling.
In practice, you can design the appropriate formula for yourself, as long as it matches the change between 1 and 0.


"CSS3 Mode"

There are three types of scaling transformations in the program: CSS3, Zoom, and base, and the program structure of the pattern is similar to the one in the previous article.
The purpose of the scaling transformation is to display the scaling effect and achieve the final 3D effect, based on the ratio and position offset passed over.

The CSS3 mode uses the CSS3 transform, which has been introduced in the previous article to zoom and rotate with the transform matrix, which requires two more parameters to do position conversion.
The following two parameters should pay attention to the unit settings, in the MDC's-moz-transform have instructions:
Gecko (Firefox) accepts a <length> value for TX and Ty.
Safari (WebKit) and Opera currently support a unitless <number> for Tx and Ty.
It means that the displacement parameters tx and Ty are required in Firefox, while WebKit and opera only need numbers (without units, default px).
The program sets the unit according to the browser.

Using the CSS3 mode, you can also rotate by modifying the _r radians property.
Finally, The matrix implementation transformation is set:

Copy Code code as follows:

layer.style[Css3transform] = "Matrix ("
+ (Cos * scale). toFixed (5) + "," + (Sin * scale). toFixed (5) + ","
+ (-sin * scale). toFixed (5) + "," + (Cos * scale). toFixed (5) + ","
+ Math.Round (x) + unit + "," + math.round (y) + unit + ")";

Here also pay attention to a problem, the calculated ratio may be a very long decimal, in the spelling of the problem.
For example: Alert (0.0000001), will get "1e-7", JS will use this result to spell characters, get the wrong result.
So in the concatenation of the number and character, can be used integer should first turn into an integer, decimal words also need to use tofixed conversion.


"Zoom Mode"

IE does not yet support transform, but there is a zoom style that can achieve similar results.
Because the dimensions change after zoom, you need to fix left and top moves to the correct location.

In addition to Ie,webkit (Chrome/safari), Zoom is supported, but IE6/7, IE8 and WebKit implementations are not exactly the same.
Test the following code:

Copy Code code as follows:

<style>
. inner{width:100px; height:100px position:absolute; background: #0CF; zoom:0.5; top:50px; left:50px;}
. Inner div{width:50px height:50px;position:absolute; Left:25px;background: #CCC;}
</style>
<div style= "width:150px;height:150px; border:1px solid #000; position:relative; " >
<div class= "inner" id= "T" ><div>test</div></div>
</div>

The desired effect was achieved in IE6/7, but the location shown in WebKit was wrong.
The reason is that when you use zoom, the left and top of the element will also scale, so just recalculate it proportionally.
As in the example above, just change left and top to 50/0.5, or 100 is correct.

IE8 is even more troublesome, the contents of which are scaled by zoom, but left and top are still the same size.
Plagued by this problem for a long time, finally found that by using a percentage positioning can be resolved, when the picture load left and top to use the percentage is the reason.
For example, in the example, fix left and top, and change the innermost div to 25%.
In IE8 also see a problem, after zoom, the content is reduced, the container and the internal elements of the size has not changed, fortunately this will not affect the image of the display, positioning also use left and top, so as to avoid trouble.
Also, if the size of the zoom element is set as a percentage, the size of the element is not scaled according to the zoom.

There is also a problem to be noted in the calculation, which mentions that the WebKit and ie8,left and top need to be corrected by dividing scale, and when the scale is close to 0 to a certain extent, the result becomes infinity (infinity).
Using infinity to perform an operation can be an error, and you need to fix this problem:

Left = math.min (max, Math.max ( -Max, left)) | 0;
Top = math.min (max, Math.max ( -max, top)) | 0;

Where Max is Number.MAX_VALUE (the maximum number of JS can express).


"Base Mode"

There is also a base mode that is compatible with all browsers, using the traditional method of calculating and setting the size and position of each picture according to the scaling ratio.
Each time the display, the picture inside the layer, and then calculate the settings.
The calculation requires the original position and size of the picture, and the data is saved in the _original property on the first calculation:

var original = img._original = img._original | |  {
Width:img.offsetWidth, Height:img.offsetHeight,
Left:img.offsetLeft, Top:img.offsetTop
};

Size as long as the scale on the line, the position in addition to the calculation of the relative level of the scaling and the relative container displacement, this is the same as the calculation of the zoom mode.
Once you understand how layers change, it's not difficult to understand this.


"ZIndex"

Depth in addition to scaling and positioning, but also need reasonable front and rear cover.
The front and back cover needs to be implemented with ZIndex, which can be set on the picture or layer.
First, the easiest way to do this is to set up on the layer:

Copy Code code as follows:

<style>
div,img{width:200px;height:200px;position:absolute;left:0;top:0;}
img{width:150px;height:150px;}
</style>
<div style= "z-index:300;" >
)
</div>
<div style= "Z-INDEX:100;" >

</div>

Achieve a general 3D effect can be set this way.
But the click Test, in front of FF and WebKit can trigger behind, and IE and opera can be triggered before and after.
PS: If the IMG changed to Div, then ie and opera behind the elements can not trigger, the reason is not clear.
In this way, you can't set zindex at the layer if you want to trigger a picture event like 3DRoom.
You can also set on the picture:

Copy Code code as follows:

<style>
div,img{width:200px;height:200px;position:absolute;left:0;top:0;}
img{width:150px;height:150px;}
</style>
<div>

</div>
<div>

</div>

This image in all browsers can trigger the normal, but in the IE6/7 cascade effect is ineffective, it seems in the IE6/7 can only be used in the layer zindex.
There is also a problem, if the DIV plus transform effect:
Div{-moz-transform:scale (1);-webkit-transform:scale (1);-o-transform:scale (1);}
The image of the zindex will be invalidated, the CSS3 mode can only be set in the layer zindex.

To sum up:
In CSS3 mode it is certain to set the zindex at the layer, but the picture does not trigger the event.
In zoom and base mode, you should set the ZIndex in the picture, but in IE6/7 you will set it at the layer.
This is normal for at least the base mode cascade and picture trigger events.


"Msinterpolationmode"

Start to do, the effect under IE8 will be very card, but this 3DRoom will not card, and finally found that the use of-ms-interpolation-mode.
This thing was seen in Aoao's article, but I didn't think it could be used here.

An introduction to Msinterpolationmode is available on MSDN:
Gets or sets the interpolation (resampling) method is used to stretch images.
Gets or sets the interpolation (resampling) method used to stretch the image.
It has two values:
Nearest-neighbor: Use nearest neighbor interpolation mode.
Bicubic: Use high quality dual three times interpolation mode.
These nouns are more professional, as long as we know that the use of Nearest-neighbor efficiency, but the effect is poor, and bicubic effect of good efficiency is low enough.
The program set it to Nearest-neighbor to improve efficiency so that it won't be stuck in the IE8.


"Drag direction transform/wheel depth transform"

The program expands the drag visual transformation and the wheel depth transformation.
The practice of dragging and scrolling is similar to the previous one, where drag is the transformation to achieve the direction, and the scroll wheel is the transformation of the depth.
The move is done by modifying the _x and _y properties, and scaling is achieved by modifying the _z.
After modifying the property, call the Show method to display the effect.


Use Tips

"3DRoom"

In the 3DRoom effect, the CSS3 mode cannot be used because of the triggering event of the picture, because of the cascading problem mentioned above.
It also mentions that the size of the element that is zoom in the IE8 will not change, causing the trigger range to be wrong, so there is no zoom mode.
Using the base mode will not be a problem.

When you click on the picture, the vision moves to the picture, which is done by clicking on the picture and modifying the _x/_y/_z according to its own three-dimensional parameters:

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


Picture in MouseOver will display a border, in order to allow the picture to add a border after no displacement, add a " -1px" of the margin,mouseout and then removed.
Here 3DRoom and the effect of the reference is still a gap, this article is mainly on the implementation of 3D effect and research.

"Mode Selection"

CSS3 mode stability, most browsers are supported, in addition to IE.
Zoom mode compatibility is not good, but IE support.
Base is the slowest, but the compatibility is good, and there are no bugs.
In general, priority should be given to the use of CSS3 mode, then zoom, and finally base, but a situation like 3DRoom is actually chosen.
Design, IE is intended to use the matrix filter, but the development of some problems found in the efficiency is too low, do not consider.


Instructions for use

When instantiated, you must have a container as an argument:

var i3d = new Image3d (container, options);

Then call the I3d method to add the picture:

I3d.add (src, options);


Optional parameters are used to set the default properties of the system, including:
Properties: Default value//description
Mode: "Css3|zoom|base",//pattern
x:0,//Horizontal Offset value
y:0,//Vertical Offset value
z:0,//Depth Offset value
r:0,//Rotation angle (CSS3 support)
Whether the fixedfar:false,//is far fixed.
Getscale:function (z) {return 1-z/1000;},//Get Scaling method
Onerror:function (Err) {}//when errors occur

An optional parameter to the Add method is described in the picture load.

The following methods are also available:
Add: adding pictures;
Show: Display effect;
Reset: Resets the default state;
Dispose: Destroy the program.

After adding a drag direction transformation or a wheel depth transformation extension, you can define the transformation scope by setting the related parameters.

Package Download Address http://demo.jb51.net/js/Image3D/index.htm
Demo Address/201010/yuanma/image3d.rar

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.