By Zevan | August 26, 2018
Creating a dictionary type object with ES6 Symbols is easy. Yes we have Maps and WeakMaps but this is still interesting for a variety of reasons… Being able to use objects as keys in another object (dictionary) has many great uses…. So how do you use Symbols like this?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
| let a = { id: Symbol('key') },
b = { id: Symbol('key') };
let dictionary = {
[a.id]: 'value by obj a',
[b.id]: 'value by obj b'
};
console.log(dictionary[a.id]);
console.log(dictionary[b.id]);
// outputs:
// 'value by obj a'
// 'value by obj b' |
By using either object a or object b’s `id` symbol, our dictionary points to another value. This old AS3 snippet is similar:
http://actionsnippet.com/?p=426
By Zevan | August 18, 2018
Being able to draw smooth lines that connect arbitrary points is something that I find myself needing very frequently. This is a port of an old snippet that does just that. By averaging control points of a quadratic bezier curve we ensure that our resulting Bezier curves are always smooth.
The key can be seen here with the `bezierSkin` function. It draws either a closed or open curve.
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
| // array of xy coords, closed boolean
function bezierSkin(bez, closed = true) {
var avg = calcAvgs(bez),
leng = bez.length,
i, n;
if (closed) {
c.moveTo(avg[0], avg[1]);
for (i = 2; i < leng; i += 2) {
n = i + 1;
c.quadraticCurveTo(bez[i], bez[n], avg[i], avg[n]);
}
c.quadraticCurveTo(bez[0], bez[1], avg[0], avg[1]);
} else {
c.moveTo(bez[0], bez[1]);
c.lineTo(avg[0], avg[1]);
for (i = 2; i < leng - 2; i += 2) {
n = i + 1;
c.quadraticCurveTo(bez[i], bez[n], avg[i], avg[n]);
}
c.lineTo(bez[leng - 2], bez[leng - 1]);
}
}
// create anchor points by averaging the control points
function calcAvgs(p) {
var avg = [],
leng = p.length, prev;
for (var i = 2; i < leng; i++) {
prev = i - 2;
avg.push((p[prev] + p[i]) / 2);
}
// close
avg.push((p[0] + p[leng - 2]) / 2);
avg.push((p[1] + p[leng - 1]) / 2);
return avg;
} |
The control points are then averaged to ensure that the curve contains no sharp angles.
Actionscript:
-
[SWF(width = 500, height=500)]
-
var ring:MovieClip = createRing();
-
ring.x = stage.stageWidth / 2;
-
ring.y = stage.stageHeight / 2;
-
addChild(ring);
-
-
function createRing(sectionNum:int = 30):MovieClip{
-
var container:MovieClip = new MovieClip();
-
container.circles = [];
-
container.theta = 0;
-
container.thetaDest = 0;
-
var step:Number = (Math.PI * 2) / sectionNum;
-
for (var i:int = 0; i<sectionNum; i++){
-
var c:MovieClip = new MovieClip();
-
with (c.graphics){
-
lineStyle(0,0x000000);
-
beginFill(0xCCCCCC);
-
drawCircle(0,0,20);
-
}
-
c.thetaOffset = step * i;
-
container.addChild(c);
-
container.circles.push(c);
-
}
-
container.addEventListener(Event.ENTER_FRAME, onRun);
-
return container;
-
}
-
function onRun(evt:Event):void {
-
var container:MovieClip = MovieClip(evt.currentTarget);
-
var num:int = container.circles.length;
-
for (var i:int = 0; i<num; i++){
-
var c:MovieClip = container.circles[i];
-
var angle:Number = container.theta + c.thetaOffset;
-
c.x = 200 * Math.cos(angle);
-
c.y = 100 * Math.sin(angle);
-
c.scaleX = (100 + c.y) / 120 + 0.2;
-
c.scaleY = c.scaleX;
-
}
-
container.circles.sortOn("y", Array.NUMERIC);
-
for (i = 0; i<num; i++){
-
container.addChild(container.circles[i]);
-
}
-
if (container.mouseX <-100){
-
container.thetaDest -= 0.05;
-
}
-
if (container.mouseX> 100){
-
container.thetaDest += 0.05;
-
}
-
container.theta += (container.thetaDest - container.theta) / 12;
-
-
}
This snippet shows how to create a 3D ring navigation using sine and cosine. Have a look: