-
Notifications
You must be signed in to change notification settings - Fork 0
/
concave-mirror.html
283 lines (240 loc) · 13 KB
/
concave-mirror.html
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
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>凹面鏡のはたらき</title>
</head>
<body onLoad="loopd()">
<h2>凹面鏡のはたらき(PC用サイト)</h2>
光線の本数
<input type="range" value="20" min="10" max="300" step="1"
oninput="document.getElementById('output1').value=this.value * 2">
<output id="output1">40</output>
<input type="checkbox" name="sakuzu" id="sakuzu" value="sakuzu">作図用の線を描画する
<br>下の図形上でクリックすると全光線を描画します<br>
<canvas id="cv" style="background-color:rgb(163, 166, 167);">
図形を表示するには、canvasタグをサポートしたブラウザが必要です。
</canvas>
<br>2020.3.19 phys-ken作成
<script>
//領域
var cvs = document.getElementById("cv");
var ctx = cvs.getContext("2d");
cvs.width = document.documentElement.clientWidth - 10;
cvs.height = cvs.width * 9 / 16;
w = cvs.width;
h = cvs.height
//光源
var X = (1 / 6) * w; //初期座標 X
var Y = (1 / 2) * h; //初期座標y
var L = Math.sqrt(h * h + w * w); //対角線の長さ
//var honsu = 70; //光線の本数
var r = h / 20; //光源の半径
//スリット
slithole = h / 3; //スリットの穴の高さdef120
slitw = w / 50; //幅
slitx = w * 5 / 6; //スリットの位置
//レンズ
var f = w / 6; //焦点距離
var state; //全光線のstate
function loopd() {
setInterval(draw, 10);
}
function draw() {
var flag1 = document.getElementById("sakuzu").checked;
if (flag1 == true) {
sakuzustate = 1;;
} else {
sakuzustate = 0;
}
var ho = document.getElementById('output1');
var honsu = ho.value;
//クリック時のイベントを追加
cvs.addEventListener('click', function (e) {
if (state == 0) {
state = 1;;
} else {
state = 0;
}
});
//マウスの動きを取得
cvs.addEventListener("mousemove", (e) => {
var rect = e.target.getBoundingClientRect()
if (e.clientX - rect.left <= slitx) { //光源がスリットより右にいかないように制御
if (e.clientX - rect.left == slitx - f) { } else {//光源が焦点に来ないように制御
X = e.clientX - rect.left;
Y = e.clientY - rect.top;
}
}
});
ctx.clearRect(0, 0, w, h); //canvasの初期化
/////////////////////////////////////////////結像公式から、像の位置を求める////////////////////////////////////
var zouX;
var zouY;
var distXslit = slitx - X; //結像公式のa
var distzouX; //結像公式のb
var kh = Y - (h / 2);//光源の光軸からの高さh
var zouH;//像の光軸からの高さH
distzouX = (f * distXslit) / (distXslit - f);
zouX = slitx + -distzouX;
zouH = f * kh / (distXslit - f);
zouY = -1 * zouH + (h / 2);
/////////////////////////////////////////////結像公式から、像の位置を求める////////////////////////////////////
///////////////////////////////////////////////////////////////////////放射状に線を引く/////////////////////////////////////////////////////////////////
//まずは、縦線だけ引く
if (state == 0) {//stateが0だったら全体の光線、そうじゃなかったら代表線のみ
var L = Math.sqrt(h * h + w * w); //全体の光線を表示する場合
} else {
var L = 0; //代表線のみを表示する場合
}
X2 = X + L * Math.sin(Math.PI * 0);
Y2 = Y - L * Math.cos(Math.PI * 0);
ctx.beginPath(); // 1.Pathで描画を開始する
ctx.moveTo(X, Y); // 2.描画する位置を指定する
ctx.lineTo(X2, Y2);
ctx.strokeStyle = "yellow";
ctx.lineWidth = 3;
ctx.stroke();
//放射状に引く
for (var i = 1; i < 2 * (honsu); i++) {
if (state == 0) {
var L = Math.sqrt(h * h + w * w); //全体の光線を表示する場合
} else {
var L = 0; //代表線のみを表示する場合
}
if (i < (honsu)) {
takasa = (slitx - X) * Math.tan((Math.PI * i / honsu) + Math.PI / 2); //光面と光線の交点の高さ
yoko = slitx - X;//光面と光源の距離
if (Y + takasa < h / 2 + slithole / 2 && Y + takasa > h / 2 - slithole / 2) {
L = Math.sqrt(takasa * takasa + yoko * yoko);
}
}
X2 = X + L * Math.sin(Math.PI * i / honsu);//レンズとの交点のX座標
Y2 = Y - L * Math.cos(Math.PI * i / honsu);//レンズとの交点のy座標
ctx.beginPath(); // 1.Pathで描画を開始する
ctx.moveTo(X, Y); // 2.描画する位置を指定する
ctx.lineTo(X2, Y2);
ctx.strokeStyle = "yellow";
ctx.lineWidth = 3;
ctx.stroke(); // 4.Canvas上に描画する
var L = Math.sqrt(h * h + w * w);
//レンズより奥
if (X == slitx - f) {//光源が焦点にあるとき
if (Y + takasa < h / 2 + slithole / 2 && Y + takasa > h / 2 - slithole / 2) {//レンズより内側なら屈折
var L = Math.sqrt(h * h + w * w);
}
} else if (X >= slitx - f) {//光源が焦点とレンズの間にあるとき
if (Y + takasa < h / 2 + slithole / 2 && Y + takasa > h / 2 - slithole / 2) {//レンズより内側なら屈折
linemaker(X2, Y2, zouX, zouY, 0, "red");
}
} else {//光源が焦点より左にあるとき
if (Y + takasa < h / 2 + slithole / 2 && Y + takasa > h / 2 - slithole / 2) {//光線のうち、レンズの内側にある光線については、屈折させる。
linemaker(X2, Y2, zouX, zouY, 0, "red");
var L = Math.sqrt(h * h + w * w);
}
}
}
///////////////////////////////////////////////////////////////////////放射状に線を引いた/////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////光源/////////////////////////////////////////////////////////////////
// パスをリセット
ctx.beginPath();
// 円の中心座標: XY
// 半径: r
// 開始角度: 0度 (0 * Math.PI / 180)
// 終了角度: 360度 (360 * Math.PI / 180)
// 方向: true=反時計回りの円、false=時計回りの円
ctx.arc(X, Y, r, 0 * Math.PI / 180, 360 * Math.PI / 180, false);
// 塗りつぶしの色
ctx.fillStyle = "yellow";
// 塗りつぶしを実行
ctx.fill();
// 線の色
ctx.strokeStyle = "black";
// 線の太さ
ctx.lineWidth = 3;
// 線を描画を実行
ctx.stroke();
///////////////////////////////////////////////////////////////////////光源/////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////スクリーン/////////////////////////////////////////////////////////////
// パスをリセット
ctx.beginPath();
//色を指定する
ctx.fillStyle = "black"; //塗りつぶしの色は黒
//左から,上から,の位置に、幅,高さ,の四角形を描く
ctx.fillRect(w - (w / 30), 0, w / 30, h);
// 線を描画を実行
ctx.stroke();
//////////////////////////////////////////////////////////////スクリーン/////////////////////////////////////////////////////////////
/* /////////////////////////////////////////////////////////////スリット/////////////////////////////////////////////////////////////
// パスをリセット
ctx.beginPath();
//色を指定する
ctx.fillStyle = "black"; //塗りつぶしの色は黒
//左から,上から,の位置に、幅,高さ,の四角形を描く
ctx.fillRect(slitx, 0, slitw, h / 2 - slithole / 2); //スリット上部
ctx.fillRect(slitx, h / 2 + slithole / 2, slitw, h / 2 - slithole / 2); //スリット下部
// 線を描画を実行
ctx.stroke();
/////////////////////////////////////////////////////////////スリット///////////////////////////////////////////////////////////// */
/////////////////////////////////////////////////////////////焦点/////////////////////////////////////////////////////////////
// パスをリセット
ctx.beginPath();
//色を指定する
ctx.fillStyle = "black"; //塗りつぶしの色は黒
//左から,上から,の位置に、幅,高さ,の四角形を描く
blocksize = 10;
ctx.fillRect(slitx + f - (blocksize / 2), (h / 2) - blocksize / 2, blocksize, blocksize); //f
ctx.fillRect(slitx - f - (blocksize / 2), (h / 2) - blocksize / 2, blocksize, blocksize); //f
ctx.fillRect(slitx + 2 * f - (blocksize / 2), (h / 2) - blocksize / 2, blocksize, blocksize); //2f
ctx.fillRect(slitx - 2 * f - (blocksize / 2), (h / 2) - blocksize / 2, blocksize, blocksize); //2f
// 線を描画を実行
ctx.stroke();
/////////////////////////////////////////////////////////////焦点終わり/////////////////////////////////////////////////////////////
////////////////////////////////////////////光軸
ctx.beginPath(); // 1.Pathで描画を開始する
ctx.moveTo(0, h / 2); // 2.描画する位置を指定する
ctx.lineTo(w, h / 2);
ctx.strokeStyle = "black";
ctx.lineWidth = 2;
ctx.stroke();
////////////光軸終わり
/////////////凹面鏡をかく////////////////////////////////
lensw = 10;
ctx.beginPath();
ctx.lineWidth = 15;
//パスの開始座標を指定する
ctx.moveTo(slitx - lensw, (h / 2) - (slithole / 2));
//座標を指定してラインを引いていく quadraticCurveTo(cpx, cpy, x, y)
ctx.quadraticCurveTo(slitx + lensw, h / 2, slitx - lensw, (h / 2) + (slithole / 2));
//現在のパスを輪郭表示する
ctx.stroke();
/////////////凹面鏡を書いた////////////////////////////////
///////////////////////////////////sakuzustate==1のとき作図用の光線を引く///////////////////////////////////
if (sakuzustate == 1) {
linemaker(X, Y, slitx, h / 2, slitx, "blue");//凹面鏡の中心をとおる線
linemaker(slitx, h/2, X, h - Y, 0, "blue");//鏡の中心で跳ね返った線
linemaker(slitx, Y, slitx - f, h / 2, 0, "blue");//凹面鏡に平行な線(凹面鏡の奥)
linemaker(slitx, Y, slitx - f, h / 2, 0, "blue");//凹面鏡に平行な線(凹面鏡の奥)
linemaker(X, Y, slitx, Y, slitx, "blue");//凹面鏡に平行に入射する線
}
///////////////////////////////////////////////////////////////////////////////////
}
//始点と途中点の座標を指定することで、直線を引く。endは、終点のx座標
function linemaker(x1, y1, x2, y2, end, col) {
var y3 = ((y2 - y1) * (end - x1) / (x2 - x1)) + y1;
ctx.beginPath(); // 1.Pathで描画を開始する
ctx.moveTo(x1, y1); // 2.描画する位置を指定する
ctx.lineTo(end, y3);
ctx.strokeStyle = col;
ctx.lineWidth = 2;
ctx.stroke();
}
//始点と途中点の座標を指定することで、線分の終点の座標を取得する。
function endyget(x1, y1, x2, y2, end) {
var y3 = ((y2 - y1) * (end - x1) / (x2 - x1)) + y1;
return y3;
}
</script>
</body>
</html>