1

キャンバス 2D API では、最初に 1 つのコンテキストの変換を使用してサブパスを定義し、次にそのコンテキストの変換をfill()またはstroke()呼び出しのみに変更できます。定義されたパス。これは、同じストローク幅を維持しながらベクトル形状を拡大したい場合に非常に便利です。fillStylelineWidth

lineWidth以下は、可変ズーム変換によってのみが影響を受ける簡単な例です。

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

let zoom = 1;
let speed = 0.1;
requestAnimationFrame(update);

function update() {
  if( zoom >= 10 || zoom <= 0.1 ) speed *= -1;
  zoom += speed;
  draw();
  requestAnimationFrame(update);
}

function draw() {
  ctx.setTransform(1, 0, 0, 1, 0, 0);
  ctx.clearRect(0,0,canvas.width,canvas.height);
  // define the subpath at identity matrix
  ctx.beginPath();
  ctx.moveTo(10 ,80);
  ctx.quadraticCurveTo(52.5,10,95,80);
  ctx.quadraticCurveTo(137.5,150,180,80);
  // stroke zoomed
  ctx.setTransform(zoom, 0, 0, zoom, 0, 0);
  ctx.stroke();
}
<canvas id="canvas"></canvas>

Path2D API では、このサブパスをctx.fill(path)またはctx.stroke(path)メソッドで直接渡す必要があります。
これは、前に行ったようにサブパス宣言からスタイリングを分離できないことを意味します。

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

let zoom = 1;
let speed = 0.1;
requestAnimationFrame(update);

function update() {
  if( zoom >= 10 || zoom <= 0.1 ) speed *= -1;
  zoom += speed;
  draw();
  requestAnimationFrame(update);
}

function draw() {
  ctx.setTransform(1, 0, 0, 1, 0, 0);
  ctx.clearRect(0,0,canvas.width,canvas.height);
  // define the subpath at identity matrix
  // (declared in 'draw' just for the example, would be the same anyway outside)
  const path = new Path2D("M 10 80 Q 52.5 10, 95 80 T 180 80");
  // stroke zoomed
  ctx.setTransform(zoom, 0, 0, zoom, 0, 0);
  ctx.stroke(path);
}
<canvas id="canvas"></canvas>

この便利な Path2D API を使用しているときにこれを行う方法はありませんか?

4

1 に答える 1

2

DOMMatrix 1をメソッドに渡すことで Path2D オブジェクトを変換する方法がありPath2D.prototype.addPathます。

したがって、Path2d の変換されたコピーを渡すことで、実際に同じ結果を得ることができます。

const transformPath = (path, matrix) => {
  const copy = new Path2D();
  copy.addPath(path, matrix);
  return copy;
};
// ...
ctx.stroke( transformPath( path, {a: 1/zoom, d: 1/zoom } );

ただし、パス マトリックスをスタイリングマトリックスから相対的に作成する必要があることに気付くでしょう。
新しい DOMMatrix API は、マトリックス変換を大幅に緩和ます2。私が知っている唯一の方法...beginPath()

const transformPath = (path, matrix) => {
  const copy = new Path2D();
  copy.addPath(path, matrix);
  return copy;
};

const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
// define the subpath
const path = new Path2D("M 10 80 Q 52.5 10, 95 80 T 180 80");

let zoom = 1;
let speed = 0.1;
requestAnimationFrame(update);

function update() {
  if( zoom >= 10 || zoom <= 0.1 ) speed *= -1;
  zoom += speed;
  draw();
  requestAnimationFrame(update);
}

function draw() {
  ctx.setTransform(1, 0, 0, 1, 0, 0);
  ctx.clearRect(0,0,canvas.width,canvas.height);  
  // zoom the stylings
  ctx.setTransform(zoom, 0, 0, zoom, 0, 0);
  // create our transformed path
  const invertMatrix = {a: 1/zoom, d: 1/zoom};
  ctx.stroke(transformPath(path, invertMatrix));
}
<canvas id="canvas"></canvas>

1. 実際には、実際の DOMMatrix である必要はありません。そのプロパティを持つ任意のオブジェクトが実行されます
。 2. そのようなオブジェクトをctx.setTransform(matrix).

于 2020-01-10T07:55:44.657 に答える