缩放画布Path2d(使用svg路径数据)而不缩放整个画布?

时间:2016-05-20 01:21:08

标签: javascript canvas svg path-2d

我在一个画布中有多个Path2D,我希望能够独立地缩放和定位它们,而不是调整context.scale()和context.translate()。我正在使用SVG路径数据构造每个path2D对象,因为我希望能够修改stroke-dash和stroke-length。

似乎我可能无法使用Path2D实现这一点,解决这个问题的最佳方法是什么?

我考虑了一些潜在的选择:

  1. 使用带有svg源的drawImage方法
  2. 将svg路径数据转换为画布路径弧(可能使用库)
  3. 调整实际的svg路径数据,并为每个绘图重建Path2D对象
  4. 编辑:

    我构建了这个代码笔,我试图将p1移向p2而不改变p2的位置。当我翻译上下文时,两个对象都会移动。什么是仅调整p1位置的最佳方法?

    var canvas = document.getElementById("canvas");
    var ctx = canvas.getContext("2d");
    var p1x = 0
    var p1 = new Path2D("M1 0 h 100 v 50 h -100 Z");
    var p2 = new Path2D("M200 0 h 50 v 25 h -50 Z");
    
    setInterval(() => {
      p1x = p1x + 1
      ctx.translate(0, 0)
      ctx.clearRect(0, 0, 300, 300)
      ctx.translate(p1x, 0)
      ctx.fill(p1)
      ctx.fill(p2)    
    }, 1000)
    

    http://codepen.io/jasonpearson/pen/reXyVG

3 个答案:

答案 0 :(得分:2)

您可以将翻译应用于第一个元素:

setInterval(() => {
    p1x = p1x + 1;
    ctx.clearRect(0, 0, 300, 300);
    ctx.save();
    ctx.translate(p1x, 0);
    ctx.fill(p1);
    ctx.restore();
    ctx.fill(p2);
}, 1000);

答案 1 :(得分:0)

一个人可以将addPath方法与第二个 transform 参数结合使用来缩放路径...

const m = document.createElementNS("http://www.w3.org/2000/svg", "svg").createSVGMatrix()
const p = new Path2D()
const t = m.scale(0.5)
p.addPath(p1, t)

示例实现:

var canvas = document.getElementById("canvas")
var ctx = canvas.getContext("2d")
var p1x = 0
var p1 = new Path2D("M1 0 h 100 v 50 h -100 Z")
var p2 = new Path2D("M200 0 h 50 v 25 h -50 Z")
var m = document.createElementNS("http://www.w3.org/2000/svg", "svg").createSVGMatrix()

setInterval(() => {
  p1x = p1x + 1

  const p = new Path2D()
  const t = m.translate(p1x, 0)
  p.addPath(p1, t)

  ctx.clearRect(0, 0, 300, 300)
  ctx.fill(p)
  ctx.fill(p2)
}, 1000)
canvas {
  border: 1px solid blue;
  height: 300px;
  width: 300px;
}
<canvas id="canvas"></canvas>

更好的实现:

var canvas = document.getElementById("canvas")
var ctx = canvas.getContext("2d")
var p1 = new Path2D("M1 0 h 100 v 50 h -100 Z")
var p2 = new Path2D("M200 0 h 50 v 25 h -50 Z")
var m1 = document.createElementNS("http://www.w3.org/2000/svg", "svg").createSVGMatrix()

setInterval(() => {
  let p = new Path2D()
  m1 = m1.translate(1, 0)
  p.addPath(p1, m1)

  ctx.clearRect(0, 0, 300, 300)
  ctx.fill(p)
  ctx.fill(p2)
}, 1000)
canvas {
  border: 1px solid blue;
  height: 300px;
  width: 300px;
}
<canvas id="canvas"></canvas>


只需一个辅助功能,以备将来使用:

function transformPath2D(path, matrix) {
  const p = new Path2D()
  p.addPath(path, matrix)
  return p
}

答案 2 :(得分:0)

由于Chrome不再是Path2D.addPath(),因此,如果您希望Chrome兼容而不需要实验性标志,则需要在上下文中设置转换,我认为没有其他方法。

话虽如此,您可以在进行调整之前/之后仅save()restore()上下文。从上方更新示例:

var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
var p1x = 0
var p1 = new Path2D("M1 0 h 100 v 50 h -100 Z");
var p2 = new Path2D("M200 0 h 50 v 25 h -50 Z");

setInterval(() => {
  p1x = p1x + 1
  ctx.clearRect(0, 0, 300, 300);
  ctx.save();            // Save the previous translation context
  ctx.translate(p1x, 0); // Adjust context to where you want to draw p1
  ctx.fill(p1);
  ctx.restore();         // Restore the context before drawing p2
  ctx.fill(p2)    
}, 1000)

https://codepen.io/anon/pen/oMLNEz