Pixelbits

Hi, I'm @jasonlong. I'm trying to make a small creative coding sketch every day(ish) to learn new things. All code is available in the GitHub repo.

Animated woofer. The frequency is so low you probably can't even hear it. Show code

<script type="text/paperscript" canvas="canvas-0011">
  var wooferSize = view.size.height * 0.4;

  var outerRing = new Path.Circle({
    center: view.center,
    radius: wooferSize *= 1.1,
    fillColor: '#111111'
  });

  var cone = new Path.Circle({
    center: view.center,
    radius: wooferSize * 0.97
  });

  cone.fillColor = {
      gradient: {
          stops: [['#1d1d1d', 0.3 ], ['#444444', 1]],
          radial: true
      },
      origin: cone.bounds.topCenter + [0, 30],
      destination: cone.bounds.rightCenter
  };

  var centerRing = new Path.Circle({
    center: view.center,
    radius: wooferSize / 3
  });

  centerRing.fillColor = {
      gradient: {
          stops: [['#444444', 0.3 ], ['#111111', 1]],
          radial: true
      },
      origin: centerRing.bounds.topCenter + [0, 30],
      destination: centerRing.bounds.rightCenter
  };

  var center = new Path.Circle({
    center: view.center,
    radius: wooferSize / 3.2
  });

  center.fillColor = {
      gradient: {
          stops: [['#aaaaaa', 0.1], ['#3f3f3f', 0.5], ['#222222', 1]],
          radial: true
      },
      origin: center.bounds.topCenter + [0, wooferSize * 0.1],
      destination: center.bounds.rightCenter
  };

  // Build the woofer group
  var woofer = new Group(cone, centerRing, center);
  var wooferBounds = woofer.bounds;
  var frameCount = 0;

  function onFrame(event) {
    // 60 fps, so hit a bass note every 2/3 of a
    // second or 90 bpm
    if (frameCount++ == 40) {
      woofer.scale(1.04);
      frameCount = 0;
    }
    else if (event.count % 2) {
      woofer.fitBounds(wooferBounds);
    }
    else {
      woofer.scale(1.02, woofer.center);
    }
  }
</script>

<canvas id="canvas-0011" height="250"></canvas>

Rotating square tunnel inspired by Albert Omoss' Pivot project. Show code

<script type="text/paperscript" canvas="canvas-0010">
  var i = 1;
  var color = 'dark';
  while (i < view.size.width / 2) {
    var rect = new Rectangle({
                  center: view.center,
                  size: i * 1.5
                });
    var path = new Path.Rectangle(rect);
    path.strokeWidth = 0.2 * i;

    // I tried to rotate the furthest away and nearest squares for a
    // a nice twisting effect, but the furthest away squares are so
    // small that they aren't even visible.
    path.rotate(Math.pow(Math.abs(i - view.size.width/2), 2) * 0.0008);

    if (color == 'dark') {
      path.strokeColor = '#111111';
      color = 'light';
    }
    else {
      path.strokeColor = '#ffffff';
      color = 'dark';
    }
    // Simulate perspective with top squares appearing closer
    i *= 1.1;
  }
</script>

<canvas id="canvas-0010" height="250"></canvas>

Animated circles shifting hues and cycling between color blending modes. Show code

<script type="text/paperscript" canvas="canvas-0009">
  var radius = view.size.width / 4;
  var start1 = new Point(radius, view.size.height / 2);
  var start2 = new Point(view.size.width - radius, view.size.height / 2);

  var modes = ['multiply', 'screen', 'overlay', 'soft-light', 'hard-light', 'color-dodge'];

  var modeIndex = 0;

  var circle1 = new Path.Circle({
    center: start1,
    radius: radius,
    fillColor: '#0074d9',
    blendMode: modes[modeIndex]
  });
  var circle2 = new Path.Circle({
    center: start2,
    radius: radius,
    fillColor: '#ff4136',
    blendMode: modes[modeIndex]
  });

  function onFrame(event) {
    var vector1 = start2 - circle1.position;
    var vector2 = start1 - circle2.position;

    if (vector1.length == 0) {
      // swap directions
      var tmpStart = start1;
      start1 = start2;
      start2 = tmpStart;

      if (modes.length - 1 == modeIndex) {
        modeIndex = 0;
      }
      else {
        modeIndex++;
      }

      circle1.blendMode = modes[modeIndex];
      circle2.blendMode = modes[modeIndex];
    }

    circle1.position.x += (vector1.x < 0) ? -2 : 2;
    circle2.position.x += (vector2.x < 0) ? -2 : 2;

    circle1.fillColor.hue += 1;
    circle2.fillColor.hue += 1;
  }
</script>

<canvas id="canvas-0009" height="250"></canvas>

Isometric cubes with faux shadows. Show code

<script type="text/paperscript" canvas="canvas-0008">
  var columns = 12;
  var isoSize = view.size.width / columns;
  var isoWidth = isoSize * Math.sqrt(3) / 2;
  var row = 0;
  var lightFalloff = 0.0008;

  for (var y = 0; y <= view.size.height + isoSize; y += isoSize - isoSize / 4) {
    row++;
    for (var x = 0; x <= view.size.width + isoWidth; x += isoWidth) {

      var group = new Group();
      var dx = (row % 2) ? isoWidth / 2 : 0;
      var hexagon = new Path.RegularPolygon([x-dx,y], 6, isoSize / 2);
      group.addChild(hexagon);

      for (var i = 0; i < 2; i++) {
        var path = new Path();
        for (var j = 0; j < 3; j++) {
          var index = (i * 2 + j) % hexagon.segments.length;
          path.add(hexagon.segments[index].clone());
        }
        path.add(hexagon.bounds.center);
        group.addChild(path);
      }

      var color = "#b10dc9";

      group.children[0].fillColor = color;
      group.children[1].fillColor = color;
      group.children[2].fillColor = color;
      group.children[0].fillColor.brightness *= 0.75 - (y * lightFalloff);
      group.children[1].fillColor.brightness *= 1 - (y * lightFalloff);
      group.children[2].fillColor.brightness *= 0.55 - (y * lightFalloff);
    }
  }
</script>

<canvas id="canvas-0008" height="250"></canvas>

Copying and rotating shape groups. Show code

<script type="text/paperscript" canvas="canvas-0007">
  var bgColor = "#2f325c";
  var fgColor = "#405e7d";

  view.element.style.backgroundColor = bgColor;

  var center = new Point(0, 0);
  var points = 4;
  var radius1 = view.size.height / 12;
  var radius2 = view.size.height / 3;

  var star = new Path.Star(center, points, radius1, radius2);
  star.strokeColor = fgColor;
  star.rotate(45);
  var lineH = new Path.Line({
      from: [0, -radius2],
      to: [0, radius2],
      strokeColor: fgColor
  });

  var lineV = new Path.Line({
      from: [-radius2, 0],
      to: [radius2, 0],
      strokeColor: fgColor
  });

  var starGroup = new Group();
  starGroup.addChildren([star, lineH, lineV]);

  // Stars
  for (i = 0; i < 90; i += 22.5) {
      var newStar = starGroup.clone();
      newStar.rotate(i);
  }
  starGroup.remove();

  // Circles
  for (i = radius1; i <= radius2; i += radius1) {
      var circle = new Path.Circle(new Point(0, 0), i);
      circle.strokeColor = fgColor;
  }

  project.activeLayer.position = view.center;
</script>

<canvas id="canvas-0007" height="250"></canvas>

Pseudo-spirograph made of rotating rounded squares. Show code

<script type="text/paperscript" canvas="canvas-0006">
  view.element.style.backgroundColor = '#111111';

  var rectSize = view.size.width * 0.3;
  var cornerRadius = rectSize * 0.1;

  var color = new Color('#0074d9');
  var rect = new Rectangle(new Point(0, 0), new Size(rectSize, rectSize));
  var cornerSize = new Size(cornerRadius, cornerRadius);
  var shape = new Shape.Rectangle(rect, cornerSize);
  shape.strokeColor = color;

  for (i = 0; i < 360; i += 10) {
      var newShape = shape.clone();
      newShape.strokeColor.hue += i;
      newShape.rotate(i, [rectSize/4, rectSize/4]);
  }

  shape.remove();
  project.activeLayer.position = view.center;
</script>

<canvas id="canvas-0006" height="250"></canvas>

Rotating paths, hue shifting, and blending modes. Show code

<script type="text/paperscript" canvas="canvas-0005">
  var color = new Color('#0074d9');
  color.alpha = 0.6;

  var circle = new Path.Circle({
        center: [100, 100],
        radius: 20,
        fillColor: color
      });

  circle.scale(1.5, 3.5);

  for (i = 0; i < 360; i += 60) {
    var newCircle = circle.clone();
    newCircle.fillColor.hue += i;
    newCircle.blendMode = 'screen';
    newCircle.rotate(i, [100, 150]);
  }

  circle.remove();

  project.activeLayer.position = view.center;
</script>

<canvas id="canvas-0005" height="250"></canvas>

Overly verbose code for a continuous gradient hexagon. Show code

<script type="text/paperscript" canvas="canvas-0004">
  view.element.style.backgroundColor = '#111111';

  var color = new Color('#0074d9');
  var strokeWidth = view.size.height * 0.04;

  var c = view.size.height / 3;
  var a = c/2;
  var b = Math.sin(60 * Math.PI / 180) * c;

  path = new Path.Line([0, b], [a, 0]);
  var color1 = color.clone();
  var color2 = color.clone();
  color2.hue += 60;
  var gradient = new Gradient([color1, color2]);
  path.strokeColor = new Color(gradient, [0, b], [a, 0]);
  path.strokeWidth = strokeWidth;
  path.strokeCap = 'round';

  path = new Path.Line([a, 0], [a+c, 0]);
  var color1 = color.clone();
  var color2 = color.clone();
  color1.hue += 60;
  color2.hue += 120;
  var gradient = new Gradient([color1, color2]);
  path.strokeColor = new Color(gradient, [a, 0], [a+c, 0]);
  path.strokeWidth = strokeWidth;
  path.strokeCap = 'round';

  path = new Path.Line([a+c, 0], [2*c, b]);
  var color1 = color.clone();
  var color2 = color.clone();
  color1.hue += 120;
  color2.hue += 180;
  var gradient = new Gradient([color1, color2]);
  path.strokeColor = new Color(gradient, [a+c, 0], [2*c, b]);
  path.strokeWidth = strokeWidth;
  path.strokeCap = 'round';

  path = new Path.Line([2*c, b], [a+c, 2*b]);
  var color1 = color.clone();
  var color2 = color.clone();
  color1.hue += 180;
  color2.hue += 240;
  var gradient = new Gradient([color1, color2]);
  path.strokeColor = new Color(gradient, [2*c, b], [a+c, 2*b]);
  path.strokeWidth = strokeWidth;
  path.strokeCap = 'round';

  path = new Path.Line([a+c, 2*b], [a, 2*b]);
  var color1 = color.clone();
  var color2 = color.clone();
  color1.hue += 240;
  color2.hue += 300;
  var gradient = new Gradient([color1, color2]);
  path.strokeColor = new Color(gradient, [a+c, 2*b], [a, 2*b]);
  path.strokeWidth = strokeWidth;
  path.strokeCap = 'round';

  path = new Path.Line([a, 2*b], [0, b]);
  var color1 = color.clone();
  var color2 = color.clone();
  color1.hue += 300;
  color2.hue += 360;
  var gradient = new Gradient([color1, color2]);
  path.strokeColor = new Color(gradient, [a, 2*b], [0, b]);
  path.strokeWidth = strokeWidth;
  path.strokeCap = 'round';

  project.activeLayer.position = view.center;
</script>

<canvas id="canvas-0004"></canvas>

Shifting hues using yesterday's sine wave. Show code

<script type="text/paperscript" canvas="canvas-0003">
  view.element.style.backgroundColor = '#111111';

  var y = view.size.height / 2;
  var width = view.size.width * 0.9;
  var vector = new Point({
        angle: 45,
        length: width / 5
        });
  var offset = width / 30;
  var color = new Color('#0074d9')

  for (var i = 0; i < 40; i+=3) {
    var path = new Path();
    vector.length += i;
    path.segments = [
      [[offset, y], null, vector.rotate(-90-i)],
      [[width / 2, y], vector.rotate(-180+i), vector.rotate(i)],
      [[width - offset, y], vector.rotate(90-i), null]
    ];
    path.strokeColor = color;
    path.strokeColor.hue += i * 10;
  }
  project.activeLayer.position = view.center;
</script>

<canvas id="canvas-0003" height="300"></canvas>

Sine waves made by manipulating bezier handles. Show code

<script type="text/paperscript" canvas="canvas-0002">

  var y = view.size.height / 2;
  var width = view.size.width * 0.9;
  var vector = new Point({
        angle: 45,
        length: width / 5
        });
  var offset = width / 30;

  for (var i = 0; i < 40; i+=3) {
    var path = new Path();
    vector.length += i;
    path.segments = [
      [[offset, y], null, vector.rotate(-90-i)],
      [[width / 2, y], vector.rotate(-180+i), vector.rotate(i)],
      [[width - offset, y], vector.rotate(90-i), null]
    ];
    path.strokeColor = '#0074d9';
  }

  project.activeLayer.position = view.center;
</script>

<canvas id="canvas-0002" height="300"></canvas>