【问题标题】:Can't create multiple canvas with paperJS?不能用 paperJS 创建多个画布?
【发布时间】:2018-11-08 17:36:40
【问题描述】:

我正在尝试在 Angular 2 中使用来自 paper.js 的元球制作一些组件。他画了圆圈,但在第二个画布圆圈上没有连接......请帮助......不仅如此,我什至无法用纯javascript制作2个画布...... http://paperjs.org/examples/meta-balls/

【问题讨论】:

    标签: javascript angular paperjs


    【解决方案1】:

    我不知道你在哪里犯了错误,因为你没有发布你的代码,但我认为你应该阅读这个article,详细解释如何在JavaScript上下文中使用Paper.js

    这是一个stackblitz 演示解决方案。

    应用组件

    import { Component } from '@angular/core';
    
    @Component({
      selector: 'my-app',
      template: `
        <!-- instantiate 2 meta ball components -->
        <app-meta-ball></app-meta-ball>
        <app-meta-ball></app-meta-ball>
      `,
    })
    export class AppComponent
    {
    
    }
    

    元球组件

    import { AfterViewInit, Component, ElementRef, ViewChild } from '@angular/core';
    import {paper} from 'paper';
    
    @Component({
      selector: 'app-meta-ball',
      template: `
        <canvas #canvas></canvas>
      `,
      styles  : [
          `
          canvas {
            width  : 800px;
            height : 500px;
            margin : 10px;
            border : 1px solid;
          }
          `,
      ],
    })
    export class MetaBallComponent implements AfterViewInit
    {
      // get a reference to the canvas element
      @ViewChild('canvas') canvas: ElementRef;
    
      ngAfterViewInit ()
      {
        // create a new scope
        const scope = new paper.PaperScope();
        // bind it to the canvas
        scope.setup(this.canvas.nativeElement);
        // draw
        this.drawMetaBalls(scope);
      }
    
      // code adapted from http://paperjs.org/examples/meta-balls/
      private drawMetaBalls ( scope: paper.PaperScope )
      {
        // Ported from original Metaball script by SATO Hiroyuki
        // http://park12.wakwak.com/~shp/lc/et/en_aics_script.html
        scope.project.currentStyle = {
          fillColor: 'black',
        };
    
        var ballPositions = [
          [ 255, 129 ], [ 610, 73 ], [ 486, 363 ],
          [ 117, 459 ], [ 484, 726 ], [ 843, 306 ], [ 789, 615 ], [ 1049, 82 ],
          [ 1292, 428 ], [ 1117, 733 ], [ 1352, 86 ], [ 92, 798 ],
        ];
    
        var handle_len_rate = 2.4;
        var circlePaths     = [];
        var radius          = 50;
        for (var i = 0, l = ballPositions.length; i < l; i++)
        {
          var circlePath = new paper.Path.Circle({
            center: ballPositions[ i ],
            radius: 50,
          });
          circlePaths.push(circlePath);
        }
    
        var largeCircle = new paper.Path.Circle({
          center: [ 676, 433 ],
          radius: 100,
        });
        circlePaths.push(largeCircle);
    
        var tool = new paper.Tool();
    
        tool.onMouseMove = function ( event )
        {
          largeCircle.position = event.point;
          generateConnections(circlePaths);
        };
    
        var connections = new paper.Group();
    
        function generateConnections ( paths )
        {
          // Remove the last connection paths:
          connections.children = [];
    
          for (var i = 0, l = paths.length; i < l; i++)
          {
            for (var j = i - 1; j >= 0; j--)
            {
              var path = metaball(paths[ i ], paths[ j ], 0.5, handle_len_rate, 300);
              if (path)
              {
                connections.appendTop(path);
                path.removeOnMove();
              }
            }
          }
        }
    
        generateConnections(circlePaths);
    
        // ---------------------------------------------
        function metaball ( ball1, ball2, v, handle_len_rate, maxDistance )
        {
          var center1 = ball1.position;
          var center2 = ball2.position;
          var radius1 = ball1.bounds.width / 2;
          var radius2 = ball2.bounds.width / 2;
          var pi2     = Math.PI / 2;
          var d       = center1.getDistance(center2);
          var u1, u2;
    
          if (radius1 == 0 || radius2 == 0)
          {
            return;
          }
    
          if (d > maxDistance || d <= Math.abs(radius1 - radius2))
          {
            return;
          } else if (d < radius1 + radius2)
          { // case circles are overlapping
            u1 = Math.acos((radius1 * radius1 + d * d - radius2 * radius2) /
                           (2 * radius1 * d));
            u2 = Math.acos((radius2 * radius2 + d * d - radius1 * radius1) /
                           (2 * radius2 * d));
          } else
          {
            u1 = 0;
            u2 = 0;
          }
    
          var angle1  = center2.subtract(center1).getAngleInRadians();
          var angle2  = Math.acos((radius1 - radius2) / d);
          var angle1a = angle1 + u1 + (angle2 - u1) * v;
          var angle1b = angle1 - u1 - (angle2 - u1) * v;
          var angle2a = angle1 + Math.PI - u2 - (Math.PI - u2 - angle2) * v;
          var angle2b = angle1 - Math.PI + u2 + (Math.PI - u2 - angle2) * v;
          var p1a     = center1.add(getVector(angle1a, radius1));
          var p1b     = center1.add(getVector(angle1b, radius1));
          var p2a     = center2.add(getVector(angle2a, radius2));
          var p2b     = center2.add(getVector(angle2b, radius2));
    
          // define handle length by the distance between
          // both ends of the curve to draw
          var totalRadius = (radius1 + radius2);
          var d2          = Math.min(v * handle_len_rate, p1a.subtract(p2a).length / totalRadius);
    
          // case circles are overlapping:
          d2 *= Math.min(1, d * 2 / (radius1 + radius2));
    
          radius1 *= d2;
          radius2 *= d2;
    
          var path                = new paper.Path({
            segments: [ p1a, p2a, p2b, p1b ],
            style   : ball1.style,
            closed  : true,
          });
          var segments            = path.segments;
          segments[ 0 ].handleOut = getVector(angle1a - pi2, radius1);
          segments[ 1 ].handleIn  = getVector(angle2a + pi2, radius2);
          segments[ 2 ].handleOut = getVector(angle2b - pi2, radius2);
          segments[ 3 ].handleIn  = getVector(angle1b + pi2, radius1);
          return path;
        }
    
        // ------------------------------------------------
        function getVector ( radians, length )
        {
          return new paper.Point({
            // Convert radians to degrees:
            angle : radians * 180 / Math.PI,
            length: length,
          });
        }
      }
    }
    

    【讨论】:

    • 不,我有 2 个不同的组件...具有不同的元球动画和颜色以及半径和大小画布...您只需复制 1 个组件...。
    • 那么您只需要像我为这个组件所做的那样创建另一个组件,并且应该可以正常工作。看看这个stackblitz 演示它。
    猜你喜欢
    • 1970-01-01
    • 2014-07-12
    • 2019-12-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-11-28
    • 1970-01-01
    相关资源
    最近更新 更多