Search code examples
two.js

Clip a line inside a circle with Two.js using SVG


I want to draw a line that goes through a circle but is clipped by the boundary of the circle. Here is my code so far,

var elem = document.getElementById('draw-shapes');
var params = { width: 600, height: 400 };
var two = new Two(params).appendTo(elem);
var center = { x: params.width/2, y: params.height/2};
var circle = two.makeCircle(center.x, center.y, 80);
var line = two.makeLine(0, 0, 600, 300);

circle.fill = 'white';
circle.stroke = 'black';
circle.linewidth = 2;
// circle.clip = true;

line.stroke = 'black';
line.linewidth = 2;

line.mask = circle;

two.update();

I have tried to comment out and keep the circle.clip = true line but it only hides the circle itself when set to true. The line itself is drawn normally.

What am I doing wrong?

I am using Two.js. This is a working example.


Solution

  • You can achieve it with something like

    var line = two.makeLine(center.x+circle.vertices[0].x, center.y+circle.vertices[0].y, center.x+circle.vertices[5].x, center.y+circle.vertices[5].y);
    

    output

    Update:

    The vertices are drawn based on the resolution chosen

    makeCircle: function(x, y, radius, resolution) {
    
        var circle = new Circle(x, y, radius, resolution);
        this.scene.add(circle);
    
        return circle;
    
      }
    

    and

    /**
     * @name Two.Circle
     * @class
     * @extends Two.Path
     * @param {Number} [x=0] - The x position of the circle.
     * @param {Number} [y=0] - The y position of the circle.
     * @param {Number} radius - The radius value of the circle.
     * @param {Number} [resolution=4] - The number of vertices used to construct the circle.
     */
    var Circle = function(ox, oy, r, resolution) {
    
      // At least 2 vertices are required for proper circlage
      var amount = resolution ? Math.max(resolution, 2) : 4;
    
      var points = [];
      for (var i = 0; i < amount; i++) {
        points.push(new Anchor());
      }
    
      Path.call(this, points, true, true, true);
    
      /**
       * @name Two.Circle#radius
       * @property {Number} - The size of the radius of the circle.
       */
      this.radius = r;
    
      this._update();
    
      if (typeof ox === 'number') {
        this.translation.x = ox;
      }
      if (typeof oy === 'number') {
        this.translation.y = oy;
      }
    
    };
    

    and

    _update: function() {
    
        if (this._flagRadius) {
          // Coefficient for approximating circular arcs with Bezier curves
          var c = (4 / 3) * Math.tan(Math.PI / (this.vertices.length * 2));
    
          var radius = this._radius;
          var rc = radius * c;
    
          for (var i = 0, numVertices = this.vertices.length; i < numVertices; i++) {
            var pct = i / numVertices;
            var theta = pct * TWO_PI;
    
            var x = radius * cos(theta);
            var y = radius * sin(theta);
    
            var lx = rc * cos(theta - HALF_PI);
            var ly = rc * sin(theta - HALF_PI);
    
            var rx = rc * cos(theta + HALF_PI);
            var ry = rc * sin(theta + HALF_PI);
    
            var v = this.vertices[i];
    
            v.command = Commands.curve;
            v.set(x, y);
            v.controls.left.set(lx, ly);
            v.controls.right.set(rx, ry);
          }
        }
    
        Path.prototype._update.call(this);
        return this;
    
      }
    

    https://github.com/jonobr1/two.js/blob/dev/src/shapes/circle.js#L23

    You can use the library or mathematically calculate the points