4

I have an exponential curve made using p5.js that draws itself over time as follow :

enter image description here

However I am trying to have it responsive in such a way that as the curve grows, it would always be fully visible inside the canvas.

Here are screenshots of what I mean to achieve :

description description
description
Working examples found on a website

As you can see on this example, once it reaches the edges of the canvas, it kind of "zooms out" in order for the canvas to fit the whole curve, as a result since it never leaves the canvas the curve bends the more it grows.

To try and achieve this, I explored using scale scale(x / 100, y / 100) to be triggered once the limits of the canvas are reached. That way the canvas starts scaling proportionally to the curve's expansion.

However, using this method does not solve my problem because it seems that reducing the scaling while adding points to the curve does not make the curve grow anymore.

Here is my current (updated) code :

var y = 49;
var x = 0;
var inc = 0.02;
var translateY;
let createTopY = false;
let createTopX = false;
var topY;
var percentageIncY = 100;
var perecntageIncX = 100;
// Scaling
var scaleX = 1
var scaleY = 1

function setup() {
  createCanvas(400, 200);
  background(20, 25, 29)
}

function draw() {
  
  frameRate(20)
  
  // Set curve history for continuous lines
  let prev_x = x
  let prev_y = y

  // Recreate canvas position (origin) based on Scale Y (zoom)
  translateY = height * scaleY
  translate(0, (height - translateY) + 49 ) // 49 is the initial y value
  scale(scaleX, scaleY)

  // Exponential curve values
  x = x + 5 // Approximate
  y = y + y * inc

  // Draw curve
  strokeWeight(3)
  stroke(229, 34, 71);
  line(prev_x, height - prev_y, x, height - y);

  // Create topY when top at scale(1) is reached
  if (createTopY !== true) checkInt(y)
  if (createTopX !== true) checkInt(x)

  //-------------- SCALING ---------------//

  // From TopX, decrease scale exponentialy
  if (x > width - 20) { // Temporarily set to 20 (50-30) to better visualize
    
    // The increased value of x in % starting at topX
    percentageIncX = (x * 100) / (width - 20)
    
    // Decrease scaleX exponentialy
    scaleX = 100 / percentageIncX
    
    print(
      "% increase X: " +
      percentageIncX
    )
  }

  // From topY, decrease scale exponentialy
  if (y > height + 20) { // Temporarily set to 20 (50-30) to visualize
    
    // The increased value of y in % starting at topY
    percentageIncY = (y * 100) / (height + 20) // Temporarily set to 20 (50-30) to better visualize
    
    // Decrease scaleY exponentialy
    scaleY = 100 / percentageIncY
    
    print(
      "% increase Y: " +
      percentageIncY
    )
  }
  //-------------------------------------//
}

const checkInt = (prop) => {
  const parsed = int(prop)
  
  if (parsed > height + 20) { // Temporarily set to 20 (50-30) to better visualize
    createTopY = true
    createTopX = true
    topY = y
    print('createTopY is: ' + createTopY)
    print('createTopX is: ' + createTopX)
    print("---START SCALING---")
    print('starting at ' + y)
  }
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.1.9/p5.min.js"></script>
Monstar
  • 795
  • 1
  • 5
  • 23
  • Does `p5.js` have a `setInterval` function like Javascript? You could then use it to schedule your ellipse drawing function which would trace out the curve. – SuperJumbo Jan 14 '21 at 03:02
  • You can use [`frameRate()`](https://p5js.org/reference/#/p5/frameRate) to control to the number of frames to be displayed every second. However, I do not understand your question. What do you mean by *"it would always be fully visible"*? Do you want to draw a curve without interruptions? – Rabbid76 Jan 14 '21 at 05:38
  • @Rabbid76 I just noticed my question can be missunderstood. By "fully visible" I mean that it wouldn't leave the frame as it reaches the top-right corner. I will edit my question with some screenshots. – Monstar Jan 14 '21 at 08:36

1 Answers1

4

Use frameRate() to control to the number of frames to be displayed every second. Stitch the curve with line segments (line()) instead of drawing with single dots (ellipse()) to draw a curve without interruptions.

var y = 1;
var x = 0;
var inc = 0.01;

function setup() {
    createCanvas(400, 400);
    background(100)
    frameRate(100)
}

function draw() {
    let prev_x = x;
    let prev_y = y;
    x = x + 0.5
    y = y + y * inc;

    noFill();
    stroke(255, 0, 0, 255);
    strokeWeight(3);
    line(prev_x, height-prev_y, x, height-y);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.1.9/p5.min.js"></script>
Rabbid76
  • 202,892
  • 27
  • 131
  • 174