circlecube

RSS comments
LinkedIn Twitter delicious fb last.fm

Posts Tagged ‘interactive’

Overview

The Shared Object is like a cookie for flash. It lets flash store some data on the local machine, so between sessions it can remember things. Learn more from wikipedia.
Shared Objects are used to store data on the client machine in much the same way that data is stored in a cookie created through a web browser. The data can only be read by movies originating from the same domain that created the Shared Object. This is the only way Macromedia Flash Player can write data to a user’s machine. Shared Objects can not remember a user’s e-mail address or other personal information unless they willingly provide such information.

I’ve seen many Local Shared Object tutorials and examples, which have users input their name and/or hometown and other filler data. But I wanted to show how to creatively incorporate shared objects into interactions. So I’ve thrown in many simultaneous examples including the uber-simple ‘input your name and I’ll remember it’ approach. I hope I didn’t throw in so much that it got confusing… just let me know if you have any questions or anything is unclear. Keeping it simply and broad there’s only a few things to know about Shared Objects.

Steps

    Simply put there are only a couple things to worry about with Local Shared Objects

  • Create them.
    • As in create the shared object
  • Write them.
    • As is write to the shared object
  • Set them.
    • As in setting variables in the shared object
  • Get them.
    • As in getting variables back out of the shared object
  • Clear them.
    • As in clearing the shared objec

Actionscript

here’s samples on how to do each of those

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
/* Create them. */
//make Local Shared Object named myLocalSO(in as) called "myflashcookie" on disk
var myLocalSO:SharedObject = SharedObject.getLocal("myflashcookie");

/* Write them. */
//flush the SO, write the SO to disk
myLocalSO.flush();

/* Set them. */
//set key's value to specified value in SO
//key is the name of the data
//val is key's value
function setVal(key, val) {
myLocalSO.data[key] = val;
trace(key +" set to "+val);
/* including writing to Shared Object in the setter function */
//flush the SO, write the SO to disk
myLocalSO.flush();
}
/* Get them. */
//get key's value from SO
function getVal(key) {
return myLocalSO.data[key];
trace(myLocalSO.data[key] +" received from "+key);
}
/* Clear them. */
myLocalSO.clear();

Example

here’s my colorful example.
The purple/yellow circle is draggable, so place it where you want it. Enter your name and age in the input boxes. Press the center red ‘Set cookie’ button to copy those values to the shared object that is on your computer now. The red transparent circle represents the cookie positions. You can position the purple/yellow circle from the cookie contents with the dark green ‘Position from cookie’ button, or position it randomly with the blue ‘Position randomly’ button. Erase the cookie with the orange ‘Erase cookie’ button. Toggle easing (animation) with the Bright green button (which changes to dark red when off), it tells the current mode of ease. I have the cookie coordinates displayed and the current coordinates of the purple/yellow circle also displayed.
The cookie includes a date object, which is used to calculate the age of the cookie (watch it reset when you erase the cookie (orange button)).
The ‘All Time Visit’ stat is the only thing that does not get reset when you erase the cookie,

Get Adobe Flash player

and source code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
////////////////////////  Initialize variables  ///////////////////////

//make Local Shared Object named myLocalSO(in as) called "myflashcookie" on disk
var myLocalSO:SharedObject = SharedObject.getLocal("myflashcookie");
//speed var for easing
var speed = 3;
var w = myCircle._width/2;
//toggle var for easing
var ease = true;
//as var to store alltime cookie
var allTimeVisitCount=0;
countVisit();
cookieFeedback();
//line style for tracing movement
lineStyle(1, 0, 50);


////////////////////////  Functions  ///////////////////////

//set key's value to specified value in SO
//key is the name of the data
//val is key's value
function setVal(key, val) {
  myLocalSO.data[key] = val;
  trace(key +" set to "+val);
  //flush the SO, write the SO to disk
  myLocalSO.flush();
}
//get key's value from SO
function getVal(key) {
  return myLocalSO.data[key];
  trace(myLocalSO.data[key] +" received from "+key);
}

function countVisit() {
  //if first visit
  if (getVal('visitCount') == undefined) {
    //create date for now and store in cookie
    var todayDate:Date = new Date();
    setVal('date', todayDate);
    trace("creating date");
    //start/reset counting visits
    var visitCount = 0;
    //notice allTimeVisitCount is not reset, but stored still as a var in actionscript
  }
 
  //not first visit
  else {
    visitCount = getVal('visitCount');
    allTimeVisitCount = getVal('allTimeVisitCount');
  }
  //increment visit counter
  setVal('visitCount', visitCount+1);
  setVal('allTimeVisitCount', allTimeVisitCount+1);
  //feedback of visit counting
  visitsFeedback.text = getVal('visitCount');
  allTimeVisitsFeedback.text = getVal('allTimeVisitCount');
}
//feedback of cookie contents
function cookieFeedback() {
  //in defined print coordinate contents
  cookiex.text = getVal('circleX') == undefined ? "no cookie" : getVal('circleX');
  cookiey.text = getVal('circleY') == undefined ? "no cookie" : getVal('circleY');
 
  //if not easing assign coordinates from cookie
  if (!ease) {
    myCookie._x = getVal('circleX');
    myCookie._y = getVal('circleY');
  }
  //set target to cookie coordinates
  else {
    ctargetx = getVal('circleX');
    ctargety = getVal('circleY');
  }
  //if name then trace cookie contents
  if (getVal('name') != undefined) {
    visitorFeedback.text = "Returning Visitor";
    nameInput.text = getVal('name');
    ageInput.text = getVal('age');
  }
  //no name then a new visitor
  else {
    visitorFeedback.text = "First Time Visitor";
    nameInput.text = "";
    ageInput.text = "";
  }
  calculateCookieAge();
}
function calculateCookieAge() {
  //make a date now
  todayDate = new Date();
  //get the cookie's stored date
  cookieDate = getVal('date');
  //difference between two dates
  cookieDateAge = Math.floor(todayDate - cookieDate);
  //convert miliseconds to a timecode
  cookieAge.text = msToTimeCode(cookieDateAge);cookieDateAge;
}

//convert miliseconds to a hh:mm:ss
function msToTimeCode(ms) {
  //make sure value is within bounds. if a number grater than zero and less than the duration of video
    if (isNaN(ms) || ms< 0) {
        ms = 0;
    }
  //find seconds
  var sec = ms/1000;
  //find minutes
    var min = Math.floor(sec/60);
  //adjust seconds
    sec = sec - min*60;
  //find hours
  var hour = Math.floor(min/60);
  //adjust minutes
  min = min - hour*60;
  //floor seconds down to whole number
  sec = Math.floor(sec);
  //make time code with hours
  if (hour == 0) {
    if (sec < 10) {
          sec = "0"+sec;
      }
      if (min < 10) {
          min = "0"+min;
      }
      var tc = min+":"+sec;
  }
  //make time code without hours
  else {
    if (sec < 10) {
          sec = "0"+sec;
      }
      if (min < 10) {
          min = "0"+min;
      }
      var tc = hour+":"+min+":"+sec;
  }
  return tc;
}





//////  Actionscript attached to Objects/handlers  //////////

//place data on stage into cookie (circle coordinates and input text)
setCookieButton.onRelease = function() {
  setVal('circleX', myCircle._x);
  setVal('circleY', myCircle._y);
  setVal('name', nameInput.text);
  setVal('age', ageInput.text);
  //update the display on stage
  cookieFeedback();
}
//make random coordinates on stage
randomButton.onRelease = function() {
  //if not easing assign coordinates to myCircle
  if (!ease) {
    myCircle._x = Math.random() * (Stage.width - w);
    myCircle._y = Math.random() * (Stage.height - w);
  }
  //if easing assign coordinates to myCircle's target coords
  else {
    targetx = Math.random() * (Stage.width - w);
    targety = Math.random() * (Stage.height - w);
  }
}

myCircle.onPress = function() {
  this.startDrag();
  dragging = true;
  lineStyle(1, 200, 30);
}

myCircle.onRelease = myCircle.onReleaseOutside = function() {
  targetx = this._x;
  targety = this._y;
 
  lineStyle(1, 0, 50);
 
  dragging = false;
  this.stopDrag();
}

myCircle.onEnterFrame = function() {
  //print position feedback
  currentx.text = this._x;
  currenty.text = this._y;
  //if eas move to target
  if (ease) {
    if (!dragging) {
      moveTo(this._x+w, this._y+w);
      this._x+=(targetx-this._x)/speed;
      this._y+=(targety-this._y)/speed;
    }
    //draw line
    lineTo(this._x+w, this._y+w);
  }
}

myCookie.onEnterFrame = function() {
  //if ease move cookie to target
  if (ease) {
    this._x+=(ctargetx-this._x)/speed;
    this._y+=(ctargety-this._y)/speed;
  }
  calculateCookieAge();
}

//Position from Cookie
cookieButton.onRelease = function() {
  //if not easing set coordinates from cookie
  if (!ease) {
    myCircle._x = getVal('circleX');
    myCircle._y = getVal('circleY');
  }
  //if easing set target coordinates from cookie
  else {
    targetx = getVal('circleX');
    targety = getVal('circleY');
  }
}
easeBtn.onRelease = function () {
  //toggle easing
  ease = !ease;
  //advance the frame of this button...
  this.play();
}
clearCookieBtn.onRelease = function() {
  //clear the cookie (swipe all data)
  myLocalSO.clear();
  //restart visit count
  countVisit();
  //read cookie and give feedback
  cookieFeedback();
}

Source

download the source for this example: sharedObject.fla

  • del.icio.us
  • Digg
  • email
  • Facebook
  • Google Bookmarks
  • LinkedIn
  • Mixx
  • Print
  • PDF
  • StumbleUpon
  • Technorati
  • Twitter
  • RSS
24 Apr 2008

Shared Object – utilizing the Flash cookie

Author: Evan Mullins | Filed under: tutorial

scrut_4
Software for viewing websites through a simulated fovea vision. Since not everyone could set-up, let alone afford a real eye-tracker. This software uses the mouse pointer as the user’s focal point, or foveal view. It blurs everything except where your focal point (the mouse) is. It is helpful because it forces you to re-think web design from an extreme usability standpoint. This browser software was built using AIR and Flex. Using this software as an eye-tracking simulation, you can get a better idea of how users interact with your site design.
scrut_2scrut_1scrut_3

I was responsible for programming and designing some key functionality of the app: the menu bar logic, bookmarking engine, capturing and saving of screenshots, and the loading bar which shows page load progress, and the overall browser chrome/skin.

  • del.icio.us
  • Digg
  • email
  • Facebook
  • Google Bookmarks
  • LinkedIn
  • Mixx
  • Print
  • PDF
  • StumbleUpon
  • Technorati
  • Twitter
  • RSS
2 Apr 2008

Stomper Scrutinizer Browser AIR App

Author: Evan Mullins | Filed under: portfolio

squambido_1
The flash video player designed and developed for Free IQ and StomperNet. Plays video and audio content for a user. I implemented 85% of the actionscript, creating intuitive interactivity and functionality. External xml plsylist, author biography display, content details, share by email, social bookmarking, get embed codes, and more. Sleek design for maximum intuitive user engagement including navigable playlist, author biography, video detail, embedding, email, social bookmarking, volume control, full screen, multiple size options, etc.
squambido_2squambido_4squambido_5squambido_6squambido_7squambido_8

More About Squambido

squambido_3

  • del.icio.us
  • Digg
  • email
  • Facebook
  • Google Bookmarks
  • LinkedIn
  • Mixx
  • Print
  • PDF
  • StumbleUpon
  • Technorati
  • Twitter
  • RSS
31 Mar 2008

Custom Flash Video Player @ FreeIQ and StomperNet

Author: Evan Mullins | Filed under: portfolio

Go get the file at FlashDen

Dynamic Scrolling Link List XML driven (No Wrap)

An interactive link list. Vertically scrolling list of links or just text. Could be used for a nav menu or a link list, or even just a scrolling list. Scroll speed calculated dynamically from mouse position to give not only scrolling control, but also speed control. Reads an external XML file containing just titles and url paths and creates this interactive click-able link list! On click the link is highlighted and on release loads the url either in a blank window or not (configurable). On rollover the list item grows with animation and is highlighted (all configurable, size speed etc). Once end of list is reached scrolling stops, another version is available with a wrap-around feature: Dynamic Scrolling Link List XML driven Auto wrapping

Get Adobe Flash player

Circlecube Items at FlashDen

21075 24687 45713 45893 22018

  • del.icio.us
  • Digg
  • email
  • Facebook
  • Google Bookmarks
  • LinkedIn
  • Mixx
  • Print
  • PDF
  • StumbleUpon
  • Technorati
  • Twitter
  • RSS
26 Mar 2008

Dynamic Flash Scrolling Link List XML driven Component on FlashDen

Author: Evan Mullins | Filed under: portfolio

I have been thinking of different interactions that are possible with objects. If you’ve read this blog at all you’ll know that I’ve played with physics and gravity and throwing balls and bouncing balls and all sorts. But I hadn’t wrapped my head around an interactive spinner. I know it’d be easy to make a slider or something that would apply a spin to an object, but this just isn’t interactive enough for me.

Circle with slider to rotate and button for random spin:

Get Adobe Flash player

This attempt at spinning is ok. I mean, it spins the object and it even glides to a stop if you press the button for a random spin… But it’s just not intuitive and not fun. But if you want this, here’s how I did it.

Actionscript:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
drag = .96;
speed = 0;

slider.handle.onPress = function() {
spinning = false;
//drag along the line
this.startDrag(true, slider.line._x-slider.handle._width/2, slider.line._y-slider.handle._height/2, slider.line._width-slider.handle._width/2, slider.line._y-slider.handle._height/2);
}
slider.handle.onRelease = slider.handle.onReleaseOutside = function() {
this.stopDrag();
}
_root.onEnterFrame = function() {
if (spinning) {
//apply the speed to the rotation
knob._rotation += speed;
//recalculate speed
speed = speed*drag;
//if speed gets unnoticeably tiny just set it to 0
if (Math.pow(speed, 2) &lt; .0001) {
speed = 0;
}
}
else {
//set the rotation from the slider position
knob._rotation = slider.line._x + slider.handle._x + slider.handle._width/2;
}

//spit out feedback continuously
feedbackr.text = knob._rotation;
feedbackaccr.text = speed;
}
spinner.onRelease = function() {
//find a random speed
speed = (Math.random()* 50) - 25;
spinning = true;
}

I want to grab it and spin it though. I want to apply the same principles from physics, like acceleration and friction as forces to the object, so I can grab to spin and release to watch it glide gracefully to a stop. I’ve been thinking about this and how I’d have to use trigonometry and stuff to do it. One day I finally had the time and tried it out. It took me a minute but I figured out that what I needed was arctangent. So (with pointers from jbum, thanks Jim!) I came up with this:

Interactive grab-able circle to spin and twirl:

Get Adobe Flash player

This one is much more interactive and intuitive. I really think this is because there are no sliders or buttons, no controls, just an object to interact with. It’s much more like real life!

Steps:

In order to make a grab and spin object
1. You have to know where you grab. The user clicks on the shape (knob) and you must figure out what degree or rotation point they have started at. (atan2)
2. As the knob is clicked and the mouse moves (dragging), calculate new rotation by mouse position
3. When mouse is released figure out the current speed of rotation and apply it to the knob with friction, so it can be thrown and spun in that way. (Of course this is optional, if you just want to spin it when the mouse is down you’re done at step 2)

Actionscript:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
damp = .96; //friction
r = 0; //rotation
accr = 0; //speed of rotation

knob.onPress = function() {
dragging = true;
//find mouse y coordinate in relation to knob origin
a = _root._ymouse - knob._y;
//find mouse x coordinate in relation to knob origin
b = _root._xmouse - knob._x;
//using arctangent find the spot of rotation (in degrees)
oldr = Math.atan2(a,b)*180/Math.PI;
}

knob.onRelease = knob.onReleaseOutside = function() {
dragging = false;
}

knob.onEnterFrame = function() {
if (dragging) {
//find mouse y coordinate in relation to knob origin
a = _root._ymouse-knob._y;
//find mouse x coordinate in relation to knob origin
b = _root._xmouse-knob._x;
//using arctangent find the spot of rotation (in degrees)
r = Math.atan2(a,b)*180/Math.PI;

//use current rotation and previous rotation
//to find acceleration
//averages the acceleration with the
//previous acceleration for smoother spins
accr = ((r - oldr) + accr)/2;
//apply the acceleration to the rotation
knob._rotation += accr;
//remember current rotation as old rotation
oldr = r;
feedbacka.text = a;
feedbackb.text = b;
}
else {
knob._rotation += accr;
//apply friction to acceleration force
//and if acceleration gets tiny, just set it to zero
if (Math.pow(accr, 2) &gt; .0001 ) {
accr *= damp;
}
else{
accr = 0;
}
}
//spit out feedback continuosly
feedbackr.text = knob._rotation;
feedbackaccr.text = accr;
}

I commented the code to explain what is happening, if you need more just post a comment. Let me know if you find this useful and what you end up making with it.

Downloads:

spin.fla and interactiveSpin.fla

  • del.icio.us
  • Digg
  • email
  • Facebook
  • Google Bookmarks
  • LinkedIn
  • Mixx
  • Print
  • PDF
  • StumbleUpon
  • Technorati
  • Twitter
  • RSS
14 Mar 2008

Interactive Spin Actionscript Tutorial

Author: Evan Mullins | Filed under: portfolio, tutorial