Как нарисовать прямоугольник в рамке на холсте?

#javascript #canvas

#javascript #холст

Вопрос:

 var can = document.getElementById('canvas1');
var ctx = can.getContext('2d');

//ctx.arc(x,y,radius,startAngle,endAngle, anticlockwise);  

ctx.beginPath()
ctx.arc(100,100,100,0,Math.PI*2, false); // outer (filled)
ctx.arc(100,100,55,0,Math.PI*2, true); // outer (unfills it)
ctx.fill(); 
 <canvas id="canvas1" width="500" height="500"></canvas> 

Как я могу добиться этого эффекта с ctx.rect() помощью? Похоже, нет свойства, подобного anticlockwise with ctx.rect() .

Комментарии:

1. Может быть, нарисовать меньший белый прямоугольник поверх большего черного прямоугольника?

2. Это не достигло бы того же эффекта, если бы на холсте уже было что-то нарисовано.

3. Такое ощущение, что вы должны просто использовать thick stroke , на самом деле это не то, для чего предназначено направление вращения. Это работает, но если я увижу этот код, я изменю его на штрих, так как неясно, каков будет результат, и это будет очень похоже на штрих в целом, что делает его слишком сложным для его же блага.

4. Это не одно и то же, потому что внутренний круг может располагаться где угодно и иметь любую форму.

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

Ответ №1:

Это возможно, но не с rect помощью метода. Если вы вручную реализуете прямоугольник по часовой стрелке против часовой стрелки, это может сработать, см. Ниже:

 const canvas = document.querySelector( 'canvas' );
const ctx = canvas.getContext( '2d' );
const size = 200;

canvas.width = canvas.height = size;

// Just to show that the content still comes through
ctx.fillStyle = 'red';
ctx.fillRect( 0, 0, size, size );

ctx.fillStyle = 'white';

ctx.beginPath();

// Clockwise Rectangle
ctx.moveTo( 10, 10 );
ctx.lineTo( 190, 10 );
ctx.lineTo( 190, 190 );
ctx.lineTo( 10, 190 );
ctx.lineTo( 10, 10 );

// Anti-Clockwise Rectangle
ctx.moveTo( 20, 20 );
ctx.lineTo( 20, 180 );
ctx.lineTo( 160, 180 );
ctx.lineTo( 160, 20 );
ctx.lineTo( 20, 20 );

ctx.fill(); 
 <canvas></canvas> 

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

Уточнение

Причиной этого является свойство правила заполнения, которое вы можете передать в .fill : https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/fill , так что он будет работать на любом обратном пути с nonzero правилом по умолчанию.

@je3rdty Это работает с любым обратным путем, включая многоточия, из-за правила заполнения: https://en.wikipedia.org/wiki/Nonzero-rule

 const canvas = document.querySelector( 'canvas' );
const ctx = canvas.getContext( '2d' );
const size = 200;

canvas.width = canvas.height = size;

// Just to show that the content still comes through
ctx.fillStyle = 'red';
ctx.fillRect( 0, 0, size, size );

ctx.fillStyle = 'white';

ctx.beginPath();
ctx.ellipse( 100, 100, 100, 75, 0, 0, Math.PI * 2, false );
ctx.ellipse( 100, 100, 80, 50, Math.PI / 3, 0, Math.PI * 2, true );
ctx.fill(); 
 <canvas></canvas> 

Комментарии:

1. Как я могу сделать то же самое с ctx.ellipse() ? jsfiddle.net/tu1pmv6z Это работает , ctx.arc() но не ctx.ellipse() работает . jsfiddle.net/Hnw6a/8

2. @je3rdty Он должен работать с любым методом пути, который можно отменить, например, ellipse, последним аргументом которого является логическое значение против часовой стрелки. Это потому, что заполнение определяется «порядком намотки»: en.wikipedia.org/wiki/Winding_number

3. Я использовал ctx.ellipse() так же, как ctx.arc() , но это не сработало.

4. @je3rdty Это так, вы, должно быть, допустили ошибку. Я добавил пример к своему ответу.

5. @je3rdty Кроме того, статья, на которую дана ссылка, в более общем плане посвящена математической идее, в данном случае речь идет о конкретной системе: en.wikipedia.org/wiki/Nonzero-rule — это довольно интересно.