Thursday, September 23, 2010

JavaScript Photo 3D display space (3DRoom)

General plane effect, by changing the horizontal and vertical coordinates can be achieved, coupled with the depth, we can produce in visual 3D (three dimensional) effect.
Program is to simulate a three-dimensional space, which will be based on three-dimensional coordinates of the image displayed in this space.
Long ago saw a 3DRoom effect is achieved by complex calculations.
In the previous image transformation after studying css3 the transform to think of a more simple way to achieve.
Compatibility: ie6/7/8, firefox 3.6.8, opera 10.6, safari 5.0.1, chrome 5.0
Mid-Autumn Festival is approaching, I wish you Happy Mid-Autumn Festival, round and round!



Effect Preview


3DRoom

Description of the procedures
】 【Implementation principle
3D effects of the key is the realization of the depth.
The 3D container as a multi-layers at different depths of space, the size of these layers as the default with the container.
Layer which has a picture of the depth and the depth of each layer changes made under the scaling transformation, generated from the visual depth of difference.
Scaling transformation according to the ratio of the nearest point to 1, the farthest point to 0, and gradually change.
The key is the layer inside the image where the size and layer the same time coordinate transformation must be followed, this very simple by css3 the transform can be achieved.
This image size just set up a good bit longer given the relative level on the line, to avoid changes with depth to constantly adjust the picture size and positioning of trouble.

Loading】 【Picture
Initialized in the program, you can call the add method to add pictures.
add method takes two parameters: the address and parameters of the object image, the object will return an image operation.
Operation object contains properties and methods to facilitate the operation of the picture:
img: graphic elements
src: image Address
options: parameter object
show: display image method
remove: remove the image method which options you can set the following properties:
Attribute: The default value / / Description
x: 0, / / horizontal displacement
y: 0, / / vertical displacement
z: 0, / / depth
width: 0, / / width
height: 0, / / height
scaleW: 1, / / width scaling
scaleH: 1 / / height scaling where x, y are the horizontal and vertical coordinates of the displacement parameters of the coordinate origin in the middle bottom of the container, the level of coordinates to the right, the vertical axis upward, the unit is px.
And z is the depth, for the calculation of the proportion of direction from the near point to the origin.
Coordinate system as below:
photo

Image loading is successful, it will perform _load image loader.
First, according to the parameters set Picture Style: 
photophoto Code 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 * 100). ToFixed (5) + "%;" 
+ "Top:" + ((clientHeight - height - opt.y) / clientHeight * 100). ToFixed (5) + "%;";
Absolute positioning is required, the width and height according to the parameters set on the line.
left and top coordinates calculated based on, here expressed as a percentage of need, followed by further details.
Pictures should be given to increasing the depth of a _z property records to facilitate the call.
Finally, the layer into the corresponding z, and re-display the layer.

】 【Layer transformation
Image is loaded, the picture will be inserted with _insertLayer program to the corresponding layer.
_insertLayer two parameters: the picture elements and z depth.
Program with _layers objects to the corresponding z level recorded for the key element.
If the depth has not been created in the layer will automatically create a: 
photophoto Code 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; ";
Layer coordinates and keep up the container the same size as the picture into the container to define the relative coordinates, so more convenient to use.
_count Attribute will add a record number of pictures layer contains the last inserted into the container and recorded _layers object.
Access layer object, put the picture into layers, and to _count count plus 1.
Then they can display the corresponding _showLayer program based on the depth of the layer.
Program consists of three coordinates of properties: _x, _y, _z, three-dimensional coordinates of the container that the offset.
First of all proportion by _getScale obtained for the depth scale z scale.
Ratio greater than 1, indicating the depth of the back of the visual image, in theory, should not see, so hidden; less than 0, that is too small to see the hidden.
The _x and _y offsets need to be recalculated based on the depth of the program, there are two offset by: far point and near the fixed point fixed.
Far point means a fixed offset with depth plane displacement became smaller, resulting in a fixed point to the farthest point the effect of the direction of movement, a fixed near point to the opposite.
To achieve this effect, as long as the ratio of the displacement offset changes also followed on the line, that distant point with the proportion of fixed offset proportional to the inverse far point is fixed: 
var moveScale = this.fixedFar? scale: (1 - scale);

Then these parameters to _show to handle and display the results.
In order to maximize the use of layer elements, the program will remove the program in _remove pictures, no pictures of the layer into the waste layer _invalid collection, in the need to insert a layer, first obtain from the _invalid.

】 【Scaling
Has been said above, scaling should be based on the nearest point to 1, the farthest point to 0, and gradually change.
Program default is calculated by the following formula: 
function (z) (return 1 - z / 1000;)
But the effect of using this formula to achieve 3DRoom time, you will find the proportion of change is too rapid, not as the3DRoom as stable.
Of the code and found that it uses the original formula is this: 
this.r = FL / (FL + (z * Z));
Where FL and Z is a constant to, that formula can be expressed as:
function (z) (return 1 / (1 + z / constant);)
That according to this formula, the depth ratio of 0 to 1, when the ratio of constant depth of 0.5, a depth of infinity, the ratio of 0.
Change effects can refer to the following procedures:
Formula:

It can be seen, the scaling is uniform change in the default formula, but formula is 3DRoom slow down after the first, and gradually slow down, so have that smooth feeling.
That the actual, you can also design their own formula for as long as consistent with changes in the 1 to 0 on the line between.

Model】 【css3
There are three scaling transformation program mode: css3, zoom, and base, model to keep up with a similar program structure.
The purpose of scaling transformation is based on the proportion and location of the passed offset, the scaling effect of display, to achieve the final 3D effect.
css3 css3 mode using the transform, has been introduced in the previous transform the matrix to do with scaling and rotation, the two parameters need to do behind the location of transformation.
The last two parameters set the unit to note, in the MDC's -moz-transform has made it clear:
Gecko (Firefox) accepts a value for tx and ty. 
Safari (WebKit) and Opera currently support a unitless for tx and ty. 
Mean displacement parameters tx and ty, need to take units in Firefox, and WebKit and Opera only numbers (without units, the default px). 
Program units based on browser settings.
Use css3 mode, you can also modify the properties _r arc rotation.
Set to achieve the final transformation matrix: 
photophoto Code 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 + ")";

Also note that a problem here, the calculated ratio may be a long decimal character in the fight will go wrong.
For example, the implementation of: alert (0.0000001), will be "1e-7", js will use this result to fight the character, get the wrong results.
So do numbers and characters in the stitching, the can should be converted to integer integer, decimal, then speak with the toFixed convert it.

】 【Zoom mode
ie does not support transform, but there is a zoom style to achieve a similar effect.
The zoom, the size will change, so the need to amend the top left and move to the right place.
In addition ie, webkit (chrome / safari) also supports zoom, but ie6 / 7, ie8 and implementation of webkit is not the same.
Test the following code: 
photophoto Code 
. 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;) 



test
In ie6 / 7 to achieve the desired effect, but in webkit shows the location wrong.
The reason is to use zoom, the elements left and the top also with zoom, it would only re-calculated according to the proportion of the line.
Like the example above, as long as the left and the top into a 50/0.5, or 100 to correct.
ie8 even more trouble, which is based on the content of zoom zoom, but the left and the top is the original size.
Troubled by this problem for a long time, and eventually found by using a percentage of the positioning can be resolved, in pictures left and top to use when loading the percentage is for this reason.
For example, in example, the amendments left and top, and to the left innermost div 25% into it.
In ie8 also see a problem in zoom, the content is reduced, the size of the container and internal elements are not changed, but fortunately, this does not affect the display of images, positioning but also with the left and top, avoid trouble.
Also, if the zoom percentage size of the elements set the size of that element will not be scaled according to zoom.
Also note that in the calculation of a problem, mentioned above in webkit and ie8, left and top are divided by the scale needed to fix, when the scale is close to 0 to a certain extent, the result will become Infinity (infinity).
The operation go wrong with Infinity, 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 the Number.MAX_VALUE (js can express the maximum number.)

】 【Base model
There are all compatible browser base model, with the traditional methods that, according to scaling, calculate and set the size and location of each picture.
Each is displayed, the image inside the calendar all over the floor, and then one by one calculation settings.
Calculations require the original image position and size, will in the first calculation of data stored in the _original properties: 
var original = img._original = img._original | | ( 
width: img.offsetWidth, height: img.offsetHeight, 
left: img.offsetLeft, top: img.offsetTop 
);
According to scaling as long as the size of the line, in addition to calculate the relative position of the zoom layer plus the relative displacement of the container, the calculation with the zoom mode is the same.
Way to understand the transformation layer, and then not difficult to understand this.

】 【ZIndex
In addition to scaling and positioning of the depth, but also before and after a reasonable cover.
Need to cover before and after the zIndex to achieve, you can set the image or layer.
First, the easiest way is to set the layer: 
photophoto Code 
div, img (width: 200px; height: 200px; position: absolute; left: 0; top: 0;) 
img (width: 150px; height: 150px;) 



300



100
To achieve 3D effects can be generally set.
But the hit test, in ff and webkit behind the front will not trigger the trigger, but ie and opera on the front can be triggered.
ps: if the img into div, ie and opera it can not trigger the elements behind the reason is unclear.
Such as the trigger to imagine 3DRoom picture of events can not be in the layer, then set the zIndex.
You can also set the picture: 
photophoto Code 
div, img (width: 200px; height: 200px; position: absolute; left: 0; top: 0;) 
img (width: 150px; height: 150px;) 



300



100
This image can be normal in all browsers trigger, but in ie6 / 7 the effect of cascading failures, and seems ie6 / 7 can only be used in the layer zIndex.
There is also a problem, if a div with the transform:
div (-moz-transform: scale (1);-webkit-transform: scale (1);-o-transform: scale (1);)
ZIndex on the picture that will fail, and that css3 mode to set the zIndex of the only layer.
Summarize:
In css3 is sure to layer settings zIndex, but the picture can not trigger events.
In the zoom and the base model, it should be in the picture set zIndex, but in ie6 / 7 is necessary in the Layer.
This at least in the base model and the image trigger cascading events are normal.

】 【MsInterpolationMode
When started, the effect will be the next card in ie8, but this 3DRoom are not card, and finally found a use-ms-interpolation-mode.
This thing in aoao read the article, but did not think can be used here.
In the MSDN there msInterpolationMode description:
Gets or sets the interpolation (resampling) method used to stretch images.
That is used to stretch the image to get or set the interpolation (resampling) method.
It has two values:
nearest-neighbor: neighbor interpolation mode to use.
bicubic: the use of high-quality bicubic interpolation mode.
These terms more professional, we know that using the nearest-neighbor as long as the high efficiency but poor results, while the low efficiency of bicubic effective enough.
Program set it to improve the efficiency of nearest-neighbor, so that ie8 will not be in the cards.

【Drag direction transform / wheel depth of transformation】
Program extends the drag and wheel depth of transformation of visual transformation.
Drag and rolling practices to keep up with a similar approach, where the direction of drag is to achieve the transformation, the wheel is to realize the depth of the transformation.
Mobile is the _x and _y properties by modifying achieved, scaling is achieved by modifying _z.
Modify the show method is called after attributes display.

Tips
】 【3DRoom
In 3DRoom effect, because to achieve the picture of the trigger event, so can not use css3 model, because the cascading problems mentioned above.
The above mentioned elements in ie8 zoom size is not change, resulting in the trigger range error, so do not have to zoom mode.
Using the base model would not have a problem.
After clicking the image, the visual will move to the picture above, this post by clicking the image changes according to their own three-dimensional parameter _x / _y / _z to achieve:
img.onclick = function () ( 
i3D._z =-options.z | 0; 
i3D._x =-options.x | 0; 
i3D._y = options.y | 0; 
i3D.show (); 
)

Picture will display a mouseover border, in order to make the picture plus frame shift does not occur after, added a "-1px" the margin, mouseout again when removed.
3DRoom with reference to the effect here is a gap, this paper is the realization of 3D effects and research.
】 【Mode
css3 mode stability, and most browsers support, in addition to ie.
zoom mode compatibility is not good, but ie support.
the slowest base, but good compatibility, and there is no bug.
Under normal circumstances should be given priority to use css3 mode, then zoom, the last base, but would like 3DRoom situation as the actual choice.
Design time, ie is intended to use the Matrix filter, but some of the problems found in the development, efficient and low, is not taken into account.

Help
Instantiated, it must have the container as a parameter: 
var i3D = new Image3D (container, options);
Add a picture and then call i3D methods:
i3D.add (src, options);

Optional parameter used to set the system default properties, including:
Attribute: The default value / / Description
mode: "css3 | zoom | base", / / mode
x: 0, / / horizontal offset
y: 0, / / vertical offset
z: 0, / / depth migration values
r: 0, / / rotation angle (css3 support)
fixedFar: false, / / is far from fixed points
getScale: function (z) (return 1 - z / 1000;), / / get ratio method
onError: function (err ){}// implementation error
add optional parameter method has been loaded in the image description.
Also provides the following methods:
add: Add a picture;
show: display;
reset: Reset the default state;
dispose: destruction procedures.
Drag the scroll wheel added depth transform or change the direction of extension, the relevant parameters can be defined by setting the transformation range.

No comments:

Post a Comment