private void myDiagram_Loaded(object sender, RoutedEventArgs e) { LocationStoryBoard = new Storyboard(); // The time for each complete revolution is equal to one second for each node in the outer circle. Duration duration = new Duration(TimeSpan.FromSeconds(NumberOfNodes - 1)); LocationStoryBoard.Duration = duration; // All of the animations repeat continuously. LocationStoryBoard.RepeatBehavior = RepeatBehavior.Forever; foreach (Node n in myDiagram.Nodes) { MyNodeData mnd = n.Data as MyNodeData; if (mnd.Key < 0) { continue; } // The NodePanel should be the first visual child of a Node. try { AnimateNode(mnd.Key, n.VisualElement as NodePanel, duration); } catch (Exception) { } } LocationStoryBoard.Begin(); myDiagram.MouseLeftButtonUp += new MouseButtonEventHandler(myDiagram_PauseResumeAnimation); }
// Adds individual animations to the locationAnimation StoryBoard. private void AnimateNode(int key, NodePanel np, Duration duration) { if (key < 0) { return; } if (np == null) { return; } PointAnimationUsingKeyFrames locationAnimation = new PointAnimationUsingKeyFrames(); double keyTime = 0.0; // Gets the LinearPointKeyFrames for the PointAnimationUsingKeyFrames. // Starts at key-1 to account for an initial KeyFrame. for (int i = key - 1; i < (key + NumberOfNodes - 1); i++) { LinearPointKeyFrame lpkf = new LinearPointKeyFrame(); lpkf.KeyTime = TimeSpan.FromSeconds(keyTime); int nextNodeKeyInt = i + 1; if (nextNodeKeyInt >= (NumberOfNodes - 1)) { nextNodeKeyInt = nextNodeKeyInt % (NumberOfNodes - 1); } MyNodeData nextNodeData = myDiagram.Model.FindNodeByKey((nextNodeKeyInt)) as MyNodeData; if (nextNodeData == null || nextNodeData.Location == null) { return; } lpkf.Value = nextNodeData.Location; locationAnimation.KeyFrames.Add(lpkf); // If duration equals TimeSpan.FromSeconds(NumberOfNodes - 1), // then keyTime increases by 1 with each iteration. keyTime += ((double)duration.TimeSpan.TotalSeconds) / (NumberOfNodes - 1); } LocationStoryBoard.Children.Add(locationAnimation); Storyboard.SetTarget(locationAnimation, np); Storyboard.SetTargetProperty(locationAnimation, new PropertyPath(Node.LocationProperty)); }
public Arrowheads() { InitializeComponent(); // Initialize a new GraphLinksModel var model = new GraphLinksModel <MyNodeData, int, string, MyLinkData>(); model.NodeKeyPath = "Key"; model.LinkLabelNodePath = ""; var nodesSource = new ObservableCollection <MyNodeData> { }; model.NodesSource = nodesSource; model.LinksSource = new ObservableCollection <MyLinkData> { }; model.Modifiable = true; // enables AddNode and AddLink, below // Create the big node in the center CenterNode = new MyNodeData() { Key = -1, Diameter = CenterNodeDiameter, Text = "Click to\rPause!" }; CenterNode.Location = new Point(0, 0); model.AddNode(CenterNode); // Create outer nodes and links to them from the center node, // for each pair of Arrowhead enum values. int i = 1; while (Enum.IsDefined(typeof(Arrowhead), i)) { MyNodeData mnd = new MyNodeData() { Key = (i / 2), Diameter = OuterNodeDiameter }; model.AddNode(mnd); Arrowhead fromarrow = Arrowhead.None; if (Enum.IsDefined(typeof(Arrowhead), i + 1)) { fromarrow = (Arrowhead)(i + 1); } model.AddLink(new MyLinkData() { ToArrow = (Arrowhead)i, FromArrow = fromarrow, Text = ((Arrowhead)i).ToString(), From = CenterNode.Key, To = mnd.Key }); i += 2; } // The expression (NumberOfNodes - 1) is often used to ignore the center node. NumberOfNodes = nodesSource.Count; // Calculates the SpokeLength so that the distance between the centers // of consecutive nodes is equal to RimSegmentLength. SpokeLength = (RimSegmentLength + OuterNodeDiameter) * Math.Sin(0.5 * (Math.PI - 2 * Math.PI / (NumberOfNodes - 1))) / Math.Sin(2 * Math.PI / (NumberOfNodes - 1)); // Doesn't allow SpokeLength to be too close to the centerNode's edge. double minSpokeLength = (0.75 * CenterNodeDiameter); if (SpokeLength < minSpokeLength) { SpokeLength = minSpokeLength; } // Assign the node Locations. double currentAngle = 0.0, currentX = 0.0, currentY = 0.0; for (int j = 1; j < NumberOfNodes; j++) { currentX = SpokeLength * Math.Cos(currentAngle); currentY = SpokeLength * Math.Sin(currentAngle); MyNodeData node = nodesSource[j]; node.Location = new Point(currentX, currentY); currentAngle = (j) * (2 * Math.PI / (NumberOfNodes - 1)); } myDiagram.Model = model; }