Molecular forces, also known as intermolecular forces or van der Waals forces, refer to the interactions between molecules. When two molecules are far away from each other, it is mainly manifested as attraction. This force mainly comes from the interaction caused by the polarization of one molecule by the electric dipole moment of the other molecule which changes rapidly with time. When the two molecules are very close together, repulsion becomes dominant, as the outer electron clouds of the molecules begin to overlap.

HT for Web provides elastic layout (also known as force-oriented layout). Based on the mutual repulsion between nodes and the attraction between interconnected nodes, the elastic layout gradually reaches a convergence and stable equilibrium state after running for a period of time. It’s an interesting feature, and we’re going to show it today.

In this case the address: www.hightopo.com/demo/pipeli…




To use the elastic layout function, we need to introduce the hT-Forcelayout. js elastic layout plug-in library after the introduction of the HT. js core library. Because the form is also used, we need to introduce the HT-form. js form plug-in library:

<script src=".. /.. /guide/lib/core/ht.js"></script>
<script src=".. /.. /guide/lib/plugin/ht-forcelayout.js"></script>
<script src=".. /.. /guide/lib/plugin/ht-form.js"></script>Copy the code

The HT.Layout. Force3dLayout class provides a 3D elastic layout, and the constructor takes in both DataModel and Graph3dView parameters. By default, only unselected primions are laid out. If the constructor argument is Graph3dView, the isMovable and isVisible functions of the view component will affect whether primions are laid out. The layoutable property on the primitives’ style can also be set to false to prevent primitives from participating in the layout.

Now that I’ve given you the background on the elastic layout of the HT package, I’m going to help you easily achieve this effect.

First, we define a color array variable to store the colors of each bouncy ball. We also define a random function to generate the colors in a random array:

var colorList = ['#FFAFA4'.'#B887C5'.'#B9EA9C'.'#CFD9E7'.'#4590B8'.'#FF9C30'], 
    colorLen = colorList.length;
var randomColor = function() {
    var ran = Math.random() * colorLen;
    returncolorList[Math.floor(ran)]; // random 6 colors};Copy the code

Then create the elastic ball and simply generate a 3D Node. Control the display mode of the Node by setting the style attribute of this Node. Set “shape3D” to “sphere” to turn the HT. Node hexahedron into a 3D sphere model. S3 is short for the setSize3d function that sets the size of 3D nodes encapsulated in HT. Finally, add this node to dataModel:

var createNode = function(dm) {// create node circle var node = new ht.node (); Node.s ({// sets the style tosetStyle of shorthand'shape3d': 'sphere'.'shape3d.color': randomColor() // set the randomColor}); node.s3(40, 40, 40); dm.add(node);return node;
};Copy the code

Now there is also a connection between the bouncy balls in the renderings, which we think is very unusual at first sight, also by constructing nodes one by one, Modeling technology based on the node is manual – HT for custom Web setShape3dModel function of HT. Default. CreateRingModel according to the curve of the x, y plane, around a week to form 3 d ring model, named it “custom” :

Ht. Default. SetShape3dModel (/ / create the model according to the x, y plane curve, around a week to form 3 d model.'custom'Ht), the Default, createRingModel ([0.5, 0.5, 0.2, 0, 0.5, 0.5], [1, 3]));Copy the code

HT divides the user – defined properties and HT default property calls into Node. a and node.s so that the two can be effectively separated (see the how-to-get – HT for Web Style section). We used this method when creating the pipeline:

var updatePipeline = function(edge) {var pipeline = edge. A ('pipeline'); pipeline.s3(1, 1, 1); // set the size of pipeline.p3(0, 0, 0); Var node1 = edge.getSourceAgent(), // Get the start node node2 = edge.gettargetAgent (); // Get the target node pipeline.s('mat', createMatrix(node1.p3(), node2.p3(), 20)); // 3d overall graphics matrix change};Copy the code

The most mysterious thing is how to make the two nodes “neither side nor side” effect?

We know that a matrix can describe any linear transformation. Linear transformation preserves straight lines and parallel lines. While linear transformation preserves straight lines, other geometric properties such as length, Angle, area and volume may be changed by transformation. Simply put, a linear transformation may “stretch” the frame, but not “bend” or “curl” it. This function is mainly to perform a “change matrix” operation on the connection line dragged after dragging the elastic ball. The change matrix is also hT.default. createMatrix function wrapped by HT. By setting the style attribute mat of the node as a custom function, Math.PI/6, 0, 0]. Suppose we set R3 to math. PI/3, 0, 0 in createMatrix. So this node is going to be rotated 90 degrees. Very easy to create a change matrix:

var createMatrix = functionVar vec = [p2[0]-p1[0], P2 [1]-p1[1], (p1, p2, width) {// createMatrix(array, matrix) {var vec = [p2[0]-p1[0], P2 [1]-p1[1], p2[2]-p1[2]], dist = ht.Default.getDistance(p1, p2); // Get the distance between two points, or the vector lengthreturn 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]
    });
};Copy the code

After all the basic accessories are defined, set the “Shape3D” property to the custom 3D model “Custom” and set the “Layoutable” property to “false” to prevent primions from participating in the layout. Edge. a(‘pipeline’, node) and add to dataModel:

var createEdge = function(dm, node1, node2) {// Create edge var node for 'custom' model = 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;
};Copy the code

Insert: We can also use HeatMap in the industrial world, and the effect is still amazing. The specific address is HeatMap 3D




The form form is added to the HTML page using the HT.Widget. FormPane function wrapped in HT.

var formPane = new ht.widget.FormPane();
formPane.setWidth(230);
formPane.setHeight(125);
formPane.addToDOM();Copy the code

Remember to set the width and height of the form, otherwise it will not be displayed.

Rows are added to the form using the addRow function. Let’s focus on the following rows, Color, Range and Intensity. These three names are used to control the “headlight”. In the HT directly through setHeadlightColor setHeadlightRange/setHeadlightIntensity three functions to control the color of the head lamp, the scope and the intensity of the light, onValueChanged properties, The event that is triggered when the property value changes as the name implies:

['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 for the colorPicker box instant:true,
        value: g3d['getHeadlight' + name](), // === g3d.getHeadlightColor()
        onValueChanged: func
    };
    elseObj. slider = {// Slider min: 0, Max: name ==='Range'? 20000:3, step: 0.1, value: g3d['getHeadlight'+ name](), onValueChanged: func }; AddRow ([name, obj], [70, 0.1]); });Copy the code

Slider and colorPicker are custom sliders and color pickers for HT. See the form manual – HT for Web for details.