diff --git a/src/calculate-origin-offsets.js b/src/calculate-origin-offsets.js new file mode 100644 index 0000000..a79c276 --- /dev/null +++ b/src/calculate-origin-offsets.js @@ -0,0 +1,53 @@ +'use strict'; + +const defaultValue = require("default-value"); + +const validateSync = require("./validate-sync"); + +let originAliases = { + top: 0, + left: 0, + center: "50%", + bottom: "100%", + right: "100%" +} + +function tryAlias(value) { + if (originAliases[value] != null) { + return originAliases[value]; + } else { + return value; + } +} + +function calculateOffset(value, origin) { + if (typeof origin === "number") { + return -origin; + } else { + let match = /^(-?[0-9]+(?:\.[0-9]+)?)%$/.exec(origin); + + if (match == null) { + throw new Error(`Encountered invalid origin value: ${origin}`); + } else { + let percentage = match[1]; + return -(value * (parseFloat(percentage) / 100)); + } + } +} + +module.exports = function calculateOriginOffsets(options) { + validateSync(options, { + width: "required", + height: "required", + originX: "required", + originY: "required" + }); + + let originX = tryAlias(options.originX); + let originY = tryAlias(options.originY); + + return { + x: calculateOffset(options.width, originX), + y: calculateOffset(options.height, originY) + } +} diff --git a/src/create-object.js b/src/create-object.js index 891ebe7..58782e5 100644 --- a/src/create-object.js +++ b/src/create-object.js @@ -4,6 +4,7 @@ const createEventEmitter = require("create-event-emitter"); const defaultValue = require("default-value"); const validateSync = require("./validate-sync"); +const calculateOriginOffsets = require("./calculate-origin-offsets"); module.exports = function createObject(options) { validateSync(options, { @@ -18,16 +19,29 @@ module.exports = function createObject(options) { flipY: false, scaleX: 1, scaleY: 1, + originX: "left", + originY: "top", opacity: 1, + bustCache: function bustCache() { + this.isCached = false; + }, set: function setProperties(properties) { - Object.assign(this, properties); + let transformedProperties; + + if (this.onSet != null) { + transformedProperties = this.onSet(properties); + } else { + transformedProperties = properties; + } + + Object.assign(this, transformedProperties); - if (Object.keys(properties).some(property => this.sizeBustingProperties.includes(property))) { + if (Object.keys(transformedProperties).some(property => this.sizeBustingProperties.includes(property))) { this.emit("bustedSize"); this.recalculateSize(); } - if (Object.keys(properties).some(property => this.cacheBustingProperties.includes(property))) { + if (Object.keys(transformedProperties).some(property => this.cacheBustingProperties.includes(property))) { this.emit("bustedCache"); this.isCached = false; } @@ -35,12 +49,19 @@ module.exports = function createObject(options) { render: function renderObject(context, options = {}) { if (this.isCached === false) { this.renderToCache(this.cacheCanvas); - // TODO: render cached canvas + this.isCached = true; } this.emit("rendering"); - context.drawImage(this.cacheCanvas, defaultValue(options.x, 0), defaultValue(options.y, 0)); + let offset = calculateOriginOffsets({ + width: this.renderWidth, + height: this.renderHeight, + originX: this.originX, + originY: this.originY + }); + + context.drawImage(this.cacheCanvas, defaultValue(options.x, 0) + offset.x, defaultValue(options.y, 0) + offset.y); this.emit("rendered"); }, @@ -51,6 +72,8 @@ module.exports = function createObject(options) { this.renderWidth = newSize.width * this.scaleX; this.renderHeight = newSize.height * this.scaleY; + this.renderOffsetX = defaultValue(newSize.offsetX, 0) * this.scaleX; + this.renderOffsetY = defaultValue(newSize.offsetY, 0) * this.scaleY; this.cacheCanvas.width = this.renderWidth; this.cacheCanvas.height = this.renderHeight; @@ -64,6 +87,8 @@ module.exports = function createObject(options) { alpha: true }); + context.clearRect(0, 0, targetCanvas.width, targetCanvas.height); + context.save(); this.emit("renderingToCache");