Canvas時計を描く

10949 ワード

  • 前言
  • 関連ジオメトリ
  • 時計面関数
  • 時計回り
  • 画分針秒針中心点関数
  • リアルタイム
  • を描画
  • 最適化

  • 前言
    何を勉強しても、手を出さないと、永遠にマスターできない.canvas APIを勉強すると、直線や円などの画法で描くだけで、canvasは簡単すぎると思います.しかし、本当に絵を描くと、多くの問題に直面します.
    次に紹介するのはcanvas時計で、主にみんなと私の学習過程を分かち合います.
    canvasの学友を知らないで、先に学びます:Canvasキャンバス
    関連ジオメトリ
    時計は1つの円で、主に1時間あたりの数字と目盛りを含んで、それらの位置座標はどのように計算しますか?
    上の図から容易に得られる:−x=r*cos(角度)−y=r*sin(角度)Math対象内のsin()cos()の方法は弧を使用しているので、変換が必要です
    しかし、今回の使用では実際には使われていない.時計の目盛りなどは等比例で区切られているため、2 PIを目盛り数などで割るだけで相応の弧度が得られる.
    時計回り、分針、秒針は、いずれも直線が一定の角度を回転させることで得られる
    けいじょうかんすう
    canvasキャンバスを使用するには、まず図面コンテキスト環境を取得する必要があります.
    var canvas = document.getElementById('clock');
    var cxt = canvas.getContext('2d');
    var width = canvas.width;
    var height = canvas.height;
    var r = width / 2;

    canvas要素の幅の高さを取得し、半径rを最大の半径、すなわち幅の半分として定義します.
    function drawBg() {
      //    
      cxt.save();
      cxt.translate(r,r);
    
      //      
      cxt.beginPath();
      cxt.arc(0, 0, r - 5, 0, 2*Math.PI, true);
      cxt.lineWidth = 8;
      cxt.stroke();
    
      //    
      var hour = [3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 1, 2];
    
      hour.forEach(function(num,i){
        var rad = 2 * Math.PI / 12 * i;
        var x = Math.cos(rad) * (r - 30);
        var y = Math.sin(rad) * (r - 30);
        cxt.font = "18px sans-serif"
        cxt.textAlign = "center";
        cxt.textBaseline = "middle";
        cxt.fillText(num, x, y);
      });
    
      //    
      for (var i = 0; i < 60; i++) {
        var rad = 2 * Math.PI / 60 * i;
        var x = Math.cos(rad) * (r - 18);
        var y = Math.sin(rad) * (r - 18);
    
        cxt.beginPath();
        if(i%5 == 0){
          cxt.fillStyle = "#000";
          cxt.arc(x, y, 2, 0, 2*Math.PI, true);
        }
        else {
          cxt.fillStyle = "#bbb";
          cxt.arc(x, y, 2, 0, 2*Math.PI, true);
        }   
        cxt.fill();
      }
    }

    ポイント:-cxt.save()ここには元の原点位置が保存されています.canvasをクリアするときにcxt.clearRect()メソッドを簡単に呼び出すためです.
  • cxt.translate(r,r)は、原点を(r,r)位置に置く.すべての目盛り数などが同心円を中心に行われるため、原点を円心上に置くのは、位置座標の計算を容易にするためである.なお、この方法では、後の図面がこの原点に基づいて
  • を描画する
  • 図面を描くごとに、ブラシなどの繰り返しを避けるために、新しいパスを開くことに注意してください.
  • 時間の数字を3から描き、時計回りに描くのは、canvasの座標系が右にx正軸、下にy正軸であるため、sin()cos()の正負値がxyの正負値に対応しないようにするためです.
  • cxt.textAlign = "center"cxt.textBaseline = "middle"は、テキストの位置合わせ方法であり、設定しないと時間数のオフセット
  • につながる.
    時計の針を引く
    //    
    function drawHour(hour, minute) {
      cxt.save();
      var rad = 2 * Math.PI / 12 * hour + 2 * Math.PI / 12 * minute / 60;
      cxt.beginPath();
      cxt.rotate(rad);
      cxt.moveTo(0, 15);
      cxt.lineTo(0, -r/2);
      cxt.lineWidth = 5;
      cxt.lineCap = "round";
      cxt.stroke();
      cxt.restore();
    }

    ポイント:-回転するたびに後の描画に影響するため、ここで描画環境を保存し、描画時計回りの終了後に元の描画環境にリセットします.
  • 時計回りの回転は分数の影響を受けることを忘れないでください.
    画分針、秒針、中心点関数
    //    
    function drawMinute(minute) {
      cxt.save();
      var rad = 2 * Math.PI / 60 * minute;
      cxt.beginPath();
      cxt.rotate(rad);
      cxt.moveTo(0, 18);
      cxt.lineTo(0, -r + 40);
      cxt.lineWidth = 3;
      cxt.lineCap = "round";
      cxt.stroke();
      cxt.restore();
    }
    //    
    function drawSecond(second) {
      cxt.save();
      var rad = 2 * Math.PI / 60 * second;
      cxt.beginPath();
      cxt.rotate(rad);
      cxt.moveTo(0, 25);
      cxt.lineTo(2, 25);
      cxt.lineTo(-2, 25);
      cxt.lineTo(-1, -r + 25);
      cxt.lineTo(1, -r + 25);
      cxt.lineTo(2, 25);
      cxt.lineWidth = 1;
      cxt.fillStyle = "#f00";
      cxt.fill();
      cxt.restore();
    }
    //     
    function drawDot() {
      cxt.beginPath();
      cxt.arc(0, 0, 4, 0, 2*Math.PI,true);
      cxt.fillStyle = "#fff";
      cxt.fill();
    }
    :-図面環境を上の時計回りに保存します.
    リアルタイムの描画
    //       
    function draw() {
      cxt.clearRect(0, 0, width, height);
      var now = new Date();
      var hour = now.getHours();
      var minute = now.getMinutes();
      var second = now.getSeconds();
      drawBg();
      drawHour(hour,minute);
      drawMinute(minute);
      drawSecond(second);
      drawDot();
      cxt.restore();
    }
    
    draw();
    setInterval(function(){ 
      draw();   
    },1000);

    ポイント:-cxt.restore()ここでリセットされているのは時計を描くときに保存されている描画環境です.原点をデフォルトにリセットしてから、矩形領域をクリアする方法を使用します.
  • cxt.clearRect(0, 0, width, height) canvas領域をクリアし、再描画します.毎回描かれている時計回りや分針などは、残されているので、
  • をクリアします
  • setInterval()メソッドを呼び出す前に、ペイントを呼び出す必要があります.そうしないと、1秒遅れた表示
  • が表示されます.
    最適化
    現在の時計回りは200pxの正方形に基づいて描かれています.では、幅を大きくすると、どうなるのでしょうか.600px:
    時計の針は醜くなり、大きさは比例しない、つまり歪みです.
    では、どうすれば歪まないことができますか?
    クロックは正方形の領域であり、円の体現であるため、すべての関連する大きさは半径または幅に比例するだけで実現することができる.
    まず、それらのスケール関係を計算します.
    200 / width = 13 / length

    すなわち、200pxの幅において13pxの大きさとして表現される場合、widthの幅においてlengthの大きさとして表現されるべきである.
    すなわち、length = 13 * width/200得られる比例関係は、width/200である.
    スケールを定義します.
    var rem = width / 200;

    後の各関数において,関連する大きさにこの比例関係を乗じるだけで実現でき,どんなに幅の広いクロックでも完璧に表現できる.