在每个节点上应用onmouseover - GOjs库 - swimlane [英] Apply onmouseover on each node - GOjs library - swimlane

查看:1655
本文介绍了在每个节点上应用onmouseover - GOjs库 - swimlane的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我完成了第一部分,在每个节点上添加颜色。下一步是如何在每个节点上添加onmouseover,然后在属于悬停节点的子图(包括连接它的链接/线)上突出显示/应用样式。

I've done the first part, adding colors on each node. The next step would be how to add onmouseover on each node then highlight/apply style on the subgraph (including the links/lines connecting it) belonging to the hovered node.

任何人都知道?

这是我的代码到目前为止:

This is my code so far:

        <?php
    $prospectus = array(
    'subjects' => array(
        'First Year' => array(
            array('course_no' => 'CS 110'       , 'color' => '#21ff1c'),
            array('course_no' => 'CS 111'       , 'color' => 'white'),
            array('course_no' => 'MATH 1'       , 'color' => 'white'),
            array('course_no' => 'MATH 2'       , 'color' => 'white'),
            array('course_no' => 'ENGL 1'       , 'color' => 'white'),
            array('course_no' => 'REED 1'       , 'color' => 'white'),
            array('course_no' => 'PE 1'         , 'color' => 'white'),
            array('course_no' => 'CWTS/ROTC 11' , 'color' => 'white'),
            array('course_no' => 'GUIDANCE 1'   , 'color' => 'white'),
            array('course_no' => 'CS 120'       , 'color' => 'white'),
            array('course_no' => 'CS 121'       , 'color' => 'white'),
            array('course_no' => 'CS 122'       , 'color' => 'white'),
            array('course_no' => 'MATH 4'       , 'color' => 'white'),
            array('course_no' => 'ENGL 2'       , 'color' => 'white'),
            array('course_no' => 'REED 2'       , 'color' => 'white'),
            array('course_no' => 'PE 2'         , 'color' => 'white'),
            array('course_no' => 'CWTS/ROTC 12' , 'color' => 'white'),
            array('course_no' => 'GUIDANCE 2'   , 'color' => 'white')
        ),
        'Second Year' => array(
            array('course_no' => 'CS 211'       , 'color' => 'white'),
            array('course_no' => 'CS 212'       , 'color' => 'white'),
            array('course_no' => 'CS 213'       , 'color' => 'white'),
            array('course_no' => 'ENGL 3'       , 'color' => 'white'),
            array('course_no' => 'MATH 6'       , 'color' => 'white'),
            array('course_no' => 'REED 3'       , 'color' => 'white'),
            array('course_no' => 'PE 3'         , 'color' => 'white'),
            array('course_no' => 'CS 221'       , 'color' => 'white'),
            array('course_no' => 'CS 222'       , 'color' => 'white'),
            array('course_no' => 'CS 223'       , 'color' => 'white'),
            array('course_no' => 'CS 224'       , 'color' => 'white'),
            array('course_no' => 'ENGL 4'       , 'color' => 'white'),
            array('course_no' => 'REED 4'       , 'color' => 'white'),
            array('course_no' => 'PE 4'         , 'color' => 'white'),
            array('course_no' => 'HUMANITIES 1' , 'color' => 'white'),
            array('course_no' => 'MATH 7'       , 'color' => 'white')
        )
    ),
    'preqs'    => array(
        array('subject' => 'CS 120'      , 'preq' => 'CS 110'),
        array('subject' => 'CS 121'      , 'preq' => 'CS 111'),
        array('subject' => 'CS 122'      , 'preq' => 'MATH 1'),
        array('subject' => 'MATH 4'      , 'preq' => 'MATH 1'),
        array('subject' => 'MATH 4'      , 'preq' => 'MATH 2'),
        array('subject' => 'ENGL 2'      , 'preq' => 'ENGL 1'),
        array('subject' => 'REED 2'      , 'preq' => 'REED 1'),
        array('subject' => 'PE 2'        , 'preq' => 'PE 1'  ),
        array('subject' => 'CWTS/ROTC 12', 'preq' => 'CWTS/ROTC 11'),
        array('subject' => 'GUIDANCE 2'  , 'preq' => 'GUIDANCE 1'),

        array('subject' => 'CS 211'        , 'preq' => 'CS 121'),
        array('subject' => 'CS 212'        , 'preq' => 'CS 110'),
        array('subject' => 'CS 213'        , 'preq' => 'CS 122'),
        array('subject' => 'ENGL 3'        , 'preq' => 'ENGL 2'),
        array('subject' => 'MATH 6'        , 'preq' => 'MATH 4'),
        array('subject' => 'REED 3'        , 'preq' => 'REED 2'),
        array('subject' => 'PE 3'          , 'preq' => 'PE 2'),

        array('subject' => 'CS 221'        , 'preq' => 'CS 122'),
        array('subject' => 'CS 221'        , 'preq' => 'CS 211'),
        array('subject' => 'CS 222'        , 'preq' => 'CS 211'),
        array('subject' => 'CS 223'        , 'preq' => 'CS 211'),
        array('subject' => 'CS 224'        , 'preq' => 'CS 121'),
        array('subject' => 'ENGL 4'        , 'preq' => 'ENGL 2'),
        array('subject' => 'REED 4'        , 'preq' => 'REED 3'),
        array('subject' => 'PE 4'          , 'preq' => 'PE 3'),
    )
);
?>

<!DOCTYPE html>
<html>
<head>
<title>Swimlane</title>
<!-- Copyright 1998-2014 by Northwoods Software Corporation. -->
<link href="goSamples.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="go.js"></script>
<script id="code">

function highlightNode(node, color) {
    if (node === null) return;
    var shape = node.findMainElement();
    if (shape === null) return;
    if (color !== undefined) {
        if (!shape.previousStroke) shape.previousStroke = shape.stroke;
        shape.stroke = color;
    } else {  // restore previous color
        shape.stroke = shape.previousStroke;
    }
}

function highlightLink(link, color) {
    if (link === null) return;
    var shape = link.findMainElement();
    if (shape === null) return;
    if (color !== undefined) {
        if (!shape.previousStroke) shape.previousStroke = shape.stroke;
        shape.stroke = color;
    } else {  // restore previous color
        shape.stroke = shape.previousStroke;
    }
}

function highlightConnectedNodes(node, color) {
    if (node === null) return;

    var lit = node.findLinksOutOf();

    while (lit.next()) {
        highlightLink(lit.value, color);
    }

    var nit = node.findNodesOutOf();

    while (nit.next()) {
        highlightNode(nit.value, color);
        highlightConnectedNodes(nit.value, color);
    }
}

// These parameters need to be set before defining the templates.
// this controls whether the swimlanes are horizontal stacked vertically, or the other way:
var HORIZONTAL = false;
// this controls the minimum length of any swimlane
var MINLENGTH = 500;
// this controls the minimum breadth of any swimlane
var MINBREADTH = 360;


// compute the minimum length needed to hold all of the subgraphs
function computeMinPlaceholderSize(diagram) {

    var len = MINLENGTH;

    for (var it = diagram.nodes; it.next(); ) {
        var group = it.value;

        if (!(group instanceof go.Group))
            continue;

        var holder = group.placeholder;

        if (holder !== null) {
            var sz = holder.actualBounds;
            len = Math.max(len, (HORIZONTAL ? sz.width : sz.height));
        }
    }

    return (HORIZONTAL ? new go.Size(len, NaN) : new go.Size(NaN, len));
}

// get the minimum placeholder size for a particular Group;
// when group is null, return the minimum size
function computePlaceholderSize(group) {

    if (group instanceof go.Group) {
        var holder = group.placeholder;

        if (holder !== null) {
            return holder.actualBounds.size;
        }
    }

    return (HORIZONTAL ? new go.Size(MINLENGTH, MINBREADTH) : new go.Size(MINBREADTH, MINLENGTH));
}

// define a custom grid layout that makes sure the length of each lane is the same
// and that each lane is broad enough to hold its subgraph
function StackLayout() {
    go.GridLayout.call(this);
}
go.Diagram.inherit(StackLayout, go.GridLayout);

StackLayout.prototype.doLayout = function(coll) {
    var diagram = this.diagram;

    if (diagram === null)
        return;

    diagram.startTransaction("StackLayout");

    // make sure all of the Group Shapes are big enough
    var minsize = computeMinPlaceholderSize(diagram);

    for (var it = diagram.nodes; it.next(); ) {
        var group = it.value;

        if (!(group instanceof go.Group))
            continue;

        var shape = group.findObject("SHAPE");

        if (shape !== null) {  // change the desiredSize to be big enough in both directions
            var sz = computePlaceholderSize(group);

            if (HORIZONTAL) {
                shape.width = (isNaN(shape.width) ? minsize.width : Math.max(shape.width, minsize.width));

                if (!isNaN(shape.height))
                    shape.height = Math.max(shape.height, sz.height);
            } else {
                if (!isNaN(shape.width))
                    shape.width = Math.max(shape.width, sz.width);
                shape.height = (isNaN(shape.height) ? minsize.height : Math.max(shape.height, minsize.height));
            }

            var cell = group.resizeCellSize;

            if (!isNaN(shape.width) && !isNaN(cell.width) && cell.width > 0)
                shape.width = Math.ceil(shape.width / cell.width) * cell.width;
            if (!isNaN(shape.height) && !isNaN(cell.height) && cell.height > 0)
                shape.height = Math.ceil(shape.height / cell.height) * cell.height;
        }
    }

    // now do all of the usual stuff, according to whatever properties have been set on this GridLayout
    go.GridLayout.prototype.doLayout.call(this, coll);
    diagram.commitTransaction("StackLayout");
};
// end StackLayout class

function init() {

    var $ = go.GraphObject.make;
    myDiagram =
        $(go.Diagram, "myDiagram",
            {
                initialContentAlignment: go.Spot.Center,
                layout:
                    $(StackLayout,
                        {
                            cellSize: new go.Size(1, 1),
                            spacing: new go.Size(0, 0),
                            wrappingColumn: (HORIZONTAL ? 1 : Infinity),
                            wrappingWidth: Infinity,
                            isViewportSized: false
                        })
            });

    myDiagram.nodeTemplate =
        $(go.Node, "Auto",
            $(go.Shape, "Rectangle",
                { fill: "lightblue", portId: "", cursor: "pointer", fromLinkable: true, toLinkable: true },
                new go.Binding("fill", "color")),
            $(go.TextBlock, { margin: 5 },
                new go.Binding("text", "key")),
            // limit dragging of Nodes to stay within the containing Group, defined above
            {
                mouseEnter: function(e, obj, prev) {
                    var shape = obj.findMainElement();
                    if (shape){
                        shape.previousFill = shape.fill || "lightblue";
                        shape.fill = "white";
                    }
                    highlightConnectedNodes(obj, "red");
                },
                mouseLeave: function(e, obj, next) {
                    var shape = obj.findMainElement();
                    var original_color = obj.wl.color;

                    if (shape) shape.fill = shape.previousFill;

                    highlightConnectedNodes(obj);
                }

            }
        );

    // each Group is a "swimlane" with a header on the left and a resizable lane on the right
    myDiagram.groupTemplate =
        $(go.Group, HORIZONTAL ? "Horizontal" : "Vertical",
            {
                movable: false, copyable: false, deletable: false,  // can't move or copy or delete lanes
                avoidable: false,
                selectionObjectName: "SHAPE",  // selecting a lane causes the body of the lane to be highlit, not the label
                resizable: true, resizeObjectName: "SHAPE",  // allow lanes to be resized, but the custom resizeAdornmentTemplate only permits one kind of resizing
                layout: $(go.LayeredDigraphLayout,  // automatically lay out the lane's subgraph
                    { direction: HORIZONTAL ? 90 : 0, columnSpacing: 10, layeringOption: go.LayeredDigraphLayout.LayerLongestPathSource }),
                computesBoundsAfterDrag: false,  // needed to prevent recomputing Group.placeholder bounds too soon
                computesBoundsIncludingLinks: false,
                computesBoundsIncludingLocation: true
            },

            // the lane header consisting of a Shape and a TextBlock
            $(go.Panel, "Horizontal",
                {
                    angle: HORIZONTAL ? 270 : 0,  // maybe rotate the header to read sideways going up
                    alignment: go.Spot.Center
                },

                $(go.Shape, "Diamond",
                    { width: 0, height: 0 },
                    new go.Binding("fill", "color")),

                $(go.TextBlock,  // the lane label
                    { font: "bold 14pt Century Gothic" },
                    new go.Binding("text", "key"))
            ),
            // end Horizontal Panel

            $(go.Panel, "Auto",  // the lane consisting of a background Shape and a Placeholder representing the subgraph
                $(go.Shape, "Rectangle",
                    { name: "SHAPE", fill: "white", minSize: computePlaceholderSize(null) },
                    new go.Binding("fill", "color")),
                $(go.Placeholder,
                    { padding: 10, alignment: go.Spot.TopLeft })
            )
            // end Auto Panel
        );
    // end Group

    // define a custom resize adornment that only has a single resize handle
    myDiagram.groupTemplate.resizeAdornmentTemplate =
        $(go.Adornment, "Spot",
            $(go.Placeholder),
            $(go.Shape,  // for changing the length of a lane
                {
                    alignment: HORIZONTAL ? go.Spot.Right: go.Spot.Bottom,
                    desiredSize: HORIZONTAL ? new go.Size(7, 50) : new go.Size(50, 7),
                    fill: "lightblue", stroke: "dodgerblue",
                    cursor: HORIZONTAL ? "col-resize" : "row-resize"
                }),
            $(go.Shape,  // for changing the breadth of a lane
                {
                    alignment: HORIZONTAL ? go.Spot.Bottom : go.Spot.Right,
                    desiredSize: HORIZONTAL ? new go.Size(50, 7) : new go.Size(7, 50),
                    fill: "lightblue", stroke: "dodgerblue",
                    cursor: HORIZONTAL ? "row-resize" : "col-resize"
                })
        );

    myDiagram.linkTemplate =
        $(go.Link,
            { routing: go.Link.AvoidsNodes, corner: 5 },
            { relinkableFrom: true, relinkableTo: true },
            $(go.Shape),
            $(go.Shape, { toArrow: "Standard" }),
            {
                layoutConditions: go.Part.LayoutAdded
            }
        );

    // define some sample graphs in some of the lanes
    myDiagram.model = new go.GraphLinksModel(
        [ // node data
            { key: "First Year"   , isGroup: true, color: "#84ff9e" },
            { key: "Second Year"  , isGroup: true, color: "#dafb69" },
            { key: "Third Year"   , isGroup: true, color: "#fd5c91" },
            { key: "Fourth Year"  , isGroup: true, color: "#6f5cfd" },

            <?php
                if(isset($prospectus['subjects'])){
                    if(!empty($prospectus['subjects'])){
                        foreach($prospectus['subjects'] as $year => $subjects){
                            foreach($subjects as $subject){
                                echo '{key: "' . $subject['course_no'] . '", group: "' . $year . '", color: "' . $subject['color'] . '"},' ;
                            }
                        }
                    }
                }
            ?>
        ],
        [ // link data
            <?php
                if(isset($prospectus['preqs'])){
                    if(!empty($prospectus['preqs'])){
                        foreach($prospectus['preqs'] as $preq){
                            echo "{from: '" . $preq['preq'] . "', to: '" . $preq['subject'] . "'}," ;
                        }
                    }
                }
            ?>
        ]);

    myDiagram.isReadOnly = true;
}
</script>
</head>
<body onload="init()" style="font-family: Century Gothic">
<div id="sample" style="margin-left: 0px">
    <div id="myDiagram" style="border: solid 1px blue; width:100%; height:750px;">
    </div>
</div>
</body>
</html>


推荐答案

下面是包含鼠标进入的节点模板部分,离开函数:

Here is the node template part containing the mouse enter and leave functions:

     myDiagram.nodeTemplate =
      $(go.Node, "Auto",
        $(go.Shape, "Rectangle",
          { fill: "lightblue", portId: "", cursor: "pointer", fromLinkable: true, toLinkable: true },
          new go.Binding("fill", "color")),
        $(go.TextBlock, { margin: 5 },
          new go.Binding("text", "key")),
        // limit dragging of Nodes to stay within the containing Group, defined above
        {
          dragComputation: stayInGroup,
          mouseDrop: function (e, node) {  // dropping a copy of some Nodes and Links onto this Node adds them to this Node's Group
            if (!e.shift && !e.control) return;  // cannot change groups with an unmodified drag-and-drop
            var grp = node.containingGroup;
            if (grp !== null) {
              var ok = grp.addMembers(node.diagram.selection, true);
              if (!ok) grp.diagram.currentTool.doCancel();
            }
          },
          layoutConditions: go.Part.LayoutAdded | go.Part.LayoutNodeSized,

            mouseEnter: function(e, obj, prev) {
                var shape = obj.findMainElement();
                if (shape){
                    shape.previousFill = shape.fill || "lightblue";
                    shape.fill = "white";
                }
                highlightConnectedNodes(obj, "red");
            },
            mouseLeave: function(e, obj, next) {
                var shape = obj.findMainElement();
                var original_color = obj.wl.color;

                if (shape) shape.fill = shape.previousFill;

                highlightConnectedNodes(obj);
            }

        }
      );



两个函数都调用highlightConnectedNodes函数,后者又调用另外两个函数。一个用于节点,一个用于链接。



Both functions call highlightConnectedNodes function which in turn calls two other functions. One for nodes and one for links.

   function highlightNode(node, color) {
     if (node === null) return;
     var shape = node.findMainElement();
     if (shape === null) return;
     if (color !== undefined) {
       if (!shape.previousStroke) shape.previousStroke = shape.stroke;
       shape.stroke = color;
     } else {  // restore previous color
       shape.stroke = shape.previousStroke;
     }
   }

   function highlightLink(link, color) {
     if (link === null) return;
     var shape = link.findMainElement();
     if (shape === null) return;
     if (color !== undefined) {
       if (!shape.previousStroke) shape.previousStroke = shape.stroke;
       shape.stroke = color;
     } else {  // restore previous color
       shape.stroke = shape.previousStroke;
     }
   }

   function highlightConnectedNodes(node, color) {
     if (node === null) return;

     var lit = node.findLinksInto();

     while (lit.next()) {           
       highlightLink(lit.value, color);
     }

     var nit = node.findNodesInto();

     while (nit.next()) {   
       highlightNode(nit.value, color);
       highlightConnectedNodes(nit.value, color);
     }
   }



通过节点,所有节点和连接到它的链接改变颜色(向后)。但是,如果您只希望悬停节点前面的节点和链接更改颜色,您可以更改



When you hover over a node all nodes and links connected to it change color (going backwards). However, if you want only nodes and links forward of the hovered node to change color you can change

findNodesInto
findLinksInto

findNodesOutOf 
findLinksOutOf 


希望有帮助。


Hope that helps.

这篇关于在每个节点上应用onmouseover - GOjs库 - swimlane的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆