Резка неправильной формы на изображении - PullRequest
2 голосов
/ 13 июля 2011

Я пытаюсь вырезать изображение определенной формы, используя метод canvas clip ().

Для этого я выполнил следующие шаги:

  1. Нарисуйте прямоугольник.
  2. Нарисуйте полукруги с каждой стороны.Правый и нижний полукруги выступают наружу, а левый и верхний полукруги внутрь.

Ниже приведен фрагмент кода:

var canvasNode = this.hasNode();
var ctx = canvasNode && canvasNode.getContext('2d');

var image = new Image();
image.onload = function() {
  ctx.drawImage(image, 0, 0, 512, 384);
};

image.src = "images/image.png";
var startX = 200;
var startY = 0;

var rectWidth = 150;
var rectHeight = 150;
var radius = 30;

//Main Rect
ctx.rect(startX, startY, rectWidth, rectHeight);

//Right arc
ctx.moveTo(startX+=rectWidth, startY+=(rectHeight/2));
ctx.arc(startX, startY, radius, 3 * Math.PI / 2, Math.PI / 2, false);

//Left arc
ctx.moveTo(startX-=(rectWidth / 2), startY+=(rectHeight / 2));
ctx.arc(startX, startY, radius, 0, Math.PI, true);

ctx.moveTo(startX-=(rectWidth / 2), startY-=(rectWidth / 2));
ctx.arc(startX, startY, radius, 3 * Math.PI / 2, Math.PI / 2, false);

ctx.clip();

Используемое изображениеразмером 800 х 600 (png).Пожалуйста, помогите мне понять, что я делаю здесь неправильно.

1 Ответ

2 голосов
/ 13 июля 2011

Во-первых, почему вы используете clip? В настоящее время вы просто рисуете полукруги, которые работают без clip.

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

Если вы просто нажмете вместо клипа, у меня это будет работать частично: http://jsfiddle.net/r6yAN/. Хотя вы не включили верхний полукруг.

Редактировать: Похоже, вы не используете лучший способ отсечения. Вы рисуете прямоугольник, но это также включает в себя линию в полукруге. Было бы лучше, если бы вы рисовали каждую линию / дугу самостоятельно так: http://jsfiddle.net/CH6qB/6/.

Основная идея состоит в том, чтобы перемещаться из точки в точку, как показано на этом рисунке:

image

Итак, сначала начните с (startX, startY), затем с линии на (startX + lineWidth, startY), затем с дуги на (startX + rectWidth / 2, startY) от pi до 0 (против часовой стрелки) и т. Д.

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

var canvasNode = document.getElementById('cv');
var ctx = canvasNode && canvasNode.getContext('2d');

var image = new Image();
image.onload = function() {
    // draw the image, region has been clipped
    ctx.drawImage(image, startX, startY);

    // restore so that a stroke is not affected by clip
    // (restore removes the clipping because we saved the path without clip below)
    ctx.restore();
    ctx.stroke();
};

image.src = "http://www.lorempixum.com/200/200/";

var startX = 200;
var startY = 0;

var rectWidth = 150;
var rectHeight = 150;
var radius = 30;

var lineWidth  = rectWidth  / 2 - radius;
var lineHeight = rectHeight / 2 - radius;

// typing pi is easier than Math.PI each time
var pi = Math.PI;

ctx.moveTo(startX, startY);

ctx.lineTo(startX + lineWidth, startY);
ctx.arc(startX + rectWidth / 2, startY,
        radius,
        pi, 0, true);
ctx.lineTo(startX + rectWidth, startY);

ctx.lineTo(startX + rectWidth, startY + lineHeight);
ctx.arc(startX + rectWidth, startY + rectHeight / 2,
        radius,
        -pi / 2, pi / 2, false);
ctx.lineTo(startX + rectWidth, startY + rectHeight);

ctx.lineTo(startX + rectWidth - lineWidth, startY + rectHeight);
ctx.arc(startX + rectWidth / 2, startY + rectHeight,
        radius,
        0, pi, false);
ctx.lineTo(startX, startY + rectHeight);

ctx.lineTo(startX, startY + rectHeight - lineHeight);
ctx.arc(startX, startY + rectHeight / 2,
        radius,
        pi/2, pi*3/2, true);
ctx.lineTo(startX, startY);

ctx.save(); // Save the current state without clip

ctx.clip();
...