Heylo folks,
Many-a-times it happens that one makes an ill informed hurried analysis of a simple problem. This is followed by rapid questions on IRC / discussion forums etc, until someone
someone more sensible comes along and makes you realize what a dumb ass you’ve been. 😛
Well something similar happened to me the other day. The task at hand was to create an interactive chain sortta an element for a project. I started thinking about Physics / The Bone Tool
Linked Lists and what not. I knew I was thinking too much for a simple problem but I couldn’t strike the solution. Then finally, I logged onto IRC and asked around.
Here was my question ,
The answer was – YES!
However, that’s not the one I chose. The stuff I couldn’t figure out was the “Links” between the nodes.
How would they rise / stretch when the node rises on rollover. Do I rotate them? Do I scale them ? What should I do ???
The solution was elementary – Anchor the links to the nodes and redraw the links every frame.
That way when a node’s position changes, the new link is drawn from the previous node to the new position, thus giving
a “stretching” effect when you use a tween to update the nodes position.
To give it a bouncy effect I used TweenLite by Greensock. That’s what changes the colors too.
Here’s what it looks like : http://dazzlecode.com/downloads/NodeOver.swf
Here’s the code :
package { import com.greensock.TweenLite; import com.greensock.easing.Bounce; import com.greensock.plugins.*; import flash.display.MovieClip; import flash.display.Sprite; import flash.events.Event; import flash.events.MouseEvent; import flash.geom.Point; TweenPlugin.activate([TintPlugin]); /** * @author smaira */ [SWF(backgroundColor="#FFFFFF", frameRate="31", width="550", height="400")] public class NodeOver extends MovieClip { private var lastX : Number = 10; private var numberOfLinks : Number = 7; //Helper function handler. This is just a class I created for common functions I use in projects. Ignore it. private var hf : Funcs = Funcs.getInstance(); //Array to hold the nodes private var nodeArray : Array = new Array(); //Array to hold the links private var linkArray : Array = new Array(); public function NodeOver() { createNodes(); createLinks(); addHeader(); addEventListener(Event.ENTER_FRAME, onEnterFrameListener); } //Just adds a graphic on the top of the movie private function addHeader() : void { var hd : Header = new Header(); hd.x = (stage.stageWidth - hd.width) / 2; hd.y = 20; addChild(hd); } //Recreate the links every frame - Clear them first. private function onEnterFrameListener(event : Event) : void { clearLinks(); createLinks(); } private function clearLinks() : void { //Removing the child from the stage for each (var link in linkArray) { removeChild(getChildByName(link.name)); link = null; } //Clearing the link array linkArray.splice(0, linkArray.length); } private function createLinks() : void { //Each link is created between the previous and the next node. for (var i : uint = 0;i < nodeArray.length - 1;i++) { var linkSprite : Sprite = new Sprite(); linkSprite.graphics.lineStyle(2, 0x0000FF, 1, false, "NONE"); linkSprite.graphics.moveTo(nodeArray[i].node.x + nodeArray[i].node.width / 2, nodeArray[i].node.y + nodeArray[i].node.height / 2); linkSprite.graphics.lineTo(nodeArray[i + 1].node.x + nodeArray[i + 1].node.width / 2, nodeArray[i + 1].node.y + nodeArray[i + 1].node.height / 2); addChild(linkSprite); //Setting the depth of the link , sending it behind the node setChildIndex(linkSprite, getChildIndex(nodeArray[i].node) + 1); //Setting the mouse to false linkSprite.mouseEnabled = false; //Setting the name of the link linkSprite.name = "link" + i; linkArray.push(linkSprite); } } private function createNodes() : void { // 7 is the number of nodes I created. You can change this to any number. for (var i : uint = 0;i < numberOfLinks;i++) { var node : MovieClip = new Node(); var nodeObj : Object = new Object(); //Positioning the new node relative to the last one. node.x += lastX + 60; node.y = hf.randomRange(270, 300); lastX = node.x; addChild(node); //Just setting the alpha to a lower value for the first and last node if (i == 0 || i == numberOfLinks - 1) { node.alpha = 0.3; } //Add the mouse over event to the node node.addEventListener(MouseEvent.MOUSE_OVER, onNodeMouseOver); node.buttonMode = true; //Creating the node object that goes into the nodeArray. nodeObj.node = node; nodeObj.initPos = new Point(node.x, node.y); nodeObj.dataMc = setNodeData(node); //TODO: Instead of giving each node a seperate nodeData mc just have 1 mc for all the nodes and just store the image/text in this object. nodeObj.initColor = 0x0000CC; nodeObj.rollOverFlag = false; nodeArray.push(nodeObj); } } //This just creates and returns a movieclip holding the data for a node. private function setNodeData(target : MovieClip) : MovieClip { //Pull out the node data var nodeData : NodeData = new NodeData(); //NodeData is the linkage id of an asset in the library. nodeData.nodeText.text = "I am just a test, nothing more, nothing less. Test Test Test Test TestTest TestTest TestTest TestTest Test"; nodeData.alpha = 0; return MovieClip(nodeData); } private function onNodeMouseOver(event : MouseEvent) : void { //Resets the positions of all other NODES except the active one to their initial position. resetNodePositions(MovieClip(event.target)); event.target.rollOverFlag = true; TweenLite.to(event.target, 1, {y:event.target.y - 100, tint:0x00FF00, ease:Bounce.easeOut, onComplete:setFlagFalse, onCompleteParams:[event.target]}); } private function setFlagFalse(target : MovieClip) : void { target.setRollOverFlag = false; //Popout the NodeData movie clip //First find the object in the nodeArray which contains the current node (target) var nodeObject : Object; //TODO: There has to be a function to do such a search. Find out how. for (var i : uint = 0;i < nodeArray.length;i++) { if (nodeArray[i].node == target) { nodeObject = nodeArray[i]; break; } } //Set the node position relative to the target. nodeObject.dataMc.x = target.x; nodeObject.dataMc.y = target.y - nodeObject.dataMc.height / 2; //Add the dataMc to the stage //TODO: Should I add this here or on top when I'm creating it ? addChild(nodeObject.dataMc); TweenLite.to(nodeObject.dataMc, 1, {x:nodeObject.node.x + 50, alpha:1}); } //Reset the positions of all the nodes to their initPositions except the passed one private function resetNodePositions(excludedNode : MovieClip) : void { for each (var nodeObj:Object in nodeArray) { if (nodeObj.node != excludedNode) { TweenLite.to(nodeObj.node, 1, {y:nodeObj.initPos.y, tint:nodeObj.initColor, ease:Bounce.easeOut}); TweenLite.to(nodeObj.dataMc, 0.5, {alpha:0}); } } } } }
Leave a comment