whakangā

In this example below you will see how to do a whakangā with some HTML / CSS and Javascript

Thumbnail
This awesome code was written by cyrilf, you can see more from this user in the personal repository.
You can find the original code on Codepen.io
Copyright cyrilf ©
  • HTML
  • CSS
  • JavaScript
<!DOCTYPE html>
<html lang="en" >

<head>
  <meta charset="UTF-8">
  <title>whakangā</title>
  
  
  
      <link rel="stylesheet" href="css/style.css">

  
</head>

<body>

  <canvas id="whakanga" width="800" height="400"></canvas>
  
  

    <script  src="js/index.js"></script>




</body>

</html>

/*Downloaded from https://www.codeseek.co/cyrilf/whakangandx101-NjzxRz */
body {
  margin: 0px;
  padding: 0px;
  background-color: lavender;
}
canvas {
  margin: 50px;
}


/*Downloaded from https://www.codeseek.co/cyrilf/whakangandx101-NjzxRz */
var _get = function get(object, property, receiver) { if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { return get(parent, property, receiver); } } else if ("value" in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } };

var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };

var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }

function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

// TODO
// - play sound on background

var Canvas = function Canvas(id) {
  _classCallCheck(this, Canvas);

  this.id = id;

  this.canvas = document.getElementById(id);
  this.ctx = this.canvas.getContext('2d');

  this.center = {
    x: this.canvas.width / 2,
    y: this.canvas.height / 2
  };
};

var Designer = function () {
  function Designer() {
    _classCallCheck(this, Designer);

    this.default = {
      color: 'lightSkyBlue',
      radius: 180,
      borderColor: 'red',
      width: 15
    };
    this.designs = [];
    this.generateDesigns();
    this.backgroundColor = 'lavender';

    this.radiusGrow = 0;
  }

  _createClass(Designer, [{
    key: 'generateDesigns',
    value: function generateDesigns() {

      this.designs.circle = {
        radius: this.default.radius,
        color: this.default.color,
        borderColor: this.default.borderColor,
        width: this.default.width
      };

      this.designs.cursor = {
        radius: 15,
        color: 'rgba(255, 255, 255, .9)',
        borderColor: 'rgba(0, 0, 0, .3)',
        width: 1
      };
    }
  }, {
    key: 'setRadiusGrow',
    value: function setRadiusGrow(value) {
      this.radiusGrow = value;
    }
  }, {
    key: 'update',
    value: function update() {
      this.updateCircleRadius();
    }
  }, {
    key: 'updateCircleRadius',
    value: function updateCircleRadius() {
      this.designs.circle.radius += this.radiusGrow;
    }
  }, {
    key: 'getBreatheColor',
    value: function getBreatheColor(breatheType) {
      var breatheColors = {
        in: 'lightSkyBlue',
        out: 'lightBlue',
        hold: 'royalBlue'
      };

      return breatheColors[breatheType];
    }
  }]);

  return Designer;
}();

var Painter = function () {
  function Painter(canvas, designer) {
    _classCallCheck(this, Painter);

    this.canvas = canvas.canvas;
    this.ctx = canvas.ctx;
    this.center = canvas.center;
    this.designer = designer;
  }

  _createClass(Painter, [{
    key: 'draw',
    value: function draw(breathe, cursor, currentAngle) {
      // this.reset()
      this.fillBackground();

      this.drawArcs(breathe);
      this.drawCursor(_extends({ coords: cursor.coords }, cursor.style));
    }

    // reset() {
    //   this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);  
    // }

  }, {
    key: 'fillBackground',
    value: function fillBackground() {
      this.ctx.fillStyle = this.designer.backgroundColor;
      this.ctx.fillRect(0, 0, this.canvas.width, this.canvas.height);
    }
  }, {
    key: 'drawArc',
    value: function drawArc(arc) {
      var _ref = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : style,
          center = _ref.center,
          radius = _ref.radius,
          width = _ref.width,
          color = _ref.color;

      this.ctx.beginPath();
      this.ctx.arc(this.center.x, this.center.y, radius, arc.start * Math.PI, arc.end * Math.PI);
      this.ctx.lineWidth = width;

      this.ctx.strokeStyle = this.designer.getBreatheColor(arc.type) || color;
      this.ctx.stroke();

      this.ctx.closePath();
    }
  }, {
    key: 'drawArcs',
    value: function drawArcs(arcs) {
      var _this = this;

      var design = this.designer.designs.circle;
      arcs.map(function (arc) {
        return _this.drawArc(arc, design);
      });
    }
  }, {
    key: 'drawCursor',
    value: function drawCursor(_ref2) {
      var coords = _ref2.coords,
          radius = _ref2.radius,
          color = _ref2.color,
          width = _ref2.width,
          borderColor = _ref2.borderColor;

      this.ctx.beginPath();
      this.ctx.arc(coords.x, coords.y, radius, 0, 2 * Math.PI);
      this.ctx.fillStyle = color;
      this.ctx.fill();
      this.ctx.lineWidth = width;
      this.ctx.strokeStyle = borderColor;
      this.ctx.stroke();
      this.ctx.closePath();
    }
  }]);

  return Painter;
}();

var Point = function Point() {
  var x = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0;
  var y = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;

  _classCallCheck(this, Point);

  this.x = x;
  this.y = y;
};

var Cursor = function Cursor(coords, cursorDesign) {
  _classCallCheck(this, Cursor);

  this.coords = coords;
  this.style = cursorDesign;
};

function getTime() {
  return new Date().getTime();
}

var Animator = function () {
  function Animator(tickCb) {
    var _ref3 = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : canvas,
        center = _ref3.center;

    var designer = arguments[2];

    _classCallCheck(this, Animator);

    this.angle = 2 * Math.PI;
    // this.angle = 3 * Math.PI / 180
    this.tickCb = tickCb;
    this.oldTime = getTime();
    this.center = center;
    // shit..
    this.designer = designer;
  }

  _createClass(Animator, [{
    key: 'animateCursor',
    value: function animateCursor(cursor) {
      var _this2 = this;

      var newTime = getTime();
      var diff = newTime - this.oldTime;
      this.oldTime = newTime;

      // this.angle += 0.5 * Math.PI / 180;
      // this.angle += 3 * Math.PI / 180;
      this.angle += diff * 0.0005;
      this.angle %= 2 * Math.PI;

      cursor.coords.x = this.center.x + this.designer.designs.circle.radius * Math.cos(this.angle);
      cursor.coords.y = this.center.y + this.designer.designs.circle.radius * Math.sin(this.angle);

      this.tickCb(cursor, this.angle);

      // window.setTimeout(() => this.animateCursor(cursor), 1000);

      requestAnimationFrame(function () {
        return _this2.animateCursor(cursor);
      });
    }
  }]);

  return Animator;
}();

var Breather = function Breather() {
  _classCallCheck(this, Breather);

  this.defaultBreathe = [{ start: 1.5, end: 0.25, type: 'in' }, { start: 0.25, end: 0.75, type: 'hold' }, { start: 0.75, end: 1.5, type: 'out' }];

  this.secondBreathe = [{ start: 1.5, end: 0.5, type: 'in' }, { start: 0.5, end: 1.5, type: 'out' }];

  this.thirdBreathe = [{ start: 1.5, end: 0, type: 'in' }, { start: 0, end: 0.5, type: 'hold' }, { start: 0.5, end: 1, type: 'out' }, { start: 1, end: 1.5, type: 'hold' }];
};

var EventNotifier = function () {
  function EventNotifier() {
    _classCallCheck(this, EventNotifier);

    this.observers = [];
  }

  _createClass(EventNotifier, [{
    key: 'on',
    value: function on(eventName, cb) {
      this.observers[eventName] = this.observers[eventName] || [];
      this.observers[eventName].push(cb);
    }
  }, {
    key: 'notify',
    value: function notify(eventName, value) {
      this.observers[eventName] && this.observers[eventName].map(function (observer) {
        return observer(value);
      });
    }
  }]);

  return EventNotifier;
}();

var Notifier = function (_EventNotifier) {
  _inherits(Notifier, _EventNotifier);

  function Notifier() {
    _classCallCheck(this, Notifier);

    var _this3 = _possibleConstructorReturn(this, (Notifier.__proto__ || Object.getPrototypeOf(Notifier)).call(this));

    _this3.currentBreatheType = null;
    return _this3;
  }

  _createClass(Notifier, [{
    key: 'checkBreatheType',
    value: function checkBreatheType(breathes, currentAngle) {
      var currentBreatheType = void 0;

      breathes.map(function (_ref4) {
        var end = _ref4.end,
            type = _ref4.type;

        if (!currentBreatheType && currentAngle >= 0 && currentAngle <= end * Math.PI) {
          currentBreatheType = type;
        }
      });

      breathes.map(function (_ref5) {
        var start = _ref5.start,
            end = _ref5.end,
            type = _ref5.type;

        if (!currentBreatheType && end * Math.PI < start * Math.PI) {
          currentBreatheType = type;
        }
      });

      if (currentBreatheType !== this.currentBreatheType) {
        this.currentBreatheType = currentBreatheType;
        _get(Notifier.prototype.__proto__ || Object.getPrototypeOf(Notifier.prototype), 'notify', this).call(this, 'newBreatheType', currentBreatheType);
      }

      return this.currentBreatheType;
    }
  }]);

  return Notifier;
}(EventNotifier);

var Singer = function () {
  function Singer() {
    _classCallCheck(this, Singer);

    this.songs = [];
    this.initSongs();
  }

  _createClass(Singer, [{
    key: 'initSongs',
    value: function initSongs() {
      this.songs['in'] = new Audio('http://www.storiesinflight.com/html5/audio/sweep.wav');
      this.songs['out'] = new Audio('http://www.storiesinflight.com/html5/audio/shimmer.wav');
      this.songs['hold'] = new Audio('http://www.storiesinflight.com/html5/audio/synth_vox.wav');
    }
  }, {
    key: 'playSong',
    value: function playSong(type) {
      this.songs[type].play();
    }
  }]);

  return Singer;
}();

// GO!


var canvas = new Canvas('whakanga');

var designer = new Designer();
var breather = new Breather();

var cursorDesign = designer.designs.cursor;
var cursorDefaultPos = new Point();
var cursor = new Cursor(cursorDefaultPos, cursorDesign);

var painter = new Painter(canvas, designer);
var notifier = new Notifier();
var singer = new Singer();

notifier.on('newBreatheType', function (breatheType) {
  singer.playSong(breatheType);
  var radiusGrow = 0;
  switch (breatheType) {
    case 'in':
      radiusGrow = .2;break;
    case 'out':
      radiusGrow = -0.2;break;
    case 'hold':
    default:
      radiusGrow = 0;
  }
  designer.setRadiusGrow(radiusGrow);
});

var animator = new Animator(function (cursor, currentAngle) {
  designer.update();
  painter.draw(breather.defaultBreathe, cursor, currentAngle);
  notifier.checkBreatheType(breather.defaultBreathe, currentAngle);
}, canvas, designer);

animator.animateCursor(cursor);

// whakanga
// veganTips
// travel.cyrilf.com
// towerDefense

Comments