首页 > 解决方案 > 不能用 paperJS 创建多个画布?

问题描述

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

标签: javascriptangularpaperjs

解决方案


I can't tell where you made mistakes because you didn't post your code but I think that you should read this article explaining in details how to use Paper.js in JavaScript context.

Here is a stackblitz demonstrating the solution.

App component

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
{

}

Metaball component

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

推荐阅读