pirika logo

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

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

2022.2.26

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

2-3:デザインしたオブジェクト(球)をキャンバスに

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もグローバル変数です。)

それをキャンバスに描いて見ましょう。
2-2で描いたものと同じ球が描ければ成功です。
このようにして作成した球のデータは第5時限でも使います。

マウス(タッチ)を使って球を移動

この画面の球の上でマウスの左ボタンを押して、押し続けたままマウスを動かして見てください。これを、マウスをドラッグするといいます。
マウスボタンを押してからちょっと時間を置いてから動かしましょう。(すぐ動かすとうまく捕まえられません。) タブレットなどでは、指でタッチしてそのまま動かして見て下さい。
これは普通の美術のお絵描きとは随分違います。
絵を描く時に画用紙やキャンバスに絵筆で色をつけてしまうと、描いた場所や大きさはもう自由には変えられません。
コンピュータでは、キャンバス上のピクセル(光っている1つのドット)に色を指定して絵を描くと、できることは限られてしまいます。そうした絵のことをペイント系の絵と呼びます。
それに対して中心と半径を指定して円を描くようなものは、拡大縮小、移動などが自由なのでドロー系の絵と呼びます。
キャンバスの上でマウスの左ボタンを押して、押しっぱなしで動かすと(ドラッグすると)コンピュータはそれを検知できます。
何故なら、イベント(Event)を聴いて(Listener)とキャンバス(canvas)に耳をつけて(add)しているからです。

マウスとタッチのイベントリスナーは別々にプログラムしなければなりませんが、イベントへの対応はonMoveで共通になります。

canvas.addEventListener('mousemove', function(e) {//マウスイベントを聞く

        onMove(pos(e));
});

canvas.addEventListener('touchmove', function(e) {//タッチイベントを聞く
        e.preventDefault();
        if (e.changedTouches.length == 1) {
            onMove(pos(e.changedTouches[0]));//タッチイベントは[0]番目の指の動きを見る
        }
});

ページの中の座標とキャンバスの座標を次のpos関数で補正します。

function pos(e) {
    var x, y;

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

    return [x, y];
}

マウスがドラッグされている(タッチが動いている)間、onMove関数が呼ばれ続けます。

function onMove(pos) {
    event.preventDefault();
  
  x=pos[0];
  y=pos[1];

  // ドラッグが開始されていればオブジェクトの座標を更新して再描画
  if (dragging) {
    objX = x + relX;
    objY = y + relY;
    
    MyReDraw()
  }
}

そして一旦消去して、マウスの位置にMyReDraw()関数で新たに球を描きなおします。

function MyReDraw() {
  ctx.clearRect(0, 0, canvas.width, canvas.height); // キャンバスをクリア
  MyX=objX;
  MyY=objY;
  MyDraw();
}

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

<!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>


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

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


var MyRad=100;
var MyX=175;
var MyY=100;


init();
initLis();

function MyDraw(){
    ctx.clearRect(0, 0, canvas.width, canvas.height); 
    MyColor="rgb(255,165,0)";
    InitCx=MyX+MyRad*(223-175)/100;
    InitCy=MyY+MyRad*(64-100)/100;
    InitCr=0.1*MyRad;
    EndCx=MyX+0.25*MyRad;
    EndCy=MyY-0.25*MyRad;
    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();
}


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 MyReDraw() {
  ctx.clearRect(0, 0, canvas.width, canvas.height); // キャンバスをクリア
  MyX=objX;
  MyY=objY;
  MyDraw();
}


function initLis() {

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

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

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

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

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

//座標調整

function pos(e) {
    var x, y;

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

    return [x, y];
}

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


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

function onDown(pos) {
    event.preventDefault();
 
   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) {
    event.preventDefault();
  
  x=pos[0];
  y=pos[1];

  // ドラッグが開始されていればオブジェクトの座標を更新して再描画
  if (dragging) {
    objX = x + relX;
    objY = y + relY;
    
    MyReDraw()
  }
}


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

それでもグローバル変数っていうのがわかりにくいでしょう。

2-3-1 グローバル変数の変更

グローバル変数をスライダーを使って変更する方法を紹介します。

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


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