Paper.js, как настроить несколько холстов, используя только javascript

Я пытаюсь использовать paper.js в webapp, но мне не удалось заставить его работать с несколькими холстами. Это подобно областям, которые смешиваются между холстами, поэтому, когда я намереваюсь рисовать на холсте 1, он появляется на холсте 2.

В каждом представлении я инициализирую документ следующим образом:

this.mypaper = new paper.PaperScope();
this.mypaper.setup($("myCanvasId")[0]);

Когда я создаю новые бумажные объекты, я использую то, что должно быть локальной областью:

var circle = new this.mypaper.Path.Circle(10, 10, 5);

Однако, когда я создаю круг в view1, он рисует его в view2.

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

Кто-нибудь знает, как правильно использовать несколько холстов с paper.js?


EDIT: я создал jsFiddle, чтобы проиллюстрировать проблему: http://jsfiddle.net/94RTX/1/

Ответ 1

Я не работал с Paper.js широко, но кажется, что каждый вызов Path не использует PaperScope, из которого он обращается, но глобальный объект paper. Поэтому, если вы перезаписываете paper на нужный PaperScope перед каждым экземпляром, он должен работать.

Смотрите мою обновленную скрипту.

Ответ 2

Я действительно решаю это немного по-другому:

var scope1 = new paper.PaperScope();
var scope2 = new paper.PaperScope();

Когда я хочу рисовать в области 1:

scope1.activate();
// now I draw

Аналогично, когда я хочу рисовать в области видимости 2

scope2.activate();
// now I draw

Ответ 3

Используйте массивы для разделения ваших документов.

this.mypapers = []

var mypaper = new paper.PaperScope();
mypaper.setup($("myCanvasId")[0]);

mypapers.push(mypaper);

mypaper = new paper.PaperScope();
mypaper.setup($("myCanvasId")[1]);

mypapers.push(mypaper);

var circle = new this.mypapers[0].Path.Circle(10,10,5);
var circle2 = new this.mypapers[1].Path.Circle(10,10,10);

EDIT: я обновил скрипт js: http://jsfiddle.net/94RTX/3/

По-видимому, каждая установка стирает предыдущую, поэтому решение должно сделать это в следующем порядке:

setup canvas 1-> draw canvas 1 -> setup canvas 2 -> draw canvas 2

Ответ 4

Я думаю, что нашел решение: я расширил скрипт от @freejosh, чтобы также работать с обратными вызовами (например, изменить размер): трюк заключается в повторной выборке правильной области внутри функции обратного вызова:

http://jsfiddle.net/rassoh/mx9n3vsf/7/

var mypapers = [];

initPaper(0, $("#canvas1")[0]);
initPaper(1, $("#canvas2")[0]);

function initPaper(id, canvasElement) {
    var mousePosition = new paper.Point(0,0);
    mypapers[id] = new paper.PaperScope();
    paper = mypapers[id];
    paper.setup(canvasElement);
    var myCircle;

    createCircle = function() {
        if( "undefined" !== typeof myCircle) {
            myCircle.remove();
        }
        // this function is called on resize, so we have to re-fetch the scope!
        paper = mypapers[id];
        myCircle = new paper.Path.Circle(30, 30, 20);
        var lightRed = new paper.Color(1, 0.5, 0.5);
        var lightBlue = new paper.Color(0.5, 0.5, 1);
        myCircle.style = {
            fillColor: id === 0 ? lightRed : lightBlue,
            strokeColor: "black"
        };
    }
    createCircle();

    var tool = new paper.Tool();
    tool.onMouseMove = function(event) {
        mousePosition = event.lastPoint;
    };
    paper.view.onFrame = function() {
        if( "undefined" === typeof myCircle) {
            return;
        }
        var dist = mousePosition.subtract( myCircle.position );
        dist = dist.divide( 3 );
        myCircle.position = myCircle.position.add( dist );
    };
    paper.view.onResize = function() {
        createCircle();
    };
}

$(window).resize(function() {
    var width = $(".container").width() / 2;
    var height = $(".container").height();
    // this automatically triggeres paper onResize event registered above
    mypapers[0].view.viewSize = new paper.Size( width, height );
    mypapers[1].view.viewSize = new paper.Size( width, height );
});

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

Ответ 5

Чтобы более точно управлять тем, с каким бумажным ящиком вы добавляете элементы, вы можете рассмотреть возможность установки опции insertItems на false.

  var paper1 = new paper.PaperScope();
  paper1.setup(canvasElement);
  paper1.settings.insertItems = false; 

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

  // create a second scope 
  var paper2 = new paper.PaperScope();
  // create a circle in the first scope
  var myCircle = new paper1.Path.Circle(new paper1.Point(100, 70), 50);
  myCircle.fillColor = 'black';
  // add that circle to the second scope paper 
  paper2.project.activeLayer.addChild(myCircle);