Как нарисовать сегмент пончика с холстом HTML5?
Как указано в заголовке. Возможно ли это?
Изменить: Когда я говорю "пончик", я имею в виду верхний, двумерный вид
Единственная опция для рисования сегмента круга, затем нарисуйте сегмент меньшего круга с тем же самым происхождением и меньшим радиусом сверху, с цветом фона? Если бы это было так: (
Ответы
Ответ 1
Вы делаете это, создавая один путь с двумя дугами.
Вы рисуете один круг по часовой стрелке, затем нарисуйте второй круг против часовой стрелки. Я не буду вдаваться в подробности этого, но путь, который построены пути, знает, чтобы принять это как причину, чтобы разгрузить эту часть пути. Для более подробной информации о том, что он делает, вы можете эту статью wiki.
То же самое можно было бы использовать, если бы вы рисовали прямоугольник с рамкой. Вы рисуете коробку в одну сторону (по часовой стрелке), затем нарисуйте внутренний ящик другим способом (против часовой стрелки), чтобы получить эффект.
Здесь код для пончика:
var can = document.getElementById('canvas1');
var ctx = can.getContext('2d');
// Pay attention to my last argument!
//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); // inner (unfills it)
ctx.fill();
Пример:
http://jsfiddle.net/Hnw6a/
Рисование только "сегмента" этого может быть сделано путем уменьшения пути (вам может потребоваться использование безьеров вместо дуги) или с помощью области отсечения. Это действительно зависит от того, как именно вы хотите "сегмент"
Вот один пример: http://jsfiddle.net/Hnw6a/8/
// half doughnut
ctx.beginPath()
ctx.arc(100,100,100,0,Math.PI, false); // outer (filled)
ctx.arc(100,100,55,Math.PI,Math.PI*2, true); // outer (unfills it)
ctx.fill();
Ответ 2
Вы можете сделать "верхний вид пончика" (круг с полым центром), поглаживая дугу. Вы можете увидеть пример этого здесь: http://phrogz.net/tmp/connections.html
![enter image description here]()
Круги (с nib) рисуются строками 239-245:
ctx.lineWidth = half*0.2; // set a nice fat line width
var r = half*0.65; // calculate the radius
ctx.arc(0,0,r,0,Math.PI*2,false); // create the circle part of the path
// ... some commands for the nib
ctx.stroke(); // actually draw the path
Ответ 3
Да, я понимаю, сколько лет этот вопрос:)
Вот мои два цента:
(function(){
var annulus = function(centerX, centerY,
innerRadius, outerRadius,
startAngle, endAngle,
anticlockwise) {
var th1 = startAngle*Math.PI/180;
var th2 = endAngle*Math.PI/180;
var startOfOuterArcX = outerRadius*Math.cos(th2) + centerX;
var startOfOuterArcY = outerRadius*Math.sin(th2) + centerY;
this.beginPath();
this.arc(centerX, centerY, innerRadius, th1, th2, anticlockwise);
this.lineTo(startOfOuterArcX, startOfOuterArcY);
this.arc(centerX, centerY, outerRadius, th2, th1, !anticlockwise);
this.closePath();
}
CanvasRenderingContext2D.prototype.annulus = annulus;
})();
Что добавит функцию "ringulus()", аналогичную "arc()" в прототипе CanvasRenderingContext2D. Создание закрытого пути пригодится, если вы хотите проверить включение точки.
С помощью этой функции вы можете сделать что-то вроде:
var canvas = document.getElementById("canvas1");
var ctx = canvas.getContext("2d");
ctx.annulus(0, 0, 100, 200, 15, 45);
ctx.fill();
Или проверьте это: https://jsfiddle.net/rj2r0k1z/10/
Спасибо!
Ответ 4
С помощью WebGL (один из контекстов холста HTML5) это возможно. Есть даже некоторые JS-библиотеки для браузеров, которые еще не поддерживают/реализуют его - ознакомьтесь с этими ссылками:
Ответ 5
Учитывая требования, то, что @SimonSarris говорит, удовлетворяет этой проблеме. Но позвольте сказать, что вы похожи на меня, и вместо этого вы хотите "очистить" часть формы, которая может быть частично за пределами формы, которую вы очищаете. Если у вас есть это требование, его решение не даст вам желать. Он будет выглядеть как "xor" на изображении ниже.
![enter image description here]()
Решение состоит в использовании context.globalCompositeOperation = 'destination-out'
Синяя - первая форма, а красная - вторая. Как вы можете видеть, destination-out
удаляет секцию из первой формы. Вот пример кода:
explosionCanvasCtx.fillStyle = "red"
drawCircle(explosionCanvasCtx, projectile.radius, projectile.radius, projectile.radius)
explosionCanvasCtx.fill()
explosionCanvasCtx.globalCompositeOperation = 'destination-out' #see https://developer.mozilla.org/samples/canvas-tutorial/6_1_canvas_composite.html
drawCircle(explosionCanvasCtx, projectile.radius + 20, projectile.radius, projectile.radius)
explosionCanvasCtx.fill()
Здесь потенциальная проблема с этим: вторая fill()
очистит все под ней, включая фон. Иногда вам нужно только очистить первую фигуру, но вы все равно хотите видеть слои, находящиеся под ней.
Решение этого заключается в том, чтобы нарисовать это на временном холсте, а затем drawImage
, чтобы нарисовать временный холст на ваш основной холст. Код будет выглядеть так:
diameter = projectile.radius * 2
console.log "<canvas width='" + diameter + "' height='" + diameter + "'></canvas>"
explosionCanvas = $("<canvas width='" + diameter + "' height='" + diameter + "'></canvas>")
explosionCanvasCtx = explosionCanvas[0].getContext("2d")
explosionCanvasCtx.fillStyle = "red"
drawCircle(explosionCanvasCtx, projectile.radius, projectile.radius, projectile.radius)
explosionCanvasCtx.fill()
explosionCanvasCtx.globalCompositeOperation = 'destination-out' #see https://developer.mozilla.org/samples/canvas-tutorial/6_1_canvas_composite.html
durationPercent = (projectile.startDuration - projectile.duration) / projectile.startDuration
drawCircle(explosionCanvasCtx, projectile.radius + 20, projectile.radius, projectile.radius)
explosionCanvasCtx.fill()
explosionCanvasCtx.globalCompositeOperation = 'source-over' #see https://developer.mozilla.org/samples/canvas-tutorial/6_1_canvas_composite.html
ctx.drawImage(explosionCanvas[0], projectile.pos.x - projectile.radius, projectile.pos.y - projectile.radius) #center
Ответ 6
Адаптация/упрощение @Simon Sarris, чтобы легко работать с любым углом, дает следующее:
Чтобы создать сегмент дуги, вы рисуете внешнюю дугу (из n радианов) в одном направлении, а затем противоположную дугу (того же числа радианов) с меньшим радиусом и заполняете полученную область.
var can = document.getElementById('canvas1');
var ctx = can.getContext('2d');
var angle = (Math.PI*2)/8;
var outer_arc_radius = 100;
var inner_arc_radius = 50.;
ctx.beginPath()
//ctx.arc(x,y,radius,startAngle,endAngle, anticlockwise);
ctx.arc(100,100,outer_arc_radius,0,angle, false); // outer (filled)
// the tip of the "pen is now at 0,100
ctx.arc(100,100,inner_arc_radius,angle,0, true); // outer (unfills it)
ctx.fill();
<canvas id="canvas1" width="200" height="200"></canvas>