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
|
{
const MARKER_COUNT = 16;
const ROOT = window.getComputedStyle(document.documentElement);
const ANGLE_INCREMENT = Two.Utils.TWO_PI / MARKER_COUNT;
const REM = parseInt(ROOT.fontSize);
const COLOR_SQUARE_SIZE = REM;
const MARKER_LINE_LENGTH = REM / 2;
const MARKER_MARGIN = REM * 2.5;
const RADIUS = REM * 10;
///////////
// Setup //
///////////
const two = new Two({
autostart: true,
fitted: true,
}).appendTo(document.currentScript.parentNode);
const center = new Two.Vector(two.width, two.height).divide(2);
////////////
// Circle //
////////////
const circle = two.makeCircle(center.x, center.y, RADIUS);
circle.fill = "transparent";
circle.stroke = Colors.gray[700];
/////////////
// Vectors //
/////////////
const dotProductProjection = two.makeLine();
dotProductProjection.dashes = [REM / 2];
dotProductProjection.position = center.clone();
dotProductProjection.stroke = Colors.gray[700];
// Static vector.
two.makeVector({
color: Colors.green[500],
position: center.clone(),
value: Two.Vector.up.clone().multiply(RADIUS),
});
const dotProductVector = two.makeVector({
color: Colors.blue[500],
position: center.clone(),
value: Two.Vector.zero.clone(),
});
const movingVector = two.makeVector({
color: Colors.red[500],
drawCircle: true,
position: center.clone(),
value: Two.Vector.zero.clone(),
});
//////////
// Text //
//////////
const topLeftTextStyle = {
alignment: "left",
baseline: "top",
family: "Hack",
fill: Colors.gray[50],
size: REM,
};
two.makeText("a.length() = 1.00", REM * 3, REM * 1.75, topLeftTextStyle);
two.makeText("b.length() = 1.00", REM * 3, REM * 3.75, topLeftTextStyle);
const dotProductText = two.makeText("", REM * 3, REM * 5.75, topLeftTextStyle);
const redSquare = two.makeRectangle(REM * 1.5, REM * 1.5, COLOR_SQUARE_SIZE, COLOR_SQUARE_SIZE);
redSquare.fill = Colors.red[500];
redSquare.stroke = "transparent";
const greenSquare = two.makeRectangle(REM * 1.5, REM * 3.5, COLOR_SQUARE_SIZE, COLOR_SQUARE_SIZE);
greenSquare.fill = Colors.green[500];
greenSquare.stroke = "transparent";
const blueSquare = two.makeRectangle(REM * 1.5, REM * 5.5, COLOR_SQUARE_SIZE, COLOR_SQUARE_SIZE);
blueSquare.fill = Colors.blue[500];
blueSquare.stroke = "transparent";
for (let i = 0; i < MARKER_COUNT; i++) {
const angle = ANGLE_INCREMENT * i;
const x = Math.cos(angle);
const y = Math.sin(angle);
const direction = new Two.Vector(x, y);
const border = direction.clone().multiply(RADIUS).add(center);
const borderOffset = direction.clone().multiply(MARKER_LINE_LENGTH);
const line = two.makeLine(
border.x,
border.y,
border.x + borderOffset.x,
border.y + borderOffset.y
);
line.stroke = Colors.gray[700];
const dotProduct = direction.dot(Two.Vector.up).toFixed(2);
const textOffset = direction.multiply(MARKER_MARGIN);
const textPosition = border.add(textOffset);
two.makeText(dotProduct, textPosition.x, textPosition.y, {
family: "Hack",
fill: Colors.gray[50],
size: REM,
});
}
let angle = 0.0;
two.bind("update", () => {
angle = (angle - two.timeDelta / 1000.0) % Two.Utils.TWO_PI;
const x = Math.cos(angle) * RADIUS;
const y = Math.sin(angle) * RADIUS;
const a = new Two.Vector(x, y).normalize();
const dotProduct = a.dot(Two.Vector.up).toFixed(2);
movingVector.value.x = x;
movingVector.value.y = y;
dotProductVector.value.y = y;
dotProductProjection.vertices[0].x = dotProductVector.value.x;
dotProductProjection.vertices[0].y = dotProductVector.value.y;
dotProductProjection.vertices[1].x = movingVector.value.x;
dotProductProjection.vertices[1].y = movingVector.value.y;
dotProductText.value = `a.dot(b) = ${dotProduct}`;
});
}
|