~jagtalon/long-exposure-art

b2005f4cd7bad88cb0894abf91777c81d18a2372 — Jag Talon 1 year, 8 months ago 4723e79
Remove dependency on `canvas-sketch`

This simplifies the project further (the only dependency is CoffeeScript) which makes the project easier to understand and run in the future.
M README.md => README.md +6 -6
@@ 6,13 6,13 @@ Draw a long exposure shot of the night sky.

## How to run:

- Set the correct node version: `nvm install`
- Install dependencies: `npm install`
- Install [`canvas-sketch-cli`](https://github.com/mattdesl/canvas-sketch-cli): `npm install -g canvas-sketch-cli`
- Run: `canvas-sketch long-exposure-art.js`
- Open `index.html`
- Save the artwork by clicking on the 'Save' button.

## If you'd like to modify the code:

- Set the correct node version: `nvm install`
- Install CoffeeScript: `npm install -g coffeescript`
- Run: `coffee -c long-exposure-art.coffee`
- Run: `canvas-sketch long-exposure-art.js`
- Install any dependencies: `npm install`
- Run: `coffee -w -c *.coffee`
- Refresh `index.html`

A index.html => index.html +40 -0
@@ 0,0 1,40 @@
<html lang="en">
	<head>
		<style>
			html, body {
				width: 100%;
				height: 100%;
			}

			body {
				padding: 1em;
			}

			canvas {
				height: 100%;
				padding-bottom: .5em;
			}
		</style>
	</head>
	<body>
		<canvas width="3600" height="5400"></canvas>

		<div>
			<button>Save</button>
		</div>

		<script>
			let canvas = document.querySelector('canvas')
			let saveButton = document.querySelector('button')
			
			saveButton.onclick = function () {
				let link = document.createElement('a')
				link.setAttribute('download', 'Art.png')
				link.setAttribute('href', canvas.toDataURL().replace("image/png", "image/octet-stream"))
				link.click()
			} 
		</script>
		<script src="./tiny-canvas.js"></script>
		<script src="./long-exposure-art.js"></script>
	</body>
</html>

M long-exposure-art.coffee => long-exposure-art.coffee +33 -40
@@ 1,51 1,44 @@
canvasSketch = require "canvas-sketch"
TinyCanvas = require "./tiny-canvas.js"
width = 3600
height = 5400

settings = 
	dimensions: [3600, 5400]
	suffix: "12x18"
canvas = document.querySelector('canvas')
context = canvas.getContext('2d')

sketch = ->
draw = new TinyCanvas(context)

	return ({context, width, height}) ->
		draw = new TinyCanvas(context)
# Helper Functions
# ----------------

		# Helper Functions
		# ----------------
# drawStarTrails
# 1. For each radius, create an arc with an angle theta.
# 2. Rotate the arc to a random angle (Math.random() * 2π)
drawStarTrails = (radius, theta) ->
	colors = ["#fdfffc", "#819EC9", "#ACE4FF"]
	color = colors[Math.floor(Math.random() * colors.length)]

		# drawStarTrails
		# 1. For each radius, create an arc with an angle theta.
		# 2. Rotate the arc to a random angle (Math.random() * 2π)
		drawStarTrails = (radius, theta) ->
			colors = ["#fdfffc", "#819EC9", "#ACE4FF"]
			color = colors[Math.floor(Math.random() * colors.length)]
	# Add a gradient to make the stars fade out a little.
	gradient = context.createLinearGradient(0, 0, width * 0.5, height * 0.5)
	gradient.addColorStop(0, color)
	gradient.addColorStop(1, "transparent")

			# Add a gradient to make the stars fade out a little.
			gradient = context.createLinearGradient(0, 0, width * 0.5, height * 0.5)
			gradient.addColorStop(0, color)
			gradient.addColorStop(1, "transparent")
	draw.circle 0, 0, radius, 0, theta
	draw.stroke gradient, (Math.random() * 10) + 1, "round"
	draw.rotate Math.random() * 2 * Math.PI

			draw.circle 0, 0, radius, 0, theta
			draw.stroke gradient, (Math.random() * 10) + 1, "round"
			draw.rotate Math.random() * 2 * Math.PI
# Drawing
# -------

		# Drawing
		# -------
# Set the night sky.
draw.rect 0, 0, width, height, "fill", "#011627"

		# Set the night sky.
		draw.rect 0, 0, width, height, "fill", "#011627"
# Set the coordinates of the rotation.
draw.translate width * 0.2, height * 0.15

		# Set the coordinates of the rotation.
		draw.translate width * 0.2, height * 0.15
		
		# Set an angle that will be used everywhere.
		# This can be any arbitrary angle, but it
		# must be the same for all star trails.
		theta = Math.PI/6
# Set an angle that will be used everywhere.
# This can be any arbitrary angle, but it
# must be the same for all star trails.
theta = Math.PI/6

		# Generate radii
		# We generate random radii then create star trails for each one.
		drawStarTrails(Math.random() * height, theta) for n in [1..9000]


canvasSketch sketch, settings
\ No newline at end of file
# Generate radii
# We generate random radii then create star trails for each one.
drawStarTrails(Math.random() * height, theta) for n in [1..9000]

M long-exposure-art.js => long-exposure-art.js +44 -50
@@ 1,60 1,54 @@
// Generated by CoffeeScript 2.5.1
(function() {
  var TinyCanvas, canvasSketch, settings, sketch;
  var canvas, context, draw, drawStarTrails, height, i, n, theta, width;

  canvasSketch = require("canvas-sketch");
  width = 3600;

  TinyCanvas = require("./tiny-canvas.js");
  height = 5400;

  settings = {
    dimensions: [3600, 5400],
    suffix: "12x18"
  };
  canvas = document.querySelector('canvas');

  context = canvas.getContext('2d');

  draw = new TinyCanvas(context);

  // Helper Functions
  // ----------------

  sketch = function() {
    return function({context, width, height}) {
      var draw, drawStarTrails, i, n, results, theta;
      draw = new TinyCanvas(context);
      // Helper Functions
      // ----------------

      // drawStarTrails
      // 1. For each radius, create an arc with an angle theta.
      // 2. Rotate the arc to a random angle (Math.random() * 2π)
      drawStarTrails = function(radius, theta) {
        var color, colors, gradient;
        colors = ["#fdfffc", "#819EC9", "#ACE4FF"];
        color = colors[Math.floor(Math.random() * colors.length)];
        // Add a gradient to make the stars fade out a little.
        gradient = context.createLinearGradient(0, 0, width * 0.5, height * 0.5);
        gradient.addColorStop(0, color);
        gradient.addColorStop(1, "transparent");
        draw.circle(0, 0, radius, 0, theta);
        draw.stroke(gradient, (Math.random() * 10) + 1, "round");
        return draw.rotate(Math.random() * 2 * Math.PI);
      };
      // Drawing
      // -------

      // Set the night sky.
      draw.rect(0, 0, width, height, "fill", "#011627");
      // Set the coordinates of the rotation.
      draw.translate(width * 0.2, height * 0.15);
      
      // Set an angle that will be used everywhere.
      // This can be any arbitrary angle, but it
      // must be the same for all star trails.
      theta = Math.PI / 6;
      results = [];
      for (n = i = 1; i <= 9000; n = ++i) {
        // Generate radii
        // We generate random radii then create star trails for each one.
        results.push(drawStarTrails(Math.random() * height, theta));
      }
      return results;
    };
  // drawStarTrails
  // 1. For each radius, create an arc with an angle theta.
  // 2. Rotate the arc to a random angle (Math.random() * 2π)
  drawStarTrails = function(radius, theta) {
    var color, colors, gradient;
    colors = ["#fdfffc", "#819EC9", "#ACE4FF"];
    color = colors[Math.floor(Math.random() * colors.length)];
    // Add a gradient to make the stars fade out a little.
    gradient = context.createLinearGradient(0, 0, width * 0.5, height * 0.5);
    gradient.addColorStop(0, color);
    gradient.addColorStop(1, "transparent");
    draw.circle(0, 0, radius, 0, theta);
    draw.stroke(gradient, (Math.random() * 10) + 1, "round");
    return draw.rotate(Math.random() * 2 * Math.PI);
  };

  canvasSketch(sketch, settings);
  // Drawing
  // -------

  // Set the night sky.
  draw.rect(0, 0, width, height, "fill", "#011627");

  // Set the coordinates of the rotation.
  draw.translate(width * 0.2, height * 0.15);

  // Set an angle that will be used everywhere.
  // This can be any arbitrary angle, but it
  // must be the same for all star trails.
  theta = Math.PI / 6;

  for (n = i = 1; i <= 9000; n = ++i) {
    // Generate radii
    // We generate random radii then create star trails for each one.
    drawStarTrails(Math.random() * height, theta);
  }

}).call(this);

M package-lock.json => package-lock.json +0 -194
@@ 4,205 4,11 @@
  "lockfileVersion": 1,
  "requires": true,
  "dependencies": {
    "call-bind": {
      "version": "1.0.2",
      "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz",
      "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==",
      "requires": {
        "function-bind": "^1.1.1",
        "get-intrinsic": "^1.0.2"
      }
    },
    "canvas-sketch": {
      "version": "0.7.4",
      "resolved": "https://registry.npmjs.org/canvas-sketch/-/canvas-sketch-0.7.4.tgz",
      "integrity": "sha512-CSmzohS6PXFctDnPmNU0r4Mj9AGXsaOZciZv5Bh1Cb0lhIDaaAXsTkQKFrY1HzhUfNWwqoXUcjwcXAIWKdCxTA==",
      "requires": {
        "convert-length": "^1.0.1",
        "dateformat": "^3.0.3",
        "deep-equal": "^1.0.1",
        "get-canvas-context": "^1.0.2",
        "is-class": "0.0.5",
        "is-dom": "^1.0.9",
        "is-promise": "^2.1.0",
        "object-assign": "^4.1.1",
        "pad-left": "^2.1.0",
        "right-now": "^1.0.0"
      }
    },
    "coffeescript": {
      "version": "2.5.1",
      "resolved": "https://registry.npmjs.org/coffeescript/-/coffeescript-2.5.1.tgz",
      "integrity": "sha512-J2jRPX0eeFh5VKyVnoLrfVFgLZtnnmp96WQSLAS8OrLm2wtQLcnikYKe1gViJKDH7vucjuhHvBKKBP3rKcD1tQ==",
      "dev": true
    },
    "convert-length": {
      "version": "1.0.1",
      "resolved": "https://registry.npmjs.org/convert-length/-/convert-length-1.0.1.tgz",
      "integrity": "sha512-w94Vge3sck6J1NHuA0du367/JTbj1zfjTapX7ixR2W+KlU4zb+NRTbou3x9nTpm5vlcXmjoaUJQpVN9pULCdxQ==",
      "requires": {
        "defined": "^1.0.0"
      }
    },
    "dateformat": {
      "version": "3.0.3",
      "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-3.0.3.tgz",
      "integrity": "sha512-jyCETtSl3VMZMWeRo7iY1FL19ges1t55hMo5yaam4Jrsm5EPL89UQkoQRyiI+Yf4k8r2ZpdngkV8hr1lIdjb3Q=="
    },
    "deep-equal": {
      "version": "1.1.1",
      "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.1.1.tgz",
      "integrity": "sha512-yd9c5AdiqVcR+JjcwUQb9DkhJc8ngNr0MahEBGvDiJw8puWab2yZlh+nkasOnZP+EGTAP6rRp2JzJhJZzvNF8g==",
      "requires": {
        "is-arguments": "^1.0.4",
        "is-date-object": "^1.0.1",
        "is-regex": "^1.0.4",
        "object-is": "^1.0.1",
        "object-keys": "^1.1.1",
        "regexp.prototype.flags": "^1.2.0"
      }
    },
    "define-properties": {
      "version": "1.1.3",
      "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz",
      "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==",
      "requires": {
        "object-keys": "^1.0.12"
      }
    },
    "defined": {
      "version": "1.0.0",
      "resolved": "https://registry.npmjs.org/defined/-/defined-1.0.0.tgz",
      "integrity": "sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM="
    },
    "function-bind": {
      "version": "1.1.1",
      "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
      "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A=="
    },
    "get-canvas-context": {
      "version": "1.0.2",
      "resolved": "https://registry.npmjs.org/get-canvas-context/-/get-canvas-context-1.0.2.tgz",
      "integrity": "sha1-1ue1C8TkyGNXzTnyJkeoS3NgHpM="
    },
    "get-intrinsic": {
      "version": "1.0.2",
      "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.0.2.tgz",
      "integrity": "sha512-aeX0vrFm21ILl3+JpFFRNe9aUvp6VFZb2/CTbgLb8j75kOhvoNYjt9d8KA/tJG4gSo8nzEDedRl0h7vDmBYRVg==",
      "requires": {
        "function-bind": "^1.1.1",
        "has": "^1.0.3",
        "has-symbols": "^1.0.1"
      }
    },
    "has": {
      "version": "1.0.3",
      "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
      "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
      "requires": {
        "function-bind": "^1.1.1"
      }
    },
    "has-symbols": {
      "version": "1.0.1",
      "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz",
      "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg=="
    },
    "is-arguments": {
      "version": "1.1.0",
      "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.0.tgz",
      "integrity": "sha512-1Ij4lOMPl/xB5kBDn7I+b2ttPMKa8szhEIrXDuXQD/oe3HJLTLhqhgGspwgyGd6MOywBUqVvYicF72lkgDnIHg==",
      "requires": {
        "call-bind": "^1.0.0"
      }
    },
    "is-class": {
      "version": "0.0.5",
      "resolved": "https://registry.npmjs.org/is-class/-/is-class-0.0.5.tgz",
      "integrity": "sha512-jOquneoRNrqbpDgh4hKicrMcGIl7jopvIJaWI+LyDVRzZrQy819qBaYSofOyUMTo/x5Jelvs8G5v/ptdySWy6A=="
    },
    "is-date-object": {
      "version": "1.0.2",
      "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.2.tgz",
      "integrity": "sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g=="
    },
    "is-dom": {
      "version": "1.1.0",
      "resolved": "https://registry.npmjs.org/is-dom/-/is-dom-1.1.0.tgz",
      "integrity": "sha512-u82f6mvhYxRPKpw8V1N0W8ce1xXwOrQtgGcxl6UCL5zBmZu3is/18K0rR7uFCnMDuAsS/3W54mGL4vsaFUQlEQ==",
      "requires": {
        "is-object": "^1.0.1",
        "is-window": "^1.0.2"
      }
    },
    "is-object": {
      "version": "1.0.2",
      "resolved": "https://registry.npmjs.org/is-object/-/is-object-1.0.2.tgz",
      "integrity": "sha512-2rRIahhZr2UWb45fIOuvZGpFtz0TyOZLf32KxBbSoUCeZR495zCKlWUKKUByk3geS2eAs7ZAABt0Y/Rx0GiQGA=="
    },
    "is-promise": {
      "version": "2.2.2",
      "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.2.2.tgz",
      "integrity": "sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ=="
    },
    "is-regex": {
      "version": "1.1.1",
      "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.1.tgz",
      "integrity": "sha512-1+QkEcxiLlB7VEyFtyBg94e08OAsvq7FUBgApTq/w2ymCLyKJgDPsybBENVtA7XCQEgEXxKPonG+mvYRxh/LIg==",
      "requires": {
        "has-symbols": "^1.0.1"
      }
    },
    "is-window": {
      "version": "1.0.2",
      "resolved": "https://registry.npmjs.org/is-window/-/is-window-1.0.2.tgz",
      "integrity": "sha1-LIlspT25feRdPDMTOmXYyfVjSA0="
    },
    "object-assign": {
      "version": "4.1.1",
      "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
      "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM="
    },
    "object-is": {
      "version": "1.1.4",
      "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.4.tgz",
      "integrity": "sha512-1ZvAZ4wlF7IyPVOcE1Omikt7UpaFlOQq0HlSti+ZvDH3UiD2brwGMwDbyV43jao2bKJ+4+WdPJHSd7kgzKYVqg==",
      "requires": {
        "call-bind": "^1.0.0",
        "define-properties": "^1.1.3"
      }
    },
    "object-keys": {
      "version": "1.1.1",
      "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz",
      "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA=="
    },
    "pad-left": {
      "version": "2.1.0",
      "resolved": "https://registry.npmjs.org/pad-left/-/pad-left-2.1.0.tgz",
      "integrity": "sha1-FuajstRKjhOMsIOMx8tAOk/J6ZQ=",
      "requires": {
        "repeat-string": "^1.5.4"
      }
    },
    "regexp.prototype.flags": {
      "version": "1.3.1",
      "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.3.1.tgz",
      "integrity": "sha512-JiBdRBq91WlY7uRJ0ds7R+dU02i6LKi8r3BuQhNXn+kmeLN+EfHhfjqMRis1zJxnlu88hq/4dx0P2OP3APRTOA==",
      "requires": {
        "call-bind": "^1.0.2",
        "define-properties": "^1.1.3"
      }
    },
    "repeat-string": {
      "version": "1.6.1",
      "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz",
      "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc="
    },
    "right-now": {
      "version": "1.0.0",
      "resolved": "https://registry.npmjs.org/right-now/-/right-now-1.0.0.tgz",
      "integrity": "sha1-bolgne69fc2vja7Mmuo5z1haCRg="
    }
  }
}

M package.json => package.json +1 -3
@@ 9,9 9,7 @@
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
    "canvas-sketch": "^0.7.4"
  },
  "dependencies": {},
  "devDependencies": {
    "coffeescript": "^2.5.1"
  }

M tiny-canvas.coffee => tiny-canvas.coffee +3 -1
@@ 1,4 1,4 @@
module.exports = class TinyCanvas
class TinyCanvas
	constructor: (@context) ->

	circle: (x, y, radius, startAngle = 0, endAngle = Math.PI * 2) ->


@@ 24,3 24,5 @@ module.exports = class TinyCanvas

	translate: (x, y) ->
		@context.translate x, y

window.TinyCanvas = TinyCanvas

M tiny-canvas.js => tiny-canvas.js +3 -1
@@ 2,7 2,7 @@
(function() {
  var TinyCanvas;

  module.exports = TinyCanvas = class TinyCanvas {
  TinyCanvas = class TinyCanvas {
    constructor(context) {
      this.context = context;
    }


@@ 39,4 39,6 @@

  };

  window.TinyCanvas = TinyCanvas;

}).call(this);