Skip to content

Latest commit

 

History

History
157 lines (139 loc) · 3.5 KB

index.md

File metadata and controls

157 lines (139 loc) · 3.5 KB
title scripts styles
Interactive Boid Text
h1 { text-align: center; } canvas { max-width: 100%; height: auto; } #p5-canvas { position: absolute; pointer-events: none; }

My ?Interactive Page

This is a demonstration of an ?interactive chart with boid text effect. Hover over the bars to see the magic!

// @run
// Chart setup
const canvas = document.querySelector('#charts');
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;

const interactiveWord = document.querySelector('[data-id="interactive-word"]');

const colors = [
  'rgb(255, 99, 132)',
  'rgb(54, 162, 235)',
  'rgb(255, 206, 86)',
  'rgb(75, 192, 192)',
  'rgb(153, 102, 255)',
  'rgb(255, 159, 64)'
];

const chart = new Chart(canvas.getContext('2d'), {
  type: 'bar',
  data: {
    labels: ['Red', 'Blue', 'Yellow', 'Green', 'Purple', 'Orange'],
    datasets: [{
      label: '# of Votes',
      data: [12, 19, 3, 5, 2, 3],
      backgroundColor: colors,
      borderColor: colors,
      borderWidth: 1
    }]
  },
  options: {
    animation: {
      duration: 0
    },
    responsive: true,
    onHover: (event, activeElements) => {
      if (activeElements && activeElements.length > 0) {
        const dataIndex = activeElements[0].index;
        startBoidAnimation(colors[dataIndex]);
      } else {
        stopBoidAnimation();
      }
    },
    scales: {
      y: {
        beginAtZero: true
      }
    }
  }
});

// p5.js setup
let boid;
let isAnimating = false;
let targetColor;

new p5(p => {
  p.setup = () => {
    const canvas = p.createCanvas(p.windowWidth, p.windowHeight);
    canvas.style('pointer-events', 'none');
    boid = new Boid(p, 0, 0);
  };

  p.draw = () => {
    p.clear();
    if (isAnimating) {
      boid.update();
      boid.display();
    }
  };

  p.windowResized = () => {
    p.resizeCanvas(p.windowWidth, p.windowHeight);
  };

  class Boid {
    constructor(p, x, y) {
      this.p = p;
      this.position = p.createVector(x, y);
      this.velocity = p.createVector();
      this.acceleration = p.createVector();
      this.maxSpeed = 5;
      this.maxForce = 0.2;
    }

    update() {
      this.velocity.add(this.acceleration);
      this.velocity.limit(this.maxSpeed);
      this.position.add(this.velocity);
      this.acceleration.mult(0);
    }

    applyForce(force) {
      this.acceleration.add(force);
    }

    seek(target) {
      let desired = p5.Vector.sub(target, this.position);
      desired.setMag(this.maxSpeed);
      let steer = p5.Vector.sub(desired, this.velocity);
      steer.limit(this.maxForce);
      this.applyForce(steer);
    }

    display() {
      this.p.fill(targetColor);
      this.p.noStroke();
      this.p.textSize(24);
      this.p.textAlign(this.p.CENTER, this.p.CENTER);
      this.p.text('Interactive', this.position.x, this.position.y);
    }
  }
}, 'p5-canvas');

function startBoidAnimation(color) {
  if (!isAnimating) {
    const rect = interactiveWord.getBoundingClientRect();
    boid.position.x = rect.left + rect.width / 2;
    boid.position.y = rect.top + rect.height / 2;
    interactiveWord.style.color = color;
    document.querySelector('[data-id="i"]').style.color = color;
  }
  isAnimating = true;
  targetColor = color;
}

function stopBoidAnimation() {
  isAnimating = false;
  interactiveWord.style.opacity = '1';
}