pirika logo

ホームページ Pirikaで化学 ブログ 業務案内 お問い合わせ
情報化学+教育トップ 情報化学 MAGICIAN MOOC プログラミング
高校生レベルのプログラミングはMAGICIAN-Jrへどうぞ。
フィードバックはお問い合わせフォームからお願いします。

プログラミング・トップ > 化学,薬学系の親子で楽しみながらプログラミング > 第2時限:美術

2022.2.26

Pirika.comでプログラミング
山本博志

2-3-1:デザインしたオブジェクト(球)

2-2でデザインした球(▶︎をクリックして開く)

var MyRad=100;
var MyX=175;
var MyY=100;
function MyDraw(){
    MyColor="rgb(255,165,0)";
    var InitCx=MyX+MyRad*(223-175)/100;
    var InitCy=MyY+MyRad*(64-100)/100;
    var InitCr=0.1*MyRad;
    var EndCx=MyX+0.25*MyRad;
    var EndCy=MyY-0.25*MyRad;
    var EndCr=0.75*MyRad;
    ctx.beginPath(); 
    ctx.arc(MyX, MyY, MyRad, 0, Math.PI*2, true);
    var gradient2=ctx.createRadialGradient(InitCx,InitCy,InitCr,EndCx,EndCy,EndCr);
    gradient2.addColorStop(0.0,"#EEEEEE");
    gradient2.addColorStop(1.0,MyColor);
    ctx.fillStyle = gradient2; 
    ctx.fill();
}

MyRadに100、MyXに175、MyYに100を入れています。
この3つは難しい言い方をすると、グローバル変数と言います。MyDrawという絵を描く関数の外側で定義されていて、他の関数の中でも変数として使えます。(実際にはMyColorもグローバル変数です。)

グローバル変数に対応する変数はローカル変数と言います。これは定義された関数の中だけで使えます。

<script>
 var グローバル変数=100;
 
 function MyFA{
    var MyFAローカル変数=50;
    var 答え = MyFAローカル変数 + グローバル変数
    //”答え”は150になる。
 }

function MyFB{
    var MyFBローカル変数=50;
    var 答え = MyFBローカル変数 + MyFAローカル変数
    //エラー: MyFAローカル変数は他の関数では参照できない。
}

</script>

円は日本中どこでも使えますが、地域振興券はその地域の中でしか使えないような物です。

スライダーを使った変数の変更

X
Y
半径

それでは実際に他の関数から、グローバル変数の値を変更して見ましょう。
スライダーを動かすにつれ、描画される位置や半径が変わります。
このスライダーオブジェクトは次のように記述されています。最小値minと最大値mxは自分に合わせて変更します。
何もプログラムを書く必要なく、スライダーを動かしたり、値を表示させたりできるのでとても簡単です。

//スライダーを表示・動作させる。
<input id="slider1" type="range" value="175 " min="10" max="490" oninput="this.nextSibling.value = this.value" onchange="this.nextSibling.value = this.value" /><input id="Xval" type="text" size="3" value="175" />

そうしてスライダーで変更された値を取り出すプログラムを作成します。
まず、html の中にあるスライダー要素を指定して、変化が起きた後に呼び出される関数を指定します。
スライダーの読み値は、S1Slider.valueの中に文字変数として入っているので、それを数値変数に変換して、MyXに代入します。
このようにグローバル変数を変更して、MyDraw関数を呼ぶと、指定した位置にオブジェクトを描画します。

<script>

let S1Slider = document.getElementById('slider1');//slider1のオブジェクトを指定します。
S1Slider.addEventListener('input', inputChange);//変化(イベント)が起きたら、inputChange関数を呼ぶ。

function inputChange(event){//スライダーに変化があったら呼ばれる。
  MyX=parseInt(S1Slider.value);//Slider.valueは文字列なので、paraseInt関数で整数に変換する。
  MyY=parseInt(S2Slider.value);
  MyRad=parseInt(S3Slider.value);
  MyDraw();//オブジェクトを描画する。
}

このように、inputChange関数の中で値を変更して描画(MyDraw)すると、変更した変数を使って描画します。

マウスを追いかける球

PC/Macでは、このキャンバス内で、マウスがどこにいるかをプログラムは知る事ができます。
しかし、タッチは今どこにいるかはわからないので、タッチしたまま動かさないと次のプログラムは動きません。

このキャンバス内でマウス(タッチ)を動かすと、ボタンを押していなくてもマウスの位置を検出する事ができます。(押していても検出できます)
そこで球はマウスが動いている時には追いかけますが、止まると追いかけません。

canvas2.addEventListener('mousemove', function(e) {//マウス動き

        onMove(pos(e));
    });

canvas2.addEventListener('touchmove', function(e) {//タッチ動き
        e.preventDefault();
        if (e.changedTouches.length == 1) {
            onMove(pos(e.changedTouches[0]));//指[0]の動き
        }
    });


function onMove(pos) {//マウス、タッチ共通
  x=pos[0];
  y=pos[1];
  
            MyX2 += (x-MyX2)*0.05;
            MyY2 += (y-MyY2)*0.05;
            MyDraw2();
        
        var message = 'Mouse position X:' + x + ', Y:' +y;
          PrintPosition(canvas2, message);

}

球の代わりに猫の絵にしたり、マウスのポインターをネズミに変えたりして遊べます。

完成形プログラム(▶︎をクリックして開く)

<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="UTF-8">
    <title></title>
  </head>
  <body>
  <h1>グローバル変数</h1>


<canvas id="canvas" width="500" height="350" style="border:1px solid #CCC;"></canvas>

<div class="example-box">
                <table>
                    <tr>
                        <th>X</th>
                        <td><input id="slider1" type="range"  min="10" max="490" oninput="this.nextSibling.value = this.value" onchange="this.nextSibling.value = this.value" /><input id="Xval" type="text" size="3" value="175" /></td>
                    </tr>
                    <tr>
                        <th>Y</th>
                        <td><input id="slider2" type="range" value="100 " min="10" max="340" oninput="this.nextSibling.value = this.value" onchange="this.nextSibling.value = this.value" /><input id="Yval" type="text" size="3" value="100 "/></td>
                    </tr>
                    <tr>
                        <th>半径</th>
                        <td><input id="slider3" type="range" value="100 " min="10" max="100" oninput="this.nextSibling.value = this.value" onchange="this.nextSibling.value = this.value" /><input id="Rval" type="text" size="3" value="100 "/></td>
                    </tr>
                </table>
            </div>

<canvas id="canvas2" width="500" height="350" style="border:1px solid #CCC;"></canvas>

 
<script type="text/javascript">
// set up canvas

const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');

const canvas2 = document.getElementById('canvas2');
const ctx2 = canvas2.getContext('2d');


let S1Slider = document.getElementById('slider1');//slider1のオブジェクトを取り出す。
S1Slider.addEventListener('input', inputChange);//変化(イベント)が起きたら、inputChange関数を呼ぶ。
let S2Slider = document.getElementById('slider2');
S2Slider.addEventListener('input', inputChange);
let S3Slider = document.getElementById('slider3');
S3Slider.addEventListener('input', inputChange);

var MyRad=100;
var MyX=170;
var MyY=100;

function inputChange(event){//スライダーに変化があったら呼ばれる。
  MyX=parseInt(S1Slider.value);//Slider.valueは文字列なので、paraseInt関数で整数に変換する。
  MyY=parseInt(S2Slider.value);
  MyRad=parseInt(S3Slider.value);
  MyDraw()
}
S1Slider.value=""+MyX;
S2Slider.value=""+MyY;
S3Slider.value=""+MyRad;

//MyDraw();
function MyDraw(){
    ctx.clearRect(0, 0, canvas.width, canvas.height); 
    MyColor="rgb(255,165,0)";
    var InitCx=MyX+MyRad*(223-175)/100;
    var InitCy=MyY+MyRad*(64-100)/100;
    var InitCr=0.1*MyRad;
    var EndCx=MyX+0.25*MyRad;
    var EndCy=MyY-0.25*MyRad;
    var EndCr=0.75*MyRad;
    ctx.beginPath(); 
    ctx.arc(MyX, MyY, MyRad, 0, Math.PI*2, true);
    var gradient2=ctx.createRadialGradient(InitCx,InitCy,InitCr,EndCx,EndCy,EndCr);
    gradient2.addColorStop(0.0,"#EEEEEE");
    gradient2.addColorStop(1.0,MyColor);
    ctx.fillStyle = gradient2; 
    ctx.fill();
    objX = MyX;
    objY = MyY;
    objWidth = MyRad;
}

var MyRad2=20;
var MyX2=170;
var MyY2=100;

function MyDraw2(){
    ctx2.clearRect(0, 0, canvas2.width, canvas2.height); 
    MyColor="rgb(255,165,0)";
    var InitCx=MyX2+MyRad2*(223-175)/100;
    var InitCy=MyY2+MyRad2*(64-100)/100;
    var InitCr=0.1*MyRad2;
    var EndCx=MyX2+0.25*MyRad2;
    var EndCy=MyY2-0.25*MyRad2;
    var EndCr=0.75*MyRad2;
    ctx2.beginPath(); 
    ctx2.arc(MyX2, MyY2, MyRad2, 0, Math.PI*2, true);
    var gradient2=ctx2.createRadialGradient(InitCx,InitCy,InitCr,EndCx,EndCy,EndCr);
    gradient2.addColorStop(0.0,"#EEEEEE");
    gradient2.addColorStop(1.0,MyColor);
    ctx2.fillStyle = gradient2; 
    ctx2.fill();
    
}





var objX, objY;
var objWidth, objHeight;

function init() {
  // オブジェクトの大きさを定義 
  objWidth = MyRad;
  objHeight = MyRad;

  // オブジェクトの座標を定義(キャンバスの中央に表示)
  objX = MyX;
  objY = MyY;

  // オブジェクトを描画
  MyDraw();
}
/////////////////////////////////////ボールが追いかける

var x, y, relX, relY;
var dragging = false;


function initLis() {

    canvas2.addEventListener('mousedown', function(e) {

        onDown(pos(e));
    });
    canvas2.addEventListener('mouseup', function(e) {
        onUp(pos(e));
    });

    canvas2.addEventListener('mousemove', function(e) {

        onMove(pos(e));
    });
    canvas2.addEventListener('touchstart', function(e) {
        if (e.changedTouches.length == 1) {
            onDown(pos(e.changedTouches[0]));
        }
    });

    canvas2.addEventListener('touchend', function(e) {
        if (e.changedTouches.length == 1) {
            onUp(pos(e.changedTouches[0]));
        }
    });
    canvas2.addEventListener('touchmove', function(e) {
        e.preventDefault();
        if (e.changedTouches.length == 1) {
            onMove(pos(e.changedTouches[0]));
        }
    });
    canvas2.addEventListener('touchcancel', function(e) {
        mOut();
    });
}

//座標調整
function pos(e) {
    var x, y;

    x = e.clientX - canvas2.getBoundingClientRect().left;
    y = e.clientY - canvas2.getBoundingClientRect().top;

    return [x, y];
}

function onDown(pos) {
  x=pos[0];
  y=pos[1];

  // オブジェクト上の座標かどうかを判定
  if (objX < x && (objX + objWidth) > x && objY < y && (objY + objHeight) > y) {
    dragging = true; // ドラッグ開始
    relX = objX - x;
    relY = objY - y;
  }
}

function onMove(pos) {
  x=pos[0];
  y=pos[1];
  
  MyX2 += (x-MyX2)*0.05;
            MyY2 += (y-MyY2)*0.05;
            MyDraw2();
        
        var message = 'Mouse position X:' + x + ', Y:' +y;
          PrintPosition(canvas2, message);

}

function onUp(pos) {
  dragging = false; // ドラッグ終了
}

function mOut(pos) {
    dragging = false; // ドラッグ終了
}       

init();
initLis();

function PrintPosition(canvas, message) {
        var context = canvas.getContext('2d');
        context.clearRect(0, 0, canvas.width, 50);
        context.font = '12pt "MSゴシック"';
        context.fillStyle = 'black';
        context.fillText(message, 32, 15);
    }

</script>
  </body>
</html>

次は動きをつけてみましょう

プログラミング・トップ > 化学,薬学系の親子で楽しみながらプログラミング


Copyright pirika.com since 1999-
Mail: yamahiroXpirika.com (Xを@に置き換えてください) メールの件名は[pirika]で始めてください。