Some fun with sinusoidals, like a catalog

click through more than 30 different expressions.




let pg;
let points = ;
let x = 0;
let res = 1;
let expression = "";
let expr = 0;
let valInput = 0;

// Geometric layouts calculated based on window size
let v_size;     // Height of the red strip
let graphTop;   // Y-coordinate where white space begins
let graphHeight;// Height of the available white space
let v_center;   // The calculated center (0 point) of the white space

function setup() {
  createCanvas(windowWidth, windowHeight);
  pixelDensity(1); // Ensures crisp rendering across standard and high-DPI retina screens
  smooth();
  
  calculateLayout();
  pg = createGraphics(width, height);
  pg.pixelDensity(1);
  drawGraphBackground();
}

function calculateLayout() {
  // Red strip takes up the upper quarter of the screen
  v_size = height / 4; 
  graphTop = v_size;
  graphHeight = height - graphTop;
  // Center the 0 baseline perfectly in the remaining bottom space
  v_center = graphTop + (graphHeight / 2);
}

function draw() {
  x += res;
  
  // Calculate screen position separately using modulo. 
  // When screenX reaches the right border, it wraps back to 0.
  let screenX = x % width;

  // If screenX just wrapped around to 0, clear a small sliver ahead 
  // of the dot so it creates a continuous tracking "scan line" effect
  if (screenX === 0) {
    drawGraphBackground();
  }

  let xR = radians(x); 

  switch (expr) {
    case 0:
      valInput = sin(xR);
      expression = "y = sin(x)";
      break;
    case 1:
      valInput = sin(tan(xR) * pow(sin(xR), 10));
      expression = "y = sin(tan(x)*sin(x)^10)";
      break;
    case 2:
      valInput = pow(sin(xR * PI), 12);
      expression = "y = (sin(x*PI))^12";
      break;
    case 3:
      valInput = cos(sin(xR * 3) + xR * 3);
      expression = "y = cos(sin(x*3)+x*3)";
      break;
    case 4:
      valInput = (x % 100) / 100;
      expression = "y = (x%100/100)";
      break;
    case 5:
      valInput = sin(tan(cos(xR) * 1.2));
      expression = "y = sin(tan(cos(x)*1.2))";
      break;
    case 6:
      valInput = cos(xR) * sin(xR);
      expression = "y = cos(x)*sin(x)";
      break;
    case 7:
      valInput = sin(xR) * sin(xR * 1.5);
      expression = "y = cos(x)*sin(x*1.5)";
      break;
    case 8:
      valInput = sin(tan(xR) * 0.05);
      expression = "y = sin(tan(x)*0.05)";
      break;
    case 9:
      valInput = cos(sin(xR * 3)) * sin(xR * 0.2);
      expression = "y = cos(sin(x*3))*sin(x*2)";
      break;
    case 10:
      valInput = sin(pow(8, sin(xR)));
      expression = "y = sin(8^sin(x))";
      break;
    case 11:
      valInput = sin(exp(cos(xR * 0.8)) * 2);
      expression = "y = sin(e^cos(x*0.8)*2)";
      break;
    case 12:
      valInput = sin(xR - PI * tan(xR) * 0.01);
      expression = "y = sin(x-PI*tan(x)*0.01)";
      break;
    case 13:
      valInput = pow(sin(xR * PI), 12);
      expression = "y = sin(x*PI)^12";
      break;
    case 14:
      valInput = cos(sin(xR) * tan(xR * PI) * PI / 8);
      expression = "y = cos(sin(x)*tan(x*PI)*PI/8)";
      break;
    case 15:
      valInput = cos(sin(xR * 3) + xR * 3);
      expression = "y = cos(sin(x*3))+x*3";
      break;
    case 16:
      valInput = pow(abs(sin(xR * 2)) * 0.6, sin(xR * 2)) * 0.5;
      expression = "y = |(sin(x*2)*0.6)^sin(x*2)*0.5|";
      break;
    case 17:
      valInput = abs((xR % 2) - 1);
      expression = "y = |x%2-1|";
      break;
    case 18:
      valInput = sin(xR) * tan(xR * 0.1);
      expression = "y = sin(x)*tan(x)*0.1";
      break;
    case 19:
      valInput = (cos(xR) * sin(xR * 30)) * 0.3;
      expression = "y = (cos(x) * sin(x*30))*0.3";
      break;
    case 20:
      valInput = cos(xR * (xR * 0.5));
      expression = "y = cos(x*(x*0.5))";
      break;
    case 21:
      valInput = cos(xR) * (tan(xR * 0.5) * 0.1);
      expression = "y = cos(x)* tan(x*0.5)*0.1";
      break;
    case 22:
      valInput = sqrt(abs(sin(xR))); 
      expression = "y = squareRoot(|sin(x)|)";
      break;
    case 23:
      valInput = sqrt(abs(sin(xR) * sin(xR * 2))); 
      expression = "y = squareRoot(|sin(x)*sin(x*2)|)";
      break;
    case 24:
      valInput = sqrt(abs(sin(xR) * sin(xR * 10)));  
      expression = "y = squareRoot(|sin(x)*sin(x*10)|)";
      break;
    case 25:
      valInput = tan(sin(xR) * cos(xR * 3)); 
      expression = "y = tan(sin(x)*cos(x))";
      break;
    case 26:
      valInput = sin(tan(cos(xR)));
      expression = "y = sin(tan(cos(x)))";
      break;
    case 27:
      valInput = sin(tan(xR)); 
      expression = "y = sin(tan(x))";
      break;
    case 28:
      valInput = sin(xR * sin(xR * 0.05));
      expression = "y = sin(x * sin(x * 0.05))";
      break;
    case 29:
      valInput = sin(xR) * abs(tan(xR * 0.5) * 0.2);
      expression = "y = sin(x) * |tan(x * 0.5) * 0.2|";
      break;
    case 30:
      valInput = sin(xR * 2) * exp(-xR * 0.05);
      expression = "y = sin(x * 2) * e^(-x * 0.05)";
      break;
  }

  background(255);
  image(pg, 0, 0);
  drawExpression(0, 0, width, height, valInput, screenX, expression);
}

function mouseReleased() {
  drawGraphBackground();
  x = 0;
  expr = (expr + 1) % 31; 
}

function drawGraphBackground() {
  pg.clear();
  pg.background(255);
  pg.stroke(240);
  pg.strokeWeight(1);
  
  let amplitudeOffset = graphHeight / 6; 
  pg.line(0, v_center, width, v_center);
  pg.line(0, v_center - amplitudeOffset, width, v_center - amplitudeOffset);
  pg.line(0, v_center + amplitudeOffset, width, v_center + amplitudeOffset);
}

function drawExpression(_x, y, w, h, value_y, screen_x, _expression) {
  let h_center = w / 2;
  let isMobile = w < 768;

  let pos_x = _x + screen_x;
  let pos_y = v_center + (-value_y * (graphHeight / 5));

  // Draw wave into graphics buffer
  pg.stroke(0);
  pg.strokeWeight(2);
  pg.point(pos_x, pos_y);

  // Render upper layout panel
  noStroke();
  fill(255, 200, 180); 
  rect(_x, _x, w, v_size);

  let el_x = h_center + (-value_y * w / 4);
  let el_y = v_size / 2;

  let s = map(value_y, -1, 1, 2, 80);

  // Pulse ellipse
  noStroke();
  fill(240);
  ellipse(w / 2, el_y, s, s);

  // Horizontal moving tracking tracker
  stroke(20, 20, 20, 40);
  strokeWeight(15);
  noFill();
  ellipse(el_x, el_y + 104, 40, 40);

  // Instructions line centered beneath layout block - Shrunk to size 15
  textSize(15);
  fill(200);
  noStroke();
  let instructionText = "clique em qualquer lugar pra ver outras expressões.";
  if (textWidth(instructionText) > w - 20) {
    instructionText = "clique pra ver outras expressões.";
  }
  text(instructionText, w / 2 - textWidth(instructionText) / 2, v_size + 22);

  // Setup clean text formatting strings with exactly 3 decimals
  let st_y = (value_y >= 0 ? " +" : " ") + nf(abs(value_y), 1, 3);
  let st_x = (x >= 0 ? " +" : " ") + nf(abs(x), 1, 3); // Displays the true infinite math X value

  textSize(20);
  fill(100);
  noStroke();
  
  let textYLabel = "y = ";
  let textXLabel = "x = ";

  let yLabelX, yValX, yYPos;
  let xLabelX, xValX, xYPos;

  // Handle structural screen collision layout logic
  if (isMobile) {
    // Stack layout vertically on small phones to stop overlap
    yYPos = v_center + (graphHeight / 3.2);
    xYPos = yYPos + 25;

    yLabelX = h_center - 60;
    yValX = yLabelX + textWidth(textYLabel);

    xLabelX = h_center - 60;
    xValX = xLabelX + textWidth(textXLabel);
  } else {
    // Safe wide desktop layout configuration
    yYPos = v_center + (graphHeight / 4);
    xYPos = yYPos;

    let labelOffset = min(180, w * 0.22);
    yLabelX = h_center - textWidth(textYLabel) - labelOffset;
    yValX = h_center - labelOffset;

    xLabelX = h_center + labelOffset - textWidth(textXLabel + st_x);
    xValX = xLabelX + textWidth(textXLabel);
  }
  
  // Draw dynamic numeric reads
  text(textYLabel, yLabelX, yYPos);
  text(st_y, yValX, yYPos);
  text(textXLabel, xLabelX, xYPos);
  text(st_x, xValX, xYPos);

  // Vector tracking reference guidelines configuration
  strokeWeight(0.5);
  stroke(220);
  
  if (!isMobile) {
    line(yValX, yYPos, pos_x, pos_y);
    line(xLabelX, xYPos, pos_x, pos_y);
  }
  
  // Crosshair tracking lines mapping back to view axes
  line(pos_x, graphTop, pos_x, height);
  line(0, pos_y, width, pos_y);

  stroke(200);
  line(xLabelX, xYPos + 2, xValX + textWidth(st_x), xYPos + 2);
  line(yLabelX, yYPos + 2, yValX + textWidth(st_y), yYPos + 2);

  stroke(80);
  strokeWeight(6);
  point(pos_x, pos_y);

  // Write expression name at bottom (responsively scaled size)
  textSize(isMobile ? 16 : 25);
  fill(200);
  noStroke();
  text(_expression, width / 2 - textWidth(_expression) / 2, height - 15);
}

function windowResized() {
  resizeCanvas(windowWidth, windowHeight);
  calculateLayout();
  pg = createGraphics(width, height);
  pg.pixelDensity(1);
  drawGraphBackground();
  x = 0; 
}
```

used some ai to help me making it responsive and to translate to js (was java origanaly)

1 Like