Масштабирование холста без искажения lineWidth или разрушения клипа

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

ctx.save();
ctx.scale(1, 2);
ctx.beginPath();
// draw shape
ctx.restore();
ctx.stroke();

К сожалению, мне также нужна сложная область обрезки, и метод restore () уничтожает область обрезки. Попробовал просто восстановить масштаб:

ctx.save();
ctx.scale(1, 2);
ctx.beginPath();
// draw shape
ctx.scale(1, 1);
ctx.stroke();

Но это не сработало, и ширина линии осталась искаженной.

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

Любые идеи?

вы можете предоставить фрагмент кода, воспроизводящий вашу проблему?

Helder Sepulveda 09.08.2018 20:07
jsfiddle.net/ja501sx7/6
srkleiman 10.08.2018 21:52
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
2
30
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

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

Но в любом случае, давайте предположим, что вы абсолютно хотите обрезать ...


ctx.save() будет складывать сохраненные состояния во внутренний объект ArrayLike. Каждый вызов restore() будет восстанавливать только извлеченный из pop элемент (т. Е. Самый новый в стеке).

Таким образом, вы можете очень хорошо восстановить состояние до масштабирования, но после обрезки, просто вызвав ctx.save() между этими двумя операциями.

ctx = c.getContext('2d');
ctx.save(); // stack a first state without clipping, just in case
// define our clipping region
ctx.arc(53,50,30,0,Math.PI*2);
ctx.stroke();
ctx.clip();

// draw once at normal scale
drawShape();
ctx.strokeStyle = 'blue';
ctx.stroke();

// save our context state before we scale
ctx.save();
// now draw scaled
ctx.scale(2, 1);
drawShape();
// restore to before we applied the scale
ctx.restore();
ctx.strokeStyle = 'red';
ctx.stroke();

// restore before clipping
ctx.restore();
// next drawings would be unclipped...

function drawShape() {
  ctx.beginPath();
  ctx.rect(25, 30, 20, 20);
}
<canvas id = "c"></cavnas>


Теперь вам даже не нужно управлять этим беспорядком состояний контекста, и вы можете просто восстановить матрицу преобразования контекста.

В вашем коде вы используете ctx.scale(1, 1). Это запретная операция (ничего не сделает). ctx.scale(factor, factor) умножит текущие значения шкалы на пройденные вами значения factor. Так что, начиная с п * 1 = п, это ничего не даст.

Итак, да, вы можете вычислить обратный коэффициент, который вам нужно будет передать (как в вашем примере, это будет ctx.scale(1, 0.5)), но самым простым решением является использование абсолютного метода setTransform(xScale, xSkew, ySkew, yScale, xTranslate, yTranslate). Чтобы сбросить матрицу контекста к значениям по умолчанию, вам просто нужно запомнить ctx.setTransform(1,0,0,1,0,0);.

ctx = c.getContext('2d');
// as a bonus, we will use compositing instead of clipping
// but this has no incidence on the demo

// draw once at normal scale
drawShape();
ctx.strokeStyle = 'blue';
ctx.stroke();

// now draw scaled
ctx.scale(2, 1);
drawShape();
// restore the context's matrix
ctx.setTransform(1,0,0,1,0,0);
ctx.strokeStyle = 'red';
ctx.stroke();

// clipping (compositing)
// only the pixels that are currenlty on the context,
// and whose position will match with one of the to be drawn will be kept
ctx.globalCompositeOperation = 'destination-in';
ctx.beginPath();
ctx.arc(53,50,30,0,Math.PI*2);
ctx.fill();
// restore to default
ctx.globalCompositeOperation = 'source-over';
// just to show the clipped area
ctx.strokeStyle = '#000';
ctx.stroke();

function drawShape() {
  ctx.beginPath();
  ctx.rect(25, 30, 20, 20);
}
<canvas id = "c"></canvas>

Дох! конечно же scale (1, 1) не работает. Я закончил вырезку с "destination-out", которая работала нормально. Прежде чем я наткнулся на это, я попытался просто заполнить форму отсечения с помощью rbga (0, 0, 0, 0), но это не сработало, поскольку оно было наложено поверх оригинала, вместо того, чтобы очищать его. В любом случае, спасибо, что поправили меня.

srkleiman 11.08.2018 23:50

Другие вопросы по теме