2
\$\begingroup\$

I've written a simple app that draws with a kaleidoscope effect in javascript, could someone please review the code? I'm especially interested in functional practices and design patterns.

const game = {
  pi2: Math.PI*2,
  sides: 12,
  background: '125,125,125',
  load: function () {
    game.canvas = document.createElement('canvas');
    game.ctx = game.canvas.getContext('2d');
    document.body.appendChild(game.canvas);
    document.body.style.overflow = 'hidden';
    document.body.style.background = 'rgba('+game.background+',1)';
    game.resize();
    game.input = document.querySelector('input');
    game.input.addEventListener('change', game.change);
    game.change();
    game.button = document.querySelector('button');
    game.button.addEventListener('click', game.clear);
    game.clear();
  },
  getPoint: function (event) {
    return {
      x: event.clientX - game.hw,
      y: event.clientY - game.hh
    };
  },
  mousedown: function (event) {
    game.clicking = true;
  },
  mouseup: function (event) {
    game.clicking = false;
  },
  draw: function (event) {
    game.point = game.getPoint(event);
    if (game.last) {
      if (game.clicking) {
        game.ctx.fillStyle = 'rgba('+game.background+',0.01)';
        game.ctx.fillRect(0,0,innerWidth, innerHeight);
      }
      var angle1 = Math.atan2(game.last.y,game.last.x);
      var angle2 = Math.atan2(game.point.y,game.point.x);
      for (var i=0; i<game.sides; i++) {
        angle1 += game.slice;
        angle2 += game.slice;
        var p1 = game.rotate(angle1, game.last);
        var p2 = game.rotate(angle2, game.point);
        var h = Math.round((angle1*360)/game.pi2);
        var color = 'hsl('+h+',5%,50%)';
        game.ctx.lineWidth = 1;
        if (game.clicking || game.clicking !== game.release) {
          color = 'hsl('+h+',100%,75%)';
          game.ctx.lineWidth = 3;
        }
        if (game.clicking !== game.release) {
          game.circle(p2,color);
        }
        game.line(p1,p2,color);
      }
    }
    game.last = game.point;
    game.release = game.clicking;
  },
  rotate: function (a,p) {
    var d = Math.sqrt(Math.pow(p.x,2)+Math.pow(p.y,2));
    return {
      x: d * Math.cos(a),
      y: d * Math.sin(a)
    }
  },
  line: function (a,b,c) {
    game.ctx.beginPath();
    game.ctx.strokeStyle = c;
    game.ctx.moveTo(a.x + game.hw, a.y + game.hh);
    game.ctx.lineTo(b.x + game.hw, b.y + game.hh);
    game.ctx.stroke();
  },
  circle: function (p,c) {
    game.ctx.beginPath();
    game.ctx.strokeStyle = c;
    game.ctx.arc(p.x + game.hw, p.y + game.hh, 3, 0, game.pi2);
    game.ctx.stroke();
  },
  resize: function () {
    game.canvas.width = innerWidth;
    game.canvas.height = innerHeight;
    game.hw = innerWidth/2;
    game.hh = innerHeight/2;
  },
  change: function () {
    game.sides = game.input.value;
    game.slice = game.pi2 / game.sides;
  },
  clear: function () {
    game.ctx.fillStyle = 'rgba('+game.background+',1)';
    game.ctx.fillRect(0,0,innerWidth, innerHeight);
  }
};
addEventListener('load', game.load);
addEventListener('mousedown', game.mousedown);
addEventListener('mouseup', game.mouseup);
addEventListener('resize', game.resize);
addEventListener('mousemove', game.draw);
body {
  overflow: hidden; 
  cursor: crosshair;
}
div {
  position: absolute;
  margin: 0.2em;
  margin-left: calc(50% - 3em);
  background: rgba(255,255,255,0.8);
  padding: 0 0.3em;
  border-radius: 0.3em;
}
input {
  width: 3em; 
  padding: 0.2em; 
  margin: 0.3em;
}
button {
  padding: 0.2em 0.5em; 
}
<div>
  <label>Sides:</label>
  <input type="number" value="7" min="1">
  <button>X</button>
</div>

\$\endgroup\$
  • 1
    \$\begingroup\$ I think this is the wrong site for this kind of question, try stackoverflow instead. But you would probably want to use a Functional Reactive Programming library (see here for a list). \$\endgroup\$ – morbusg Aug 21 at 13:56
  • 1
    \$\begingroup\$ I really don't get it, the help link says: "What questions can I ask about here? If you have a working piece of code from your project and are looking for open-ended feedback in the following areas: Application of best practices and design pattern usage" - I posted working code according to the links definition, no bugs, not slow nor failing any tests and I'm asking for best practices in functional design pattern. Can someone explain me what I'm getting wrong? \$\endgroup\$ – rafaelcastrocouto Aug 21 at 17:14
  • \$\begingroup\$ We review code, we don't handle specific requests for refactoring code (working code or not) as we do not provide code writing services. If a reviewer decides to include an alternative approach which happens to fit your needs, you are lucky, but it should not be the goal of a review :) \$\endgroup\$ – dfhwze Aug 21 at 17:19
  • 2
    \$\begingroup\$ I will definitely accept any kind of review, but I'm way more interested in a functional approach. My original post was only please review this code, but the SO system did not allow me and asked me to write more. I see no reason for closing the question but whatever, I edited the question. \$\endgroup\$ – rafaelcastrocouto Aug 21 at 17:41
  • 1
    \$\begingroup\$ Thanks for the edits and for the reopen. It's the first time I see such an educated and positive feedback from a stack community. And sorry for my attitude, it's just that I've been through some bad stuff around here. \$\endgroup\$ – rafaelcastrocouto Aug 21 at 19:40

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.