Skip to content

Commit

Permalink
Add reflection option to library
Browse files Browse the repository at this point in the history
  • Loading branch information
daveknights committed Oct 20, 2023
1 parent ed8854f commit a50a002
Showing 1 changed file with 68 additions and 25 deletions.
93 changes: 68 additions & 25 deletions cre8bit.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ export default class Cre8bit {
#size = 5;
#flip = false;
#outlineWidth = 0;
#reflection = false;

#characters = {
pacman: {
Expand Down Expand Up @@ -175,39 +176,37 @@ export default class Cre8bit {
return document.createElementNS(name, tag);
}

#setAttr(elem, values) {
for (const [v1, v2] of values) {
elem.setAttribute(v1, v2);
}
}

#makeSVG(svg, charPath) {
const newGroup = this.#createSvgElement(this.#svgns, 'g');
const pathPoints = this.#useAnimatePoints === false ? charPath.points : charPath.animatePoints;
const strokeW = this.#outlineWidth;
const stroke2W = strokeW * 2;
let newPath = null;

newGroup.setAttribute('fill', this.#colour);
if(this.#outlineWidth === 0.5) {
newGroup.setAttribute('stroke', 'black');
newGroup.setAttribute('stroke-width', this.#outlineWidth);
this.#setAttr(newGroup, [['fill', this.#colour]]);
if(strokeW === 0.5) {
this.#setAttr(newGroup, [['stroke', 'black'],['stroke-width', strokeW]]);
}

if (charPath.mask) {
const newDefs = this.#createSvgElement(this.#svgns, 'defs');
const newMask = this.#createSvgElement(this.#svgns, 'mask');
const wholeMask = this.#createSvgElement(this.#svgns, 'rect');

newMask.setAttribute('id', `${this.#id}-mask`);

wholeMask.setAttribute('x', 0);
wholeMask.setAttribute('y', 0);
wholeMask.setAttribute('width', (this.#size * charPath.columns) + (this.#outlineWidth * 2));
wholeMask.setAttribute('height', (this.#size * charPath.rows) + (this.#outlineWidth * 2));
wholeMask.setAttribute('fill', 'white');
this.#setAttr(newMask, [['id', `${this.#id}-mask`]]);
this.#setAttr(wholeMask, [['x', 0],['y', 0],['width', (this.#size * charPath.columns) + stroke2W],['height', (this.#size * charPath.rows) + stroke2W],['fill', 'white']]);

newMask.appendChild(wholeMask);

for (const [x,y] of charPath.mask.values()) {
const newBlock = this.#createSvgElement(this.#svgns, 'rect');
newBlock.setAttribute('x', (x * this.#size) + this.#outlineWidth);
newBlock.setAttribute('y', (y * this.#size) + this.#outlineWidth);
newBlock.setAttribute('width', this.#size);
newBlock.setAttribute('height', this.#size);
newBlock.setAttribute('fill', 'black');
this.#setAttr(newBlock, [['x', (x * this.#size) + strokeW],['y', (y * this.#size) + strokeW],['width', this.#size],['height', this.#size],['fill', 'black']]);

newMask.appendChild(newBlock);
}
Expand All @@ -219,33 +218,71 @@ export default class Cre8bit {

for (const points of pathPoints) {
newPath = this.#createSvgElement(this.#svgns, 'path');
newPath.setAttribute('d', `M ${(points[0][0] * this.#size) + this.#outlineWidth} ${(points[0][1] * this.#size) + this.#outlineWidth} ${this.#createPath(points)}`);
this.#setAttr(newPath, [['d', `M ${(points[0][0] * this.#size) + strokeW} ${(points[0][1] * this.#size) + strokeW} ${this.#createPath(points)}`]]);
newGroup.appendChild(newPath);
}

charPath.mask && newPath.setAttribute('mask', `url(#${this.#id}-mask)`);
charPath.mask && this.#setAttr(newPath, [['mask', `url(#${this.#id}-mask)`]]);

if (charPath.extraPoints) {
for (const [colour, pointsArrays] of Object.entries(charPath.extraPoints)) {
for (const points of pointsArrays) {
const extraPath = this.#createSvgElement(this.#svgns, 'path');
extraPath.setAttribute('d', `M ${(points[0][0] * this.#size) + this.#outlineWidth} ${(points[0][1] * this.#size) + this.#outlineWidth} ${this.#createPath(points)}`);
extraPath.setAttribute('fill', colour);
this.#setAttr(extraPath, [['d', `M ${(points[0][0] * this.#size) + strokeW} ${(points[0][1] * this.#size) + strokeW} ${this.#createPath(points)}`],['fill', colour]]);

newGroup.appendChild(extraPath);
}
}
}

if (this.#reflection) {
const charCopy = newGroup.cloneNode(true);
const rNewDefs = this.#createSvgElement(this.#svgns, 'defs');
const rNewMask = this.#createSvgElement(this.#svgns, 'mask');
const rRect = this.#createSvgElement(this.#svgns, 'rect');
const rlinearGrad = this.#createSvgElement(this.#svgns, 'linearGradient');
const rStopStart = this.#createSvgElement(this.#svgns, 'stop');
const rStopEnd = this.#createSvgElement(this.#svgns, 'stop');

this.#setAttr(rNewMask, [['id', `${this.#id}-ref-mask`]]);
this.#setAttr(rRect, [['x', 0],['y', 0],['width', (this.#size * charPath.columns) + stroke2W],['height', (this.#size * charPath.rows) + stroke2W],['fill', `url(#${this.#id}-grad-mask)`]]);
this.#setAttr(rlinearGrad, [['id', `${this.#id}-grad-mask`],['x1', '0'],['x2', '0'],['y1', '0'],['y2', '1']]);
this.#setAttr(rStopStart, [['offset', '0'],['stop-color', 'white']]);
this.#setAttr(rStopEnd, [['offset', '1'],['stop-color', 'white']]);

let translateVal = `0,-${((this.#characterPath().rows * this.#size) + stroke2W) * 2}`;
let scaleVal = '1,-1';
let startVal = '0';
let endVal = '0.3';

if (this.#flip) {
translateVal = `-${((this.#characterPath().columns * this.#size) + stroke2W)},-${((this.#characterPath().rows * this.#size) + stroke2W) * 2}`;
scaleVal = '-1,-1';
}

this.#setAttr(rStopStart, [['stop-opacity', startVal]]);
this.#setAttr(rStopEnd, [['stop-opacity', endVal]]);
this.#setAttr(charCopy, [['transform', `scale(${scaleVal}) translate(${translateVal})`],['mask', `url(#${this.#id}-ref-mask)`]]);

rNewMask.appendChild(rRect);
rlinearGrad.appendChild(rStopStart);
rlinearGrad.appendChild(rStopEnd);
rNewDefs.appendChild(rlinearGrad);
rNewDefs.appendChild(rNewMask);
svg.appendChild(rNewDefs);
svg.appendChild(charCopy);
}

return svg;
}

#editSVG() {
const charPath = this.#characterPath();
const svgEdit = document.getElementById(this.#id);
const editMultiplyer = this.#reflection ? 2 : 1;
svgEdit.innerHTML = '';
svgEdit.setAttributeNS(null, 'width', `${(charPath.columns * this.#size) + (this.#outlineWidth * 2)}`);
svgEdit.setAttributeNS(null, 'height', `${(charPath.rows * this.#size) + (this.#outlineWidth * 2)}`);
svgEdit.setAttributeNS(null, 'height', `${((charPath.rows * this.#size) + (this.#outlineWidth * 2)) * editMultiplyer}`);

this.#makeSVG(svgEdit, charPath);

Expand Down Expand Up @@ -309,19 +346,23 @@ export default class Cre8bit {
*/
setFlip(shouldFlip) {
if (shouldFlip) {
document.getElementById(this.#id).querySelector('g').setAttribute('transform', `scale(-1, 1) translate(-${(this.#characterPath().columns * this.#size) + (this.#outlineWidth * 2)}, 0)`);
this.#setAttr(document.getElementById(this.#id).querySelector('g'), [['transform', `scale(-1, 1) translate(-${(this.#characterPath().columns * this.#size) + (this.#outlineWidth * 2)}, 0)`]]);
} else {
document.getElementById(this.#id).querySelector('g').removeAttribute('transform');
}

if (this.#reflection) {
this.#setAttr(document.getElementById(this.#id).querySelector('g:last-of-type'), [['transform', `scale(-1,-1) translate(-${(this.#characterPath().columns * this.#size) + (this.#outlineWidth * 2)}, -${((this.#characterPath().rows * this.#size) + (this.#outlineWidth * 2)) * 2})`]]);
}

this.#flip = shouldFlip;

return this;
}

/**
* @param {string} character - character
* @param {object} [options] - Optional string colour, number size, boolean flip, boolean animate, string parentClass, string wrapperClass, boolean outline
* @param {object} [options] - Optional string colour, number size, boolean flip, boolean animate, boolean relection, string parentClass, string wrapperClass, boolean outline
*/
create(character, options) {
this.#characterName = character.toLowerCase();
Expand All @@ -336,14 +377,16 @@ export default class Cre8bit {
svgElem.classList.add('cre8bit', this.#characterName.replace(' ', '-'));

if (options) {
options.flip && (this.#flip = options.flip);
options.parentClass && (this.#parentClass = options.parentClass);
options.colour && this.setColour(options.colour, true);
options.size && this.setSize(options.size, true);
options.outline && (this.#outlineWidth = 0.5);
options.reflection && (this.#reflection = true);
}

const multiplyer = options && options.reflection ? 2 : 1;
svgElem.setAttributeNS(null, 'width', `${(newCharPath.columns * this.#size) + (this.#outlineWidth * 2)}`);
svgElem.setAttributeNS(null, 'height', `${(newCharPath.rows * this.#size) + (this.#outlineWidth * 2)}`);
svgElem.setAttributeNS(null, 'height', `${((newCharPath.rows * this.#size) + (this.#outlineWidth * 2)) * multiplyer}`);

shape = this.#makeSVG(svgElem, newCharPath);

Expand Down

0 comments on commit a50a002

Please sign in to comment.