波の式
y-xグラフとy-tグラフの意味や両者の違いを理解させるための教材。
y-xグラフの赤い円を動かすと、y-tグラフの対象となるx座標が変わります。
y-tグラフの赤い円を動かすと、y-xグラフの時刻が変わります。
playボタンを押すと、時間が進みます。
/**
* Copyright Nicolas ( http://wonderfl.net/user/Nicolas )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/a046
*/
package {
import flash.display.Sprite;
import flash.events.Event;
import flash.text.TextField;
import com.bit101.components.*;
[SWF(width="465", height="465", frameRate="60")]
public class Main extends Sprite {
public var yxChart:Chart;
public var ytChart:Chart;
public var amplitude:Number = 50;
public var lambda:Number = 50;
public var term:Number = 5;
public var time:Number = 0;
public var pos:Number = 0;
public var initialPhase:Number = 0;
public var vec:Vector.<Number>;
public var playing:Boolean = false;
private var timeLabel:TextField;
private var posLabel:TextField;
public function Main() {
//波の式
var waveEquation:TextField = addChild(new TextField()) as TextField;
waveEquation.text = "y=Asin{2π(t/T - x/λ)+φ}";
waveEquation.width = 200;
waveEquation.x = 10;
waveEquation.y = 100;
waveEquation.scaleX = waveEquation.scaleY = 1.8;
var panel:Panel = new Panel(this, 10, 200);
panel.width = 225;
panel.height = 155;
//振幅
var amplitudeLabel:TextField = panel.addChild(new TextField()) as TextField;
amplitudeLabel.text = "A:振幅";
amplitudeLabel.x = 10;
amplitudeLabel.y = 20;
amplitudeLabel.selectable = false;
var amplitudeNS:NumericStepper = new NumericStepper(panel, 110, 20, function(e:Event):void {
amplitude = amplitudeNS.value;
});
amplitudeNS.value = amplitude;
amplitudeNS.minimum = 10;
//波長(波1個分の長さ)
var lambdaLabel:TextField = panel.addChild(new TextField()) as TextField;
lambdaLabel.text = "λ:波長";
lambdaLabel.x = 10;
lambdaLabel.y = 45;
lambdaLabel.selectable = false;
var lambdaNS:NumericStepper = new NumericStepper(panel, 110, 45, function(e:Event):void {
lambda = lambdaNS.value;
});
lambdaNS.value = lambda;
lambdaNS.minimum = 1;
//周期(振動1回にかかる時間)
var termLabel:TextField = panel.addChild(new TextField()) as TextField;
termLabel.text = "T:周期";
termLabel.x = 10;
termLabel.y = 70;
termLabel.selectable = false;
var termNS:NumericStepper = new NumericStepper(panel, 110, 70, function(e:Event):void {
term = termNS.value;
});
termNS.value = term;
termNS.step = 0.1;
termNS.minimum = 1;
//初期位相(時刻t=0での振動の進み具合)
var initialPhaseLabel:TextField = panel.addChild(new TextField()) as TextField;
initialPhaseLabel.text = "φ:初期位相(度)";
initialPhaseLabel.x = 10;
initialPhaseLabel.y = 95;
initialPhaseLabel.selectable = false;
var initialPhaseNS:NumericStepper = new NumericStepper(panel, 110, 95, function(e:Event):void {
initialPhase = initialPhaseNS.value;
});
initialPhaseNS.value = initialPhase;
initialPhaseNS.step = 5;
initialPhaseNS.minimum = -180;
initialPhaseNS.maximum = 180;
//PLAY
var playBtn:PushButton = new PushButton(panel, 10, 120, "play", function(e:Event):void {
playing = !playing;
if (playing) playBtn.label = "pause";
if (!playing) playBtn.label = "play";
});
//RESET
var resetBtn:PushButton = new PushButton(panel, 115, 120, "reset", function(e:Event):void {
playing = false;
playBtn.label = "play";
time = 0;
timeLabel.text = "y-xグラフ (t=0)";
ytChart.position = 0;
});
//y-xグラフのラベル
timeLabel = addChild(new TextField()) as TextField;
timeLabel.text = "y-xグラフ (t=0)";
timeLabel.x = 250;
timeLabel.y = 0;
timeLabel.selectable = false;
timeLabel.width = 300;
timeLabel.scaleX = timeLabel.scaleY = 1.5;
//y-tグラフのラベル
posLabel = addChild(new TextField()) as TextField;
posLabel.text = "y-tグラフ (x=0)";
posLabel.x = 250;
posLabel.y = 235;
posLabel.selectable = false;
posLabel.width = 300;
posLabel.scaleX = posLabel.scaleY = 1.5;
//y-xグラフ(時刻tにおける波形)
yxChart = new Chart("x", "y", 0x000000);
addChild(yxChart);
yxChart.x = 250;
yxChart.y = 30;
yxChart.originY = 100;
yxChart.addEventListener(Event.CHANGE, function(e:Event):void {
pos = yxChart.position;
posLabel.text = "y-tグラフ (x=" + String(pos) + ")";
});
//y-tグラフ(位置xにある媒質の振動)
ytChart = new Chart("t", "y", 0x000000);
addChild(ytChart);
ytChart.x = 250;
ytChart.y = 265;
ytChart.originY = 100;
addEventListener(Event.ENTER_FRAME, onEnterFrame);
}
public function onEnterFrame(e:Event):void {
if (playing) {
time += 1 / 60;
} else {
time = ytChart.position / 10;
}
timeLabel.text = "y-xグラフ (t=" + String(int(time * 10) / 10) + ")";
vec = new Vector.<Number>();
for (var xx:int = 0; xx < 200; xx++) {
vec.push(xx, amplitude * Math.sin((2 * Math.PI * (time / term - xx/ lambda) + initialPhase * Math.PI / 180)));
}
yxChart.plot(vec);
yxChart.position = yxChart.position;//赤円の位置を再計算
vec = new Vector.<Number>();
for (var t:int = 0; t < 200; t++) {
vec.push(t, amplitude * Math.sin((2 * Math.PI * (t/10 / term - pos/ lambda) + initialPhase * Math.PI / 180)));
}
ytChart.plot(vec);
ytChart.position = time * 10;
}
}
}
import flash.display.Graphics;
import flash.display.Shape;
import flash.display.Sprite;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.text.TextField;
class Chart extends Sprite {
private var _position:int = 0;
private var yAxis:Shape;
private var xAxis:Shape;
private var yLabel:TextField;
private var xLabel:TextField;
private var _originX:Number = 0;
private var _originY:Number = 0;
private var _color:uint = 0x000000;
private var point:Sprite;
private var pointSelected:Boolean = false;
private var vec:Vector.<Number> = new Vector.<Number>();
public function Chart(xLabelText:String, yLabelText:String, color:uint = 0x000000, width:Number = 200, height:Number = 200) {
var g:Graphics;
_color = color;
//軸
xAxis = new Shape();
xAxis.y = height -_originY;
g = xAxis.graphics;
g.lineStyle(2, _color);
g.moveTo(0, 0);
g.lineTo(width, 0);
addChild(xAxis);
yAxis = new Shape();
g = yAxis.graphics;
g.lineStyle(2, _color);
g.moveTo(0, 0);
g.lineTo(0, height);
addChild(yAxis);
xLabel = addChild(new TextField()) as TextField;
xLabel.x = width + 5;
xLabel.text = xLabelText;
yLabel = addChild(new TextField()) as TextField;
yLabel.y = 0;
yLabel.x = _originX;
yLabel.text = yLabelText;
point = new Sprite();
g = point.graphics;
g.beginFill(0xFF0000);
g.drawCircle(0, 0, 5);
addChild(point);
point.x = 0;
point.y = height;
point.addEventListener(MouseEvent.MOUSE_DOWN, startMoving);
point.buttonMode = true;
}
public function plot(xyList:Vector.<Number>):void {
vec = xyList;
var g:Graphics = graphics;
g.clear();
g.lineStyle(2, _color);
g.moveTo(xyList[0] - originX, height - originY - xyList[1]);
var len:int = xyList.length;
for (var i:int = 2; i < len; i += 2) {
g.lineTo(xyList[i] - originX, height - originY - xyList[i + 1]);
}
}
public function clear():void {
graphics.clear();
}
public function startMoving(e:MouseEvent):void {
pointSelected = true;
addEventListener(Event.ENTER_FRAME, move);
stage.addEventListener(MouseEvent.MOUSE_UP, function(e:MouseEvent):void {
pointSelected = false;
removeEventListener(Event.ENTER_FRAME, move);
stage.removeEventListener(MouseEvent.MOUSE_UP, arguments.callee);
});
}
//MouseXに応じたy座標を計算し、赤円の位置をそこに持っていく
public function move(e:Event):void {
if (!pointSelected) return;
position = mouseX;
}
public function get originX():Number { return _originX; }
public function set originX(value:Number):void
{
_originX = value;
yAxis.x = value;
yLabel.x = value;
point.x = value;
}
public function get originY():Number { return _originY; }
public function set originY(value:Number):void
{
_originY = value;
xAxis.y = height - value;
xLabel.y = height - value;
point.y = height - value;
}
public function get position():int { return _position; }
//valueに応じたy座標を計算し、赤円の位置をそこに持っていく
public function set position(value:int):void
{
if (value < 0) return;
if (vec.length - 1 < value * 2 + 1) return;
_position = value;
point.x = _position;
point.y = height - _originY - vec[_position * 2 + 1];
dispatchEvent(CHANGE_EVENT);
}
private const CHANGE_EVENT:Event = new Event(Event.CHANGE);
}