在每个节点上应用onmouseover - GOjs库 - swimlane [英] Apply onmouseover on each node - GOjs library - 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屋!