JavaScript холст форма отсечения, когда выходит за пределы

То, о чем я прошу, может быть очень простым, но у меня было немало проблем с получением желаемого результата.

Я хочу, чтобы фигура (в данном примере это квадраты, но должна работать с другими фигурами, такими как круги и т. Д.), Чтобы обрезать себя, когда она выходит за границы другой фигуры.

По сути, верхнее изображение - это то, что я хочу, нижнее - то, что у меня сейчас есть: http://imgur.com/a/oQkzG

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

Это текущий код, если вы не можете использовать JSFiddle:

// Fill the background
ctx.fillStyle = '#0A2E36';
ctx.fillRect(0, 0, canvas.width, canvas.height);

// Fill the parent rect
ctx.fillStyle = '#CCA43B';
ctx.fillRect(100, 100, 150, 150);

// Fill the child rect
ctx.fillStyle = 'red';
ctx.fillRect(200, 200, 70, 70);

// And fill a rect that should not be affected
ctx.fillStyle = 'green';
ctx.fillRect(80, 80, 50, 50);

JSFiddle Link

1 ответ

Решение

Поскольку вам нужна какая-то связь между объектами - граф сцены, вы должны построить ее сейчас.
Из вашего вопроса кажется, что любой дочерний элемент должен быть нарисован обрезанным по родительскому элементу.
(Да, на помощь может прийти сложная операция, но она удобна только при рисовании в виде двух фигур на очищенном фоне, в противном случае все быстро усложняется, и вам, возможно, придется использовать задний холст, поэтому отсечение будет проще.)

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

"Сцена" состоит из фона Rect, в котором есть два дочерних элемента - желтый и зеленый. А у желтого Ректа есть красное дитя.

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

function Rect(fill, x, y, w, h) {
    var childs = [];
    this.draw = function () {
        ctx.save();
        ctx.beginPath();
        ctx.fillStyle = fill;
        ctx.rect(x, y, w, h);
        ctx.fill();
        ctx.clip();
        for (var i = 0; i < childs.length; i++) {
            childs[i].draw();
        }
        ctx.restore();
    }
    this.addChild = function (child) {
        childs.push(child);
    }
    this.setPos = function (nx, ny) {
        x = nx;
        y = ny;
    }
}

// background
var bgRect = new Rect('#0A2E36', 0, 0, canvas.width, canvas.height);
// One parent rect
var parentRect = new Rect('#CCA43B', 100, 100, 150, 150);
// child rect
var childRect = new Rect('red', 200, 200, 70, 70);
parentRect.addChild(childRect);
//  Another top level rect
var otherRect = new Rect('green', 80, 80, 50, 50);

bgRect.addChild(parentRect);
bgRect.addChild(otherRect);

function drawScene() {
    bgRect.draw();
    drawTitle();
}

drawScene();

window.addEventListener('mousemove', function (e) {
    var rect = canvas.getBoundingClientRect();
    var x = (e.clientX - rect.left);
    var y = (e.clientY - rect.top);
    childRect.setPos(x, y);
    drawScene();
});

function drawTitle() {
    ctx.fillStyle = '#DDF';
    ctx.font = '14px Futura';
    ctx.fillText('Move the mouse around.', 20, 24);
}
<canvas id='cv' width=440 height=440></canvas>

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