How to pass Corner Blob effect to right side of the screen?

Asked

Viewed 48 times

4

I would like to reverse the effect demonstrated by starting from the right side of the screen and expanding to the left side, however, I did not achieve this. Someone could give me a light? Efeito de Corner Blob

const SCALE = 0.25;
const TWO_PI = Math.PI * 2;
const HALF_PI = Math.PI / 2;
const canvas = document.createElement("canvas");
const c = canvas.getContext("2d");

canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
document.body.appendChild(canvas);

class Blob {
  constructor() {
    this.wobbleIncrement = 0;
    // use this to change the size of the blob
    this.radius = 500;
    // think of this as detail level
    // number of conections in the `bezierSkin`
    this.segments = 12;
    this.step = HALF_PI / this.segments;
    this.anchors = [];
    this.radii = [];
    this.thetaOff = [];

    const bumpRadius = 100;
    const halfBumpRadius = bumpRadius / 2;

    for (let i = 0; i < this.segments + 2; i++) {
      this.anchors.push(0, 0);
      this.radii.push(Math.random() * bumpRadius - halfBumpRadius);
      this.thetaOff.push(Math.random() * TWO_PI);
    }

    this.theta = 0;
    this.thetaRamp = 0;
    this.thetaRampDest = 12;
    this.rampDamp = 25;
  }
  update() {
    this.thetaRamp += (this.thetaRampDest - this.thetaRamp) / this.rampDamp;
    this.theta += 0.03;

    this.anchors = [0, this.radius];
    for (let i = 0; i <= this.segments + 2; i++) {
      const sine = Math.sin(this.thetaOff[i] + this.theta + this.thetaRamp);
      const rad = this.radius + this.radii[i] * sine;
      const theta = this.step * i;
      const x = rad * Math.sin(theta);
      const y = rad * Math.cos(theta);
      this.anchors.push(x, y);
    }

    c.save();
    c.translate(-10, -10);
    c.scale(SCALE, SCALE);
    c.fillStyle = "blue";
    c.beginPath();
    c.moveTo(0, 0);
    bezierSkin(this.anchors, false);
    c.lineTo(0, 0);
    c.fill();
    c.restore();
  }
}

const blob = new Blob();

function loop() {
  c.clearRect(0, 0, canvas.width, canvas.height);
  blob.update();
  window.requestAnimationFrame(loop);
}
loop();

// array of xy coords, closed boolean
function bezierSkin(bez, closed = true) {
  const avg = calcAvgs(bez);
  const leng = bez.length;

  if (closed) {
    c.moveTo(avg[0], avg[1]);
    for (let i = 2; i < leng; i += 2) {
      let n = i + 1;
      c.quadraticCurveTo(bez[i], bez[n], avg[i], avg[n]);
    }
    c.quadraticCurveTo(bez[0], bez[1], avg[0], avg[1]);
  } else {
    c.moveTo(bez[0], bez[1]);
    c.lineTo(avg[0], avg[1]);
    for (let i = 2; i < leng - 2; i += 2) {
      let n = i + 1;
      c.quadraticCurveTo(bez[i], bez[n], avg[i], avg[n]);
    }
    c.lineTo(bez[leng - 2], bez[leng - 1]);
  }
}

// create anchor points by averaging the control points
function calcAvgs(p) {
  const avg = [];
  const leng = p.length;
  let prev;

  for (let i = 2; i < leng; i++) {
    prev = i - 2;
    avg.push((p[prev] + p[i]) / 2);
  }
  // close
  avg.push((p[0] + p[leng - 2]) / 2, (p[1] + p[leng - 1]) / 2);
  return avg;
}

Corner Blob in Codepen.io

2 answers

3


Basically just include the line canvas.style.transform = "scaleX(-1)"; at the beginning of the code setting the height and width of the canvas.

From what I saw the canvas is only in that position because it is the starting point of flow-content, x=0 y=0, i.e., upper left corner...

inserir a descrição da imagem aqui

The adjustment I made is basically CSS, there is no mystery, the result is below, I left commented

const TWO_PI = Math.PI * 2;
const HALF_PI = Math.PI / 2;
const canvas = document.createElement("canvas");
const c = canvas.getContext("2d");

canvas.width = window.innerWidth;
canvas.height = window.innerHeight;

// estilo que inverte a posição do canvas para a direita
canvas.style.transform = "scaleX(-1)";

document.body.appendChild(canvas);

class Blob {
  constructor() {
    this.wobbleIncrement = 0;
    // use this to change the size of the blob
    this.radius = 500;
    // think of this as detail level
    // number of conections in the `bezierSkin`
    this.segments = 12;
    this.step = HALF_PI / this.segments;
    this.anchors = [];
    this.radii = [];
    this.thetaOff = [];

    const bumpRadius = 100;
    const halfBumpRadius = bumpRadius / 2;

    for (let i = 0; i < this.segments + 2; i++) {
      this.anchors.push(0, 0);
      this.radii.push(Math.random() * bumpRadius - halfBumpRadius);
      this.thetaOff.push(Math.random() * 2 * Math.PI);
    }

    this.theta = 0;
    this.thetaRamp = 0;
    this.thetaRampDest = 12;
    this.rampDamp = 25;
  }
  update() {
    this.thetaRamp += (this.thetaRampDest - this.thetaRamp) / this.rampDamp;
    this.theta += 0.03;

    this.anchors = [0, this.radius];
    for (let i = 0; i <= this.segments + 2; i++) {
      const sine = Math.sin(this.thetaOff[i] + this.theta + this.thetaRamp);
      const rad = this.radius + this.radii[i] * sine;
      const x = rad * Math.sin(this.step * i);
      const y = rad * Math.cos(this.step * i);
      this.anchors.push(x, y);
    }

    c.save();
    c.translate(-10, -10);
    c.scale(0.5, 0.5);
    c.fillStyle = "blue";
    c.beginPath();
    c.moveTo(0, 0);
    bezierSkin(this.anchors, false);

    c.lineTo(0, 0);
    c.fill();
    c.restore();
  }}


const blob = new Blob();

function loop() {
  c.clearRect(0, 0, canvas.width, canvas.height);
  blob.update();
  window.requestAnimationFrame(loop);
}
loop();

// array of xy coords, closed boolean
function bezierSkin(bez, closed = true) {
  const avg = calcAvgs(bez);
  const leng = bez.length;

  if (closed) {
    c.moveTo(avg[0], avg[1]);
    for (let i = 2; i < leng; i += 2) {
      let n = i + 1;
      c.quadraticCurveTo(bez[i], bez[n], avg[i], avg[n]);
    }
    c.quadraticCurveTo(bez[0], bez[1], avg[0], avg[1]);
  } else {
    c.moveTo(bez[0], bez[1]);
    c.lineTo(avg[0], avg[1]);
    for (let i = 2; i < leng - 2; i += 2) {
      let n = i + 1;
      c.quadraticCurveTo(bez[i], bez[n], avg[i], avg[n]);
    }
    c.lineTo(bez[leng - 2], bez[leng - 1]);
  }
}

// create anchor points by averaging the control points
function calcAvgs(p) {
  const avg = [];
  const leng = p.length;
  let prev;

  for (let i = 2; i < leng; i++) {
    prev = i - 2;
    avg.push((p[prev] + p[i]) / 2);
  }
  // close
  avg.push((p[0] + p[leng - 2]) / 2, (p[1] + p[leng - 1]) / 2);
  return avg;
}

1

Look here is another example OK, but the important thing is logic

"use strict";

var Test = {
 canvas: undefined,
 canvasContext: undefined,
 rectanglePosition: 0
};
var i = 0; //"Localização" atual do quadrado
var direction = 1; //1 Se a div se mover para a direita, -1 Se a div se mover para esquerda

Test.start = function() {
 Test.canvas = document.getElementById("myCanvas");
 Test.canvasContext = 
 Test.canvas.getContext("2d");
 Test.mainLoop();
};
document.addEventListener('DOMContentLoaded', Test.start);
Test.update = function() {
 //var d = new Date();
 //Test.rectanglePosition = d.getTime() % Test.canvas.width;
 if (i <= 0) {
  direction = 1;
 } 
 else if (i >= (Test.canvas.width - 50)) {
  //Text.canvas.width - 50 é até onde o quadrado pode ir
  //Para a direita sem tirar o quadrado da tela
  //(Já que 50 é a largura do quadrado)
  direction = -1;
 }
 i += direction;
 Test.rectanglePosition = i;
};
Test.draw = function() {
 Test.canvasContext.fillStyle = "green";   
 Test.canvasContext.fillRect(Test.rectanglePosition, 100, 50, 50);
};
Test.mainLoop = function() {
 Test.clearCanvas();
 Test.update();
 Test.draw();
 window.setTimeout(Test.mainLoop, 1000 / 60);
};
Test.clearCanvas = function() {
 Test.canvasContext.clearRect(0, 0, Test.canvas.width, Test.canvas.height);
};

It is another example but it is not very important, just adjust, just take the example, and go modifying and testing, the explanation is in the comments of the comic, it is simple does not have much to explain, that’s it, and the answer vlw :)

Online comic:

https://codepen.io/Maria_eduarda/pen/GRNoVbv

Browser other questions tagged

You are not signed in. Login or sign up in order to post.