如何创建一个 paper.js Path.Circle 可以 scaled/translated 与仿射矩阵,但保持圆半径始终固定?

How to create a paper.js Path.Circle that can be scaled/translated with affine matrix, but keep circle radius always fixed?

我有一个 paper.js 层,用户可以在其中绘制不同的路径(圆圈、直线等)。可以使用鼠标滚动或拖动来平移或缩放该图层。我对这一层中的 zoom/pan 路径使用仿射矩阵变换。这很好用。

我正在寻找的是创建一个可以使用矩阵平移和缩放的圆(Path.Circle 对象),只是它的半径必须始终固定(例如 5px)。所以基本上矩阵变换只需要应用到圆的位置,而不是它的轮廓。

下面是一个半径为 20px transformedPath 的圆的示例,它被放大到 2x。问题是如何在应用矩阵变换时保持圆的半径 transformedPath 固定(半径 = 20px)。

var transformedPath = new paper.Path.Circle(100,100,20);

transformedPath.strokeColor = 'black';

paper.project.activeLayer.matrix = new paper.Matrix(
  2, 0,
  0, 2,
  0, 0
);

更新。这是一个更通用的 sketch (下面的代码),它基于 sasensi 建议的解决方案。在此示例中,蓝色圆圈的半径保持固定(这是正确的),但问题是蓝色圆圈也停留在同一个地方。

期望的结果是两个圆都移动到新位置,但蓝色圆半径保持不变。

// draw a normal circle
var normalCircle = new Path.Circle({
    center: new Point(100,100),
    radius: 50,
    fillColor: 'orange',
});

// draw another circle that will have scale transformation reversed
var notScalingCircle = new Path.Circle({
    center: new Point(100,100),
    radius: 30,
    fillColor: 'blue',
});

// draw instructions
new PointText({
    content: 'press mouse button down to zoom in and see that blue circle size does not change',
    point: view.center + [0, -80],
    justification: 'center'
});

function transformLayer(matrix) {
    // scale layer
    // project.activeLayer.applyMatrix = false;
    project.activeLayer.matrix = matrix;

    // scale item with inverted amount to make it display like if it was not scaled with the layer
    notScalingCircle.matrix = matrix.clone().invert();
}

var matrix = new paper.Matrix(
        2,0,
        0,1.5,
        50,30
    );

// on mouse down...
function onMouseDown() {
    // ...scale up
    transformLayer(matrix);
}

// on mouse up...
function onMouseUp() {
    // ...scale down
    transformLayer(matrix.clone().invert());
}

我认为最好的方法是,当你用给定的量缩放图层时,用倒置的量缩放你的圆圈。
这将使您的圆圈看起来像没有缩放一样。
这是一个 sketch 演示解决方案:

// draw a normal circle
var normalCircle = new Path.Circle({
    center: view.center,
    radius: 50,
    fillColor: 'orange'
});

// draw another circle that will have scale transformation reversed
var notScalingCircle = new Path.Circle({
    center: view.center,
    radius: 30,
    fillColor: 'blue'
});

// draw instructions
new PointText({
    content: 'press mouse button down to zoom in and see that blue circle size does not change',
    point: view.center + [0, -80],
    justification: 'center'
});

function scaleLayer(amount) {
    // scale layer
    project.activeLayer.scale(amount, view.center);
    // scale item with inverted amount to make it display like if it was not scaled with the layer
    notScalingCircle.scale(1 / amount);
}

// on mouse down...
function onMouseDown() {
    // ...scale up
    scaleLayer(3);
}

// on mouse up...
function onMouseUp() {
    // ...scale down
    scaleLayer(1 / 3);
}

编辑

针对新示例,您只需反转项目的缩放变换,而不是所有矩阵(也包括平移和旋转)。
这是更正后的 sketch:

// draw a normal circle
var normalCircle = new Path.Circle({
    center: new Point(100, 100),
    radius: 50,
    fillColor: 'orange'
});

// draw another circle that will have scale transformation reversed
var notScalingCircle = new Path.Circle({
    center: new Point(100, 100),
    radius: 30,
    fillColor: 'blue'
});

// draw instructions
new PointText({
    content: 'press mouse button down to zoom in and see that blue circle size does not change',
    point: view.center + [0, -80],
    justification: 'center'
});

function transformLayer(matrix) {
    // scale layer
    // project.activeLayer.applyMatrix = false;
    project.activeLayer.matrix = matrix;

    // just invert the scale and not all matrix
    notScalingCircle.scale(1 / matrix.scaling.x, 1 / matrix.scaling.y);
}

var matrix = new paper.Matrix(
    2, 0,
    0, 1.5,
    50, 30
);

// on mouse down...
function onMouseDown() {
    // ...scale up
    transformLayer(matrix);
}

// on mouse up...
function onMouseUp() {
    // ...scale down
    transformLayer(matrix.clone().invert());
}