3D "ELASTIC" layout based on HTML5 WebGL
Molecular force (molecular force), also known as the Inter-molecular force and Van devis force, refers to the interaction between molecules. When the two molecules are far apart, they are mainly attractive. This force is mainly derived from the interaction of one molecule due to the polarization of the polar moment of the other molecule that rapidly changes over time; when the molecules are very close, the exclusion force is the main factor, because the outer electron clouds of each molecule begin to overlap.
HT for Web provides the force-directed layout (also known as force-directed layout) function, that is, based on the mutual mutex between nodes, there is gravity between nodes connected to each other, after the elastic layout runs for a period of time, the overall topology network structure will gradually reach a stable and balanced state of convergence. This feature is very interesting. Today we will show its charm.
This example address: http://www.hightopo.com/demo/pipeline/index.html
The use of stretch layout function requires the introduction of ht. js core library, and then introduce a ht-forcelayout.js of stretch layout plug-in library, because the form is also used, so the introduction of ht-form.js form plug-in Library:
-
The ht. layout. Force3dLayout class provides a 3D elastic layout. The constructor can input two parameters: DataModel and Graph3dView. By default, only unselected elements are laid out. If the constructor parameter is Graph3dView, The isMovable and isVisible functions of the view component will affect the layout of elements, the layoutable attribute on the element style can also be set to false to prevent elements from participating in the layout.
After introducing the background of the HT package's elastic layout, the next step is to help you easily achieve this effect.
First, we define a color array variable to store the color of each elastic ball. We also define a random function to generate a random number of colors in the array:
- Var colorList = ['# FFAFA4', '# B887C5', '# b9ea9c',' # CFD9E7 ',' #4590B8 ',' # ff9c30'],
- ColorLen = colorList. length;
- Var randomColor = function (){
- Var ran = Math. random () * colorLen;
- Return colorList [Math. floor (ran)]; // random 6 colors
- };
Create an elastic ball and generate a 3D node. Set the style attribute of the node to control the display mode of the node. Set "shape3d" to "sphere" to ht. node into a 3D sphere model, and then set the "shape3d" attribute to the previously defined random color. s3 is short for the setSize3d function in HT encapsulation that sets the 3D Node size, finally, add the node to the data model dataModel:
- Var createNode = function (dm) {// create a node circle
- Var node = new ht. Node ();
- Node. s ({// set the style to the abbreviation of setStyle
- 'Shape3d ': 'sphere ',
- 'Shape3d. color': randomColor () // set random color });
- Node. s3 (40, 40, 40 );
- Dm. add (node); return node;
- };
Now there is a line between various stretch balls, which we think is very unusual at first glance. It is also through the construction of a node, this node is customized through the HT for Web modeling manual setShape3dModel function. default. based on the curve of the xy plane, the createRingModel wraps around the 3D Ring Model formed in a week and name it 'custom ':
- Ht. Default. setShape3dModel (// create a model based on the xy plane curve, forming a 3D model around a week. 'Custom ',
- Ht. Default. createRingModel ([0.5, 0.5,-0.2, 0, 0.5,-0.5], [1, 3])
- )
HT divides user-defined attributes and the default calling method of HT attributes into node. a and node. in this way, the two effective regions can be separated (for details, refer to the HT for Web getting started manual style). We used this method when creating pipelines:
- Var updatePipeline = function (edge) {// reset the edge style
- Var pipeline = edge. a ('pipeline ');
- Pipeline. s3 (1, 1, 1); // set the size of pipeline. p3 (0, 0, 0); // set the coordinates
- Var node1 = edge. getSourceAgent (), // obtain the starting node connected to the graph
- Node2 = edge. getTargetAgent (); // obtain the target node connected to the graph
- Pipeline. s ('Mat ', createMatrix (node1.p3 (), node2.p3 (), 20); // 3d overall graphic matrix change
- };
The most mysterious thing is how can we achieve the "instant transfer" effect for two nodes?
We know that a matrix can describe any linear transformation. Linear transformation retains the straight lines and parallel lines. While linear transformation retains the straight lines, other geometric properties such as length, angle, area, and volume may be changed. In short, linear transformation may "stretch" the coordinate system, but it will not "bend" or "roll" the coordinate system. This function is mainly used to operate the "change matrix" of the dropped connection line after dragging the elastic ball. The change matrix is also HT encapsulated. default. the createMatrix function sets the style attribute mat of a node as a custom function to multiply the coordinates of the node by the value corresponding to the mat attribute, that is to say, if the Rotation Angle of the current pipeline is [Math. PI/6, 0, 0]. Suppose we set r3 to [Math. PI/3, 0, 0], then the node will rotate 90 degrees. It is very easy to create a change matrix:
- Var createMatrix = function (p1, p2, width) {// createMatrix (array, matrix) converts scaling, moving, and rotating operations of a set of JSON descriptions into corresponding change matrices.
- Var vec = [p2 [0]-p1 [0], p2 [1]-p1 [1], p2 [2]-p1 [2],
- Dist = ht. Default. getDistance (p1, p2); // gets the distance between two points, or returns the vector length.
- Ht. Default. createMatrix ({
- S3: [width, dist, width],
- R3: [Math. PI/2-Math. asin (vec [1]/dist), Math. atan2 (vec [0], vec [2]), 0],
- RotationMode: 'xyz ',
- T3: [(p1 [0] + p2 [0])/2, (p1 [1] + p2 [1])/2, (p1 [2] + p2 [2])/2]
- });
- };
After all the basic accessories are defined, set the "shape3d" attribute to the custom 3D model "custom" and set the "layoutable" attribute to "false" to prevent elements from participating in the layout, and connect the points through edge. a ('pipeline', node) refresh and add it to the data model dataModel:
- Var createEdge = function (dm, node1, node2) {// create the edge of the 'custom' Model
- Var node = new ht. Node ();
- Node. s ({'shape3d ': 'custom ',
- 'Shape3d. color': '# ECE0D4', 'layoutable': false
- });
- Dm. add (node );
- Var edge = new ht. Edge (node1, node2 );
- Edge. a ('pipeline', node );
- Edge. s ('edge. color', 'rgba (0, 0, 0, 0 )');
- Dm. add (edge); return edge;
- };
Plug: We can also in the industry with HeatMap hot map on the article, the effect is still very dazzling, the specific address http://hightopo.com/guide/guide/plugin/forcelayout/examples/example_heatmap3d.html
After drawing all the images on the interface, only the form is left. First, add the form to the HTML page, using the HT. widget. FormPane function encapsulated by ht:
- Var formPane = new ht. widget. FormPane ();
- FormPane. setWidth (230 );
- FormPane. setHeight (125 );
- FormPane. addToDOM ();
Remember to set the width and height of the form, otherwise it will not be displayed.
To Add rows to a form, use the addRow function. We will focus on the following lines in the form: Color, Range, and Intensity. These three names are mainly used to control the "headlight. In HT, you can use the setHeadlightColor/setHeadlightRange/setHeadlightIntensity functions to control the color, range, and lamp intensity of the "headlight". The onValueChanged attribute triggers the event after the attribute value changes:
- ['Color', 'range', 'intensity ']. forEach (function (name ){
- Var obj = {id: name },
- Func = function (oV, nV ){
- G3d ['setheadlight' + name] (nV); // === g3d. setHeadlightColor (nV)/g3d. setHeadlightRange (nV)/g3d. setHeadlightIntensity (nV)
- };
- If (name = 'color ')
- Obj. colorPicker = {// ht. widget. ColorPicker: Color Selection box
- Instant: true,
- Value: g3d ['getheadlight' + name] (), // === g3d. getHeadlightColor ()
- OnValueChanged: func
- };
- Else
- Obj. slider = {// slider min: 0,
- Max: name = 'range '? 20000: 3,
- Step: 0.1,
- Value: g3d ['getheadlight' + name] (),
- OnValueChanged: func
- };
- FormPane. addRow ([name, obj], [70, 0.1]);
- });
Slider and colorPicker are HT-defined slide and color selector. for more information, see the HT for Web form manual.
If you still do not understand, please consult me, or you can go to the HT for Web official website to check the manual.