Canvasの基本的な使い方2【導入チュートリアル】

前回の記事ではキャンバス1の基本的な使い方をご覧ください。

1. 変換

変換する

  • キャンバスでは、css のような css2D 変換に似たいくつかの効果を適用することもできます。
  1. 変位
    • 文法:ctx.translate(x, y)
    • 注: 描画(ストロークまたは塗りつぶし)前に必ずディスプレイスメントを実行してください。
  2. ズーム
    • 文法:ctx.scale(x, y)
    • 注: 描画する前に必ず拡大縮小してください (ストロークまたは塗りつぶし)。
  3. 回転する
    • 文法:ctx.rotate(弧度值)
      • 角度からラジアンへの変換式:弧度 = Math.PI/180*角度
    • 注: 描画(ストロークまたは塗りつぶし)前に必ず回転してください。
    • 回転の中心はキャンバスの 0,0 点であり、回転の中心はディスプレイスメントで変更できます。

画像.png

  1. 知らせ:
    • キャンバスのすべての変形操作は、特定の形状を操作するだけではなく、キャンバス全体を変形します。
    • 複数のシェイプに対して異なる変換を実行する必要がある場合は、各描画前にブラシの状態を保存し、描画後にブラシの状態をリセットする必要があります。
      • ブラシの状態を保存:ctx.save();
        • 一般的な存在と変換の前に
      • ブラシの状態をリセット:ctx.restore();
        • 通常、変換後に存在します
// 绘制两个矩形
ctx.strokeRect(100, 100, 100, 100);
ctx.strokeRect(300, 100, 100, 100);

スクリーンショット 2023-07-09 22.15.46.png

// 对画布进行旋转
ctx.rotate(0.5);
ctx.strokeRect(100, 100, 100, 100);
ctx.strokeRect(300, 100, 100, 100);

スクリーンショット 2023-07-09 22.16.52.png

// 将 旋转和其中一个矩形绘制 存储为一次记录
ctx.save();
ctx.rotate(0.5);
ctx.strokeRect(100, 100, 100, 100);
ctx.restore();

ctx.strokeRect(300, 100, 100, 100);

スクリーンショット 2023-07-09 22.18.05.png

2. グラデーションカラー

  1. キャンバスのグラデーションカラーは、事前にグラデーション配色(カラー1からカラー2への遷移)を設定し、そのグラデーション配色を塗りつぶしスタイルに設定します。
  2. グラデーションフォーム
    • 線形勾配
      • グラデーションを作成します。const lg = ctx.createLinearGradient(起点x坐标, 起点y坐标, 终点x坐标, 终点y坐标)
        • グラデーションの範囲を指定する
      • グラデーションカラーを追加します。lg.addColorStop(0, 'red')
        • 指定した位置に色を追加します。0 は開始座標を意味し、1 は終了座標を意味します。中央部分は自動的にグラデーション色で塗りつぶされます。
  const canvas = document.querySelector(".mycanvas");

  canvas.width = 800;
  canvas.height = 400;

  const ctx = canvas.getContext("2d");

  const lg = ctx.createLinearGradient(0, 0, 800, 400);
  
  lg.addColorStop(0, 'red');
  lg.addColorStop(1, 'green');

  ctx.fillStyle = lg;
  ctx.fillRect(0, 0, 800, 400);

スクリーンショット 2023-07-09 22.47.33.png

  • 放射状グラデーション
    • グラデーションを作成します。const lg = ctx.createRadialGradient(x1, y1, r1, x2, y2, r2);
      • x1: 開始円の中心の x 軸座標
      • y1: 開始円の中心の y 軸座標
      • r1: 開始円半径
      • x2: 端円中心の x 軸座標
      • y2: 端円の中心のy軸座標
      • r2: 終端円半径
    • グラデーションカラーを追加します。lg.addColorStop(0, 'red')
      • 同期勾配
const canvas = document.querySelector(".mycanvas");

canvas.width = 800;
canvas.height = 400;

const ctx = canvas.getContext("2d");

const lg = ctx.createRadialGradient(200, 200, 50, 200, 200, 200);

lg.addColorStop(0, 'red');
lg.addColorStop(1, 'green');

ctx.fillStyle = lg;
ctx.fillRect(0, 0, 800, 400);

スクリーンショット 2023-07-09 22.53.54.png

  1. 複数の領域で異なるグラデーション
    • 本質は、複数のグラデーション スキームのセットを構成し、それらをさまざまな形状に描画することです。
const canvas = document.querySelector(".mycanvas");

canvas.width = 800;
canvas.height = 400;

const ctx = canvas.getContext("2d");

const rg = ctx.createRadialGradient(200, 200, 50, 200, 200, 200);
rg.addColorStop(0, 'red');
rg.addColorStop(1, 'green');

ctx.fillStyle = rg;
ctx.fillRect(0, 0, 400, 400);

const lg = ctx.createLinearGradient(400, 0, 800, 0);
lg.addColorStop(0, 'blue');
lg.addColorStop(1, 'yellow');
ctx.fillStyle = lg;
ctx.fillRect(400, 0, 400, 400);

スクリーンショット 2023-07-09 23.03.24.png

3. ベジェ曲線

  • ベジェ曲線 (ベジェ曲線) は、コンピュータ グラフィックスにおいて非常に重要なパラメトリック曲線です。方程式によって曲線を記述します。方程式の最高次数に従って、線形ベジェ曲線と二次ベジェ曲線、三次ベジェ曲線、に分けられます。そして高次のベジェ曲線。
    • ベジェ曲線はいくつかの点のパラメータを提供する必要があります。最初の点は曲線の開始点と終了点です。
    • 制御点の数が 0 の場合、それを線形ベジェと呼びます。
    • 制御点の数が 1 の場合、それは 2 次ベジェ曲線です。
    • 制御点の数が 2 の場合、3 次ベジェ曲線などとなります。
  1. 2次ベジェ曲線
    • 実際には、3 つの点から 2 本の直線が引かれます。
    • 次に、各行の先頭から同時に開始し、最後に向かって移動し、比例してポイントを獲得します。これらの点が再接続されて、n - 1 本の直線が生成されます。
    • このようにして、直線になるまで同じ操作を続け、曲線が通過する点である点を比例的に取得します。
    • スケールを少し (0 から 1) 大きくすると、曲線の中央にあるすべての点が得られ、最終的に完全な曲線が描画されます。

  1. 3次ベジェ曲線を見てみましょう
    • 2次ベジェ曲線と同じですが、制御点の数が2つになります。

  1. Canvas では、多くのポイントを手動で計算する必要はありません。Canvas は関連する API を直接提供します。
    • 2 次ベジェ曲線:ctx.quadraticCurveTo(p1x, p1y, p2x, p2y)
    • 3 次ベジェ曲線:ctx.bezierCurveTo(p1x, p1y, p2x, p2y, p3x, p3y)
    • その前に、moveTo を使用して p0 の位置を決定する必要があります

二次注文

const cvs = document.querySelector(".cvs");
cvs.width = 400;
cvs.height = 400;

const ctx = cvs.getContext("2d");

ctx.beginPath();
ctx.moveTo(100, 100);
ctx.quadraticCurveTo(300, 200, 200, 300);
ctx.stroke();

画像.png
三次

const cvs = document.querySelector(".cvs");
cvs.width = 400;
cvs.height = 400;

const ctx = cvs.getContext("2d");

ctx.beginPath();
ctx.moveTo(100, 100);
ctx.bezierCurveTo(60, 80, 150, 30, 170, 150);
ctx.stroke();

画像.png
多段式

ctx.beginPath();
ctx.moveTo(75, 25);
ctx.quadraticCurveTo(25, 25, 25, 62.5);
ctx.quadraticCurveTo(25, 100, 50, 100);
ctx.quadraticCurveTo(50, 120, 30, 125);
ctx.quadraticCurveTo(60, 120, 65, 100);
ctx.quadraticCurveTo(125, 100, 125, 62.5);
ctx.quadraticCurveTo(125, 25, 75, 25);
ctx.stroke();
ctx.moveTo(75, 40);
ctx.bezierCurveTo(75, 37, 70, 25, 50, 25);
ctx.bezierCurveTo(20, 25, 20, 62.5, 20, 62.5);
ctx.bezierCurveTo(20, 80, 40, 102, 75, 120);
ctx.bezierCurveTo(110, 102, 130, 80, 130, 62.5);
ctx.bezierCurveTo(130, 62.5, 130, 25, 100, 25);
ctx.bezierCurveTo(85, 25, 75, 37, 75, 40);
ctx.fill();

4.絵を描く

  1. 画像の作成 (非キャンバス操作)
    • 画像オブジェクトを作成します。const img = new Image();
    • リソースアドレスを設定します。img.src = "图片地址"
    • リソースの読み込みが完了しました:img.onload = function(){ / * 图片加载完成 */ }
  2. キャンバスに絵を描く
    • 3 つのパラメータ:gd.drawImage(图片对象, x, y)
      • キャンバスの X、Y 座標から描画を開始します
const canvas = document.querySelector(".mycanvas");

canvas.width = 800;
canvas.height = 400;

const ctx = canvas.getContext("2d");

const img = new Image();
img.src = "../1.png";

img.onload = function(){
    
    
  ctx.drawImage(this, 0, 100);
}

スクリーンショット 2023-07-09 23.18.25.png

  • 5 つのパラメータ:gd.drawImage(图片对象, x, y, w, h)
    • キャンバスのx、y座標から描画を開始し、幅w、高さhの領域まで描画します
const canvas = document.querySelector(".mycanvas");

canvas.width = 800;
canvas.height = 400;

const ctx = canvas.getContext("2d");

const img = new Image();
img.src = "../1.png";

img.onload = function(){
    
    
  ctx.drawImage(this, 0, 100, 200, 200);
}

スクリーンショット 2023-07-09 23.18.59.png

  • 9 つのパラメータ:gd.drawImage(图片对象, sx, sy, sw, sh, dx, dy, dw, dh)
    • s = ソース元の画像の位置の幅と高さ
    • d = 目的地 ターゲット (キャンバス) がどこに描かれ、その大きさがどれくらいであるか
const canvas = document.querySelector(".mycanvas");

canvas.width = 800;
canvas.height = 400;

const ctx = canvas.getContext("2d");

const img = new Image();
img.src = "../1.png";
// 图片资源宽高
const imgW = 128;
const imgH = 194;
img.width = 128;
img.height = 194;

img.onload = function(){
    
    
  ctx.drawImage(this, 0, 0, imgW/4, imgH/4, 0, 100, imgW/4, imgH/4);
}

スクリーンショット 2023-07-09 23.20.21.png

5. イベント

  1. キャンバスにはイベント システムはありません。キャンバス要素にイベントを追加し、イベント オブジェクトと連携することによって、イベント領域を手動で検出することしかできません。
  2. 長方形の検出式:
    • 点击x > 矩形x && 点击x < 矩形x + 矩形w && 点击y > 矩形y && 点击y < 矩形y + 矩形h
  3. 円検出式:
    • ピタゴラスの定理の使用: a^2 + b^2 = c^2
    • a = 中心 x - x をクリック
    • b = y の中心 - y をクリックします
    • c = Math.sqrt( a * a + b * b )
    • c < r の場合、円形領域内
  4. 自動検出
    • ctx.isPointInPath(x, y)
    • 戻り値: 指定された座標がパス範囲内にあるかどうかを示すブール値

六、輸出(理解)

download.onclick = function(){
    
    
  // 将canvas数据转成base64数据
  const base64 = canvas.toDataURL("image/png");
  // 将base64数据解码
  const strBase64 = atob( base64.split(",")[1] );
  // 创建utf-8原始数据(长度为base64解码后的字符长度)
  const utf_8 = new Uint8Array(strBase64.length);
  // 将base64解码后的数据转成Unicode编码后,存入utf-8数组
  for(let n=0;n<strBase64.length;n++){
    
    
    utf_8[n] = strBase64.charCodeAt(n)
  }
  // 根据utf-8数据,创建文件对象
  const file = new File([utf_8], "测试图片", {
    
    type:"image/png"});
  // 根据文件对象创建url字符
  const href = URL.createObjectURL(file);
  // 准备a标签,用于下载文件
  const a = document.createElement("a");
  a.href = href;
  a.download = "测试图片";
  document.body.appendChild(a);
  a.click();
  // 删除a标签
  a.remove();
  // 释放指向文件资源的url字符
  URL.revokeObjectURL(href);
}

7. まとめ

  • 変位:ctx.translate(x, y)
  • 回転:ctx.rotate(弧度值)
  • ズーム:ctx.scale(x, y)
  • ブラシの状態を保存:ctx.save()
  • ブラシの状態をリセット:ctx.restore()
  • 線形グラデーションを作成します。ctx.createLinearGradient(起点x坐标, 起点y坐标, 终点x坐标, 终点y坐标)
  • 放射状のグラデーションを作成します。const lg = ctx.createRadialGradient(x1, y1, r1, x2, y2, r2);
  • グラデーションカラーを追加します。lg.addColorStop(0, 'red')
  • 絵を描きます:gd.drawImage(图片对象, x, y)
  • 指定された座標が特定のパス範囲内にあるかどうかを確認します。ctx.isPointInPath(x, y)

八、練習する

  1. 機械式時計
  2. スポーティな小男
  3. 飛行機戦争
  4. 折れ線グラフ

おすすめ

転載: blog.csdn.net/weixin_41636483/article/details/132024621