Calculate ellipse size in relation to distance from center point

后端 未结 1 728
暖寄归人
暖寄归人 2021-01-28 14:51

I want to achieve a slow fade in size on every collapse into itself. In other words, when the circle is at its biggest, the ellipses will be at the largest in size and conversel

相关标签:
1条回答
  • 2021-01-28 15:12

    The values you're passing into the map() function don't make a lot of sense to me:

    float fromCenter = map(cSize, 0, d, 1, 100);
    

    The cSize variable bounces from 1 to 10 independent of anything else. The d variable is the distance of each ellipse to the center of the circle, but that's going to be static for each one since you're using the rotate() function to "move" the circle, which never actually moves. That's based only on the frameCount variable, which you never use to calculate the size of your ellipses.

    In other words, the position of the ellipses and their size are completely unrelated in your code.

    You need to refactor your code so that the size is based on the distance. I see two main options for doing this:

    Option 1: Right now you're moving the circles on screen using the translate() and rotate() functions. You could think of this as the camera moving, not the ellipses moving. So if you want to base the size of the ellipse on its distance from some point, you have to get the distance of the transformed point, not the original point.

    Luckily, Processing gives you the screenX() and screenY() functions for figuring out where a point will be after you transform it.

    Here's an example of how you might use it:

      for (int x = -50; x <= 50; x+=100) {
        for (int y = -50; y <= 50; y+=100) {
          pushMatrix();
    
          //transform the point
          //in other words, move the camera
          translate(x, y);
          rotate(radians(frameCount));
    
          //get the position of the transformed point on the screen
          float screenX = screenX(x, y);
          float screenY = screenY(x, y);
    
          //get the distance of that position from the center
          float distanceFromCenter = dist(screenX, screenY, width/2, height/2);
    
          //use that distance to create a diameter
          float diameter = 141 - distanceFromCenter;
    
          //draw the ellipse using that diameter
          ellipse(x, y, diameter, diameter);
          popMatrix();
        }
      }
    

    Option 2: Stop using translate() and rotate(), and use the positions of the ellipses directly.

    You might create a class that encapsulates everything you need to move and draw an ellipse. Then just create instances of that class and iterate over them. You'd need some basic trig to figure out the positions, but you could then use them directly.

    Here's a little example of doing it that way:

    ArrayList<RotatingEllipse> ellipses = new ArrayList<RotatingEllipse>();
    
    void setup() {
      size(500, 500);
      ellipses.add(new RotatingEllipse(width*.25, height*.25));
      ellipses.add(new RotatingEllipse(width*.75, height*.25));
      ellipses.add(new RotatingEllipse(width*.75, height*.75));
      ellipses.add(new RotatingEllipse(width*.25, height*.75));
    }
    
    void draw() {
      background(0);
    
      for (RotatingEllipse e : ellipses) {
        e.stepAndDraw();
      }
    }
    
    void mouseClicked() {
      ellipses.add(new RotatingEllipse(mouseX, mouseY));
    }
    
    void mouseDragged() {
      ellipses.add(new RotatingEllipse(mouseX, mouseY));
    }
    
    class RotatingEllipse {
    
      float rotateAroundX;
      float rotateAroundY;
      float distanceFromRotatingPoint;
      float angle;
    
      public RotatingEllipse(float startX, float startY) {
    
        rotateAroundX = (width/2 + startX)/2;
        rotateAroundY = (height/2 + startY)/2;
    
        distanceFromRotatingPoint = dist(startX, startY, rotateAroundX, rotateAroundY);
    
        angle = atan2(startY-height/2, startX-width/2);
      }
    
      public void stepAndDraw() {
    
        angle += PI/64;
    
        float x = rotateAroundX + cos(angle)*distanceFromRotatingPoint;
        float y = rotateAroundY + sin(angle)*distanceFromRotatingPoint;
    
        float distance = dist(x, y, width/2, height/2);
        float diameter = 50*(500-distance)/500;
    
        ellipse(x, y, diameter, diameter);
      }
    }
    

    Try clicking or dragging in this example. User interaction makes more sense to me using this approach, but which option you choose really depends on what fits inside your head the best.

    0 讨论(0)
提交回复
热议问题