【问题标题】:paper.js how to set up multiple canvases using only javascriptpaper.js 如何仅使用 javascript 设置多个画布
【发布时间】:2021-03-26 17:05:53
【问题描述】:

我正在尝试在 web 应用程序中使用 paper.js,但我无法让它与多个画布一起使用。就像画布之间的范围混淆了,所以当我打算在画布 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 的多个画布?


编辑:我创建了一个 jsFiddle 来说明问题:http://jsfiddle.net/94RTX/1/

【问题讨论】:

    标签: javascript canvas paperjs


    【解决方案1】:

    我没有广泛使用 Paper.js,但似乎每次调用 Path 都不是使用从中访问它的 PaperScope,而是使用全局 paper 对象。因此,如果您在每次实例化之前将 paper 覆盖到所需的 PaperScope,它应该可以工作。

    See my updated fiddle.

    【讨论】:

    • 如果您稍后调用调整大小事件,这将不起作用...将尝试创建小提琴
    • 我觉得值得一提的是我使用的模式。它是有一个纸张访问器功能,如function getPaper() { return window.paper = mypaper; } 这样您就可以确保无论何时使用纸张,都会正确设置全局变量。
    • Fiddle 由于 paper.js 文件 URL 无效而无法工作。固定在这里:jsfiddle.net/sy3L9nh2
    【解决方案2】:

    我实际上解决这个问题有点不同:

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

    当我想在 scope1 中绘制时:

    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);
      

      编辑:我已经更新了你的 js 小提琴: http://jsfiddle.net/94RTX/3/

      显然每个设置都会擦除前一个,因此解决方案是按以下顺序进行:

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

      【讨论】:

      • 嗯,好像还是不行。我已经用 jsfiddle 更新了我原来的问题,所以你可以看到我在说什么。
      • 不幸的是,这种方法只有在您一步完成所有绘图代码时才有效。由于我也有需要绘制东西的异步回调,所以这样做不是一种选择。
      【解决方案4】:

      为了更明确地管理要添加项目的纸张范围,您可以考虑将选项 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's paper 
        paper2.project.activeLayer.addChild(myCircle);
      

      【讨论】:

        【解决方案5】:

        我想我找到了解决方案:我将小提琴从 @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's onResize event registered above
            mypapers[0].view.viewSize = new paper.Size( width, height );
            mypapers[1].view.viewSize = new paper.Size( width, height );
        });
        

        请注意,我还包括了与圈子的简单交互,以测试那里的正确行为。

        【讨论】:

          【解决方案6】:

          @freejosh 的回答适用于 10.2,但升级到最新版本(截至目前为 12.2)时,小提琴仍然重复使用一个画布:

          http://jsfiddle.net/ecneto/86qckn2h/1/

          这是一个简单的修复,你可以降级,也可以使用 scope.activate(),感觉比覆盖纸要好得多:

          http://jsfiddle.net/ecneto/n91rdp6z/2/

          mypapers[0].activate();
          var circle1 = new paper.Path.Circle(30, 30, 20);
          circle1.style = {
              fillColor: new paper.Color(1, .5, .5),
              strokeColor: "black"
          };
          
          mypapers[1].activate();
          var circle2 = new paper.Path.Circle(60, 60, 20);
          circle2.style = {
              fillColor: new paper.Color(.5, .5, 1),
              strokeColor: "black"
          };
          

          【讨论】:

            【解决方案7】:

            其实你只需要一个Paperscope

            This tutorial 说:

            当直接使用 JavaScript 时,大多数情况下只需要一个作用域。在此范围内,仍然可以使用 new Project() 和 new View(canvas) 构造函数创建多个项目或视图。

            paper.setup('canvas1')
            paper.setup('canvas2')
            
            paper.projects[0].activate()
            // canvas1 is activated
            // draw something on canvas1
            
            paper.projects[1].activate()
            // canvas2 is activated
            // draw something on canvas2
            
            

            【讨论】:

              猜你喜欢
              • 2013-10-07
              • 1970-01-01
              • 1970-01-01
              • 2016-03-17
              • 2012-03-04
              • 1970-01-01
              • 2015-05-10
              • 2012-10-06
              • 1970-01-01
              相关资源
              最近更新 更多