diff --git a/js/render-fox.js b/js/render-fox.js new file mode 100644 index 0000000..d92c378 --- /dev/null +++ b/js/render-fox.js @@ -0,0 +1,134 @@ +var renderFox = function (canvas, opts) { + var width = opts.canvas.width; + var height = opts.canvas.height; + var ctx = canvas.getContext('2d'); + + ctx.fillStyle = opts.canvas.color; + ctx.fillRect(0, 0, width, height); + renderEars(ctx, opts.ears); + renderHead(ctx, opts.head); + renderEyes(ctx, opts.eyes); + renderNose(ctx, opts.nose); + renderMouth(ctx, opts.mouth); +}; + +function renderHead(ctx, opts) { + ctx.save(); + ctx.translate(ctx.canvas.width/2, ctx.canvas.height/2); + ctx.rotate(Math.PI / 4); + drawEllipseByCenter(ctx, 0, 0, opts.width, opts.height, opts.color, null, opts.kappa); + ctx.restore(); + ctx.clip(); + drawEllipseByCenter(ctx, ctx.canvas.width / 2, ctx.canvas.height, opts.maskWidth, opts.maskHeight, '#fff', '#fff', 0.5); +} + +function renderEars(ctx, opts) { + var offset = { + x: ctx.canvas.width/2, + y: ctx.canvas.height/2 + } + ctx.save(); + ctx.translate(offset.x, offset.y); + ctx.rotate(-opts.left.angle); + drawEllipseByCenter(ctx, opts.left.x - offset.x, opts.left.y - offset.y, opts.left.width, opts.left.height, opts.color, null, opts.kappa); + ctx.restore(); + + ctx.save(); + ctx.translate(offset.x, offset.y); + ctx.rotate(-opts.right.angle); + drawEllipseByCenter(ctx, opts.right.x - offset.x, opts.right.y - offset.y, opts.right.width, opts.right.height, opts.color, null, opts.kappa); + ctx.restore(); +} + +function renderEyes(ctx, opts) { + switch (opts.style) { + case "ellipse": + drawEllipseByCenter(ctx, opts.left.x, opts.left.y, opts.width, opts.height, "black", null, 0.5); + drawEllipseByCenter(ctx, opts.right.x, opts.right.y, opts.width, opts.height, "black", null, 0.5); + break; + case "smiley": + ctx.strokeStyle = "black"; + ctx.beginPath(); + ctx.moveTo(opts.left.x - opts.width, opts.left.y + opts.height); + ctx.bezierCurveTo(opts.left.x - opts.width, opts.left.y + opts.height, opts.left.x, opts.left.y, opts.left.x + opts.width, opts.left.y + opts.height); + ctx.lineWidth = 2; + ctx.stroke(); + ctx.closePath(); + + ctx.beginPath(); + ctx.moveTo(opts.right.x - opts.width, opts.right.y + opts.height); + ctx.bezierCurveTo(opts.right.x - opts.width, opts.right.y + opts.height, opts.right.x, opts.right.y, opts.right.x + opts.width, opts.right.y + opts.height); + ctx.lineWidth = 2; + ctx.stroke(); + ctx.closePath(); + break; + case "none": + break; + } +} + +function renderNose(ctx, opts) { + + ctx.strokeStyle = "black"; + ctx.beginPath(); + ctx.moveTo(opts.x - opts.width/2, opts.y - opts.height/2); + ctx.bezierCurveTo(opts.x - opts.width/2, opts.y - opts.height/2, opts.x, opts.y - opts.height, opts.x + opts.width/2, opts.y - opts.height/2); + ctx.bezierCurveTo(opts.x + opts.width/2, opts.y - opts.height/2, opts.x + opts.width/2, opts.y + opts.height/2, opts.x, opts.y + opts.height/2); + ctx.bezierCurveTo(opts.x, opts.y + opts.height/2, opts.x - opts.width/2, opts.y + opts.height/2, opts.x - opts.width/2, opts.y - opts.height/2); + ctx.fillStyle = "black"; + ctx.fill(); + ctx.stroke(); +} + +function renderMouth(ctx, opts) { + ctx.strokeStyle = "black"; + ctx.lineWidth = 2; + ctx.beginPath(); + switch (opts.style) { + case "smirk": + ctx.moveTo(opts.x - opts.width/2, opts.y - opts.height/2); + ctx.bezierCurveTo(opts.x - opts.width/2, opts.y - opts.height/2, + opts.x - opts.width/2, opts.y + opts.height/2, + opts.x + opts.width/2, opts.y + ) + break; + case "cat": + ctx.moveTo(opts.x - opts.width/2, opts.y + opts.height/2); + ctx.lineTo(opts.x, opts.y - opts.height/2); + ctx.lineTo(opts.x + opts.width/2, opts.y + opts.height/2); + break; + } + ctx.stroke(); +} + +function drawEllipseByCenter(ctx, cx, cy, w, h, color, fillColor, kappa) { + drawEllipse(ctx, cx - w/2.0, cy - h/2.0, w, h, color, fillColor, kappa); +} + +function drawEllipse(ctx, x, y, w, h, color, fillColor, kappa) { + var kappa = kappa || 0.3, + ox = (w / 2) * kappa, // control point offset horizontal + oy = (h / 2) * kappa, // control point offset vertical + xe = x + w, // x-end + ye = y + h, // y-end + xm = x + w / 2, // x-middle + ym = y + h / 2; // y-middle + + if (color) { + ctx.strokeStyle = color; + } + ctx.beginPath(); + ctx.moveTo(x, ym); + ctx.bezierCurveTo(x, ym - oy, xm - ox, y, xm, y); + ctx.bezierCurveTo(xm + ox, y, xe, ym - oy, xe, ym); + ctx.bezierCurveTo(xe, ym + oy, xm + ox, ye, xm, ye); + ctx.bezierCurveTo(xm - ox, ye, x, ym + oy, x, ym); + var fillColor = fillColor || color; + if (fillColor) { + ctx.fillStyle = fillColor; + ctx.fill(); + } + ctx.stroke(); +} + +module.exports = renderFox; diff --git a/server.js b/server.js index dc86b3b..58cf053 100644 --- a/server.js +++ b/server.js @@ -3,178 +3,15 @@ var express = require('express'); var Canvas = require('canvas'); var Fox = require('./js/fox.js'); - -var renderFox = function (canvas, opts) { - var width = opts.canvas.width; - var height = opts.canvas.height; - var ctx = canvas.getContext('2d'); - - ctx.fillStyle = opts.canvas.color; - ctx.fillRect(0, 0, width, height); - // draw ears - renderEars(ctx, opts.ears); - // draw head - renderHead(ctx, opts.head); - // draw eyes - renderEyes(ctx, opts.eyes); - // draw cheeks - // draw eyes - // draw nose - renderNose(ctx, opts.nose); - // draw mouth - renderMouth(ctx, opts.mouth); -}; - -function renderHead(ctx, opts) { - - ctx.save(); - ctx.translate(ctx.canvas.width/2, ctx.canvas.height/2); - ctx.rotate(Math.PI / 4); - drawEllipseByCenter(ctx, 0, 0, opts.width, opts.height, opts.color, null, opts.kappa); - ctx.restore(); - ctx.clip(); - drawEllipseByCenter(ctx, ctx.canvas.width / 2, ctx.canvas.height, opts.maskWidth, opts.maskHeight, '#fff', '#fff', 0.5); -} - -function renderEars(ctx, opts) { - var offset = { - x: ctx.canvas.width/2, - y: ctx.canvas.height/2 - } - ctx.save(); - ctx.translate(offset.x, offset.y); - ctx.rotate(-opts.left.angle); - drawEllipseByCenter(ctx, opts.left.x - offset.x, opts.left.y - offset.y, opts.left.width, opts.left.height, opts.color, null, opts.kappa); - ctx.restore(); - - ctx.save(); - ctx.translate(offset.x, offset.y); - ctx.rotate(-opts.right.angle); - drawEllipseByCenter(ctx, opts.right.x - offset.x, opts.right.y - offset.y, opts.right.width, opts.right.height, opts.color, null, opts.kappa); - ctx.restore(); -} - -function renderEyes(ctx, opts) { - switch (opts.style) { - case "ellipse": - drawEllipseByCenter(ctx, opts.left.x, opts.left.y, opts.width, opts.height, "black", null, 0.5); - drawEllipseByCenter(ctx, opts.right.x, opts.right.y, opts.width, opts.height, "black", null, 0.5); - break; - case "smiley": - ctx.strokeStyle = "black"; - ctx.beginPath(); - ctx.moveTo(opts.left.x - opts.width, opts.left.y + opts.height); - ctx.bezierCurveTo(opts.left.x - opts.width, opts.left.y + opts.height, opts.left.x, opts.left.y, opts.left.x + opts.width, opts.left.y + opts.height); - ctx.lineWidth = 2; - ctx.stroke(); - ctx.closePath(); - - ctx.beginPath(); - ctx.moveTo(opts.right.x - opts.width, opts.right.y + opts.height); - ctx.bezierCurveTo(opts.right.x - opts.width, opts.right.y + opts.height, opts.right.x, opts.right.y, opts.right.x + opts.width, opts.right.y + opts.height); - ctx.lineWidth = 2; - ctx.stroke(); - ctx.closePath(); - break; - case "none": - break; - } -} - -function renderNose(ctx, opts) { - - ctx.strokeStyle = "black"; - ctx.beginPath(); - ctx.moveTo(opts.x - opts.width/2, opts.y - opts.height/2); - ctx.bezierCurveTo(opts.x - opts.width/2, opts.y - opts.height/2, opts.x, opts.y - opts.height, opts.x + opts.width/2, opts.y - opts.height/2); - ctx.bezierCurveTo(opts.x + opts.width/2, opts.y - opts.height/2, opts.x + opts.width/2, opts.y + opts.height/2, opts.x, opts.y + opts.height/2); - ctx.bezierCurveTo(opts.x, opts.y + opts.height/2, opts.x - opts.width/2, opts.y + opts.height/2, opts.x - opts.width/2, opts.y - opts.height/2); - ctx.fillStyle = "black"; - ctx.fill(); - ctx.stroke(); -} - -function renderMouth(ctx, opts) { - ctx.strokeStyle = "black"; - ctx.lineWidth = 2; - ctx.beginPath(); - switch (opts.style) { - case "smirk": - ctx.moveTo(opts.x - opts.width/2, opts.y - opts.height/2); - ctx.bezierCurveTo(opts.x - opts.width/2, opts.y - opts.height/2, - opts.x - opts.width/2, opts.y + opts.height/2, - opts.x + opts.width/2, opts.y - ) - break; - case "cat": - ctx.moveTo(opts.x - opts.width/2, opts.y + opts.height/2); - ctx.lineTo(opts.x, opts.y - opts.height/2); - ctx.lineTo(opts.x + opts.width/2, opts.y + opts.height/2); - break; - } - ctx.stroke(); -} - -function drawEllipseByCenter(ctx, cx, cy, w, h, color, fillColor, kappa) { - console.log("ellipse coords", cx, cy, w, h); - drawEllipse(ctx, cx - w/2.0, cy - h/2.0, w, h, color, fillColor, kappa); -} - -function drawEllipse(ctx, x, y, w, h, color, fillColor, kappa) { - var kappa = kappa || 0.3, - ox = (w / 2) * kappa, // control point offset horizontal - oy = (h / 2) * kappa, // control point offset vertical - xe = x + w, // x-end - ye = y + h, // y-end - xm = x + w / 2, // x-middle - ym = y + h / 2; // y-middle - - if (color) { - ctx.strokeStyle = color; - } - ctx.beginPath(); - ctx.moveTo(x, ym); - ctx.bezierCurveTo(x, ym - oy, xm - ox, y, xm, y); - ctx.bezierCurveTo(xm + ox, y, xe, ym - oy, xe, ym); - ctx.bezierCurveTo(xe, ym + oy, xm + ox, ye, xm, ye); - ctx.bezierCurveTo(xm - ox, ye, x, ym + oy, x, ym); - var fillColor = fillColor || color; - if (fillColor) { - ctx.fillStyle = fillColor; - ctx.fill(); - } - //ctx.closePath(); // not used correctly, see comments (use to close off open path) - ctx.stroke(); -} - -var circle = function(c){ - var ctx= c.context || false; - var x=c.x || 500; - var y=c.y || x; - var r=c.r || 10; - var cr=ctx.canvas.width/2; - var lineWidth=c.lineWidth || 1; - ctx.beginPath(); - ctx.arc(x,y,r,0,2*Math.PI); - ctx.lineWidth=lineWidth; - - ctx.fillStyle="red"; - ctx.fill(); - ctx.stroke(); - - - return true; -}; +var renderFox = require('./js/render-fox.js'); function writeFoxesToDisk (width, height, n=10) { var fileNames = []; for (var i = 0; i < n; i++) { - var Image = Canvas.Image; var canvas = new Canvas(width, height); var ctx = canvas.getContext('2d'); var fox = Fox(width, height); renderFox(canvas, fox); - var img = new Buffer(canvas.toDataURL(), 'base64'); var fileName = "fox" + Math.floor(Math.random() * 10000) + ".png"; var filePath = __dirname + '/images/' + fileName; @@ -192,7 +29,7 @@ var app = express(); app.use(express.static(__dirname + '/images')); app.get('/', function(req, res) { - var fileNames = writeFoxesToDisk(300, 300, 30); + var fileNames = writeFoxesToDisk(200, 200, 30); var images = fileNames.map(fileName => ''); res.send(images.join('')); });