Как создать файл paper.js Path.Circle, который можно масштабировать / переводить с помощью аффинной матрицы, но всегда сохраняя радиус круга неизменным? - PullRequest
0 голосов
/ 21 ноября 2018

У меня есть слой paper.js, где пользователи могут рисовать различные пути (круги, линии и т. Д.).Этот слой может быть панорамирован или увеличен с помощью прокрутки мыши или перетаскивания.Я использую аффинное матричное преобразование для увеличения / панорамирования путей в этом слое.Это работает довольно хорошо.

Мне нужно создать круг (объект Path.Circle), который можно панорамировать и масштабировать с использованием матрицы, просто его радиус всегда должен быть фиксированным (например, 5 пикселей),Таким образом, в основном матричное преобразование необходимо применять только к положению окружности, но не к его контуру.

Ниже приведен образец круга с радиусом 20px transformedPath, который увеличен до 2x.Вопрос в том, как сохранить радиус окружности transformedPath фиксированным (radius = 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
);

ОБНОВЛЕНИЕ.Вот более общий набросок (код ниже), основанный на решении, предложенном sasensi.В этом примере радиус синего круга остается фиксированным (это правильно), но проблема в том, что синий круг также остается на том же месте.enter image description here

Желаемый результат состоит в том, что оба круга перемещаются в новую позицию, но радиус синего круга остается неизменным.

// 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());
}

1 Ответ

0 голосов
/ 21 ноября 2018

Я думаю, что лучший способ сделать это, когда вы масштабируете свой слой с заданным количеством, масштабировать свой круг с инвертированным количеством.
Это сделает ваш круг похожим, если он не был масштабирован.
Вот эскиз , демонстрирующий решение:

// 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);
}

Редактировать

В ответ на новый пример вам просто нужно инвертировать преобразование масштабирования для элемента ине вся матрица (которая также включает в себя перемещение и вращение).
Вот исправленный набросок :

// 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());
}
...