You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
105 lines
3.2 KiB
JavaScript
105 lines
3.2 KiB
JavaScript
'use strict';
|
|
|
|
const canvassed = require("canvassed");
|
|
const objectPick = require("object.pick");
|
|
|
|
const tagParser = require("./tag-parser");
|
|
const layout = require("./layout");
|
|
const fromTree = require("./text-components/from-tree");
|
|
const setTextStyles = require("./render/set-text-styles");
|
|
const measureText = require("./render/measure-text");
|
|
|
|
function getTextProperties(item) {
|
|
return objectPick(item, ["fontSize", "fontFamily", "fontStyle", "fontWeight"]);
|
|
}
|
|
|
|
module.exports = function createTextShape(options) {
|
|
let textObject = canvassed.createObject(Object.assign({
|
|
_layout: null,
|
|
_lines: null,
|
|
type: "text",
|
|
cacheBustingProperties: ["fillColor", "strokeColor", "strokeWidth", "text", "fontSize", "fontFamily", "fontStyle", "fontWeight"],
|
|
sizeBustingProperties: ["text", "fontSize", "fontFamily", "fontStyle", "fontWeight"],
|
|
fillColor: "red",
|
|
strokeColor: "red",
|
|
strokeWidth: 0,
|
|
fontFamily: "sans-serif",
|
|
fontSize: 16,
|
|
fontWeight: "normal",
|
|
lineHeight: 1.16,
|
|
onRender: function onRender(context) {
|
|
if (this.tags === true) {
|
|
let currentLineOffset = 0;
|
|
let currentComponentOffset = 0;
|
|
|
|
this._layout.forEach((line) => {
|
|
line.items.forEach((item) => {
|
|
setTextStyles(context, item.style);
|
|
context.fillText(item.text, currentComponentOffset, currentLineOffset - line.lineMinAscender);
|
|
currentComponentOffset += item.measurements.width;
|
|
});
|
|
|
|
currentLineOffset += line.lineHeight * this.lineHeight;
|
|
currentComponentOffset = 0;
|
|
});
|
|
} else {
|
|
let currentLineOffset = 0;
|
|
|
|
setTextStyles(context, getTextProperties(this));
|
|
console.log(this._lines, this.renderWidth, this.renderHeight);
|
|
this._lines.forEach((line) => {
|
|
context.fillText(line.text, 0, currentLineOffset - line.lineMinAscender);
|
|
currentLineOffset += line.measurements.height * this.lineHeight;
|
|
});
|
|
}
|
|
},
|
|
onRecalculateSize: function onRecalculateSize() {
|
|
if (this.tags === true) {
|
|
this._layout = layout(this.text, {
|
|
classes: options.classes,
|
|
defaultStyle: getTextProperties(this)
|
|
});
|
|
|
|
let combinedLineHeight = this._layout.reduce((total, line, i) => {
|
|
if (i !== this._layout.length - 1) {
|
|
return total + (line.lineHeight * this.lineHeight);
|
|
} else {
|
|
/* The last line doesn't get a lineHeight multiplier... */
|
|
return total + line.lineHeight;
|
|
}
|
|
}, 0);
|
|
|
|
return {
|
|
height: Math.ceil(combinedLineHeight),
|
|
width: Math.ceil(Math.max.apply(null, this._layout.map(line => line.lineWidth)))
|
|
}
|
|
} else {
|
|
this._lines = this.text.split("\n").map((line) => {
|
|
return {
|
|
text: line,
|
|
measurements: measureText(line, getTextProperties(this))
|
|
}
|
|
});
|
|
|
|
console.log("line", this._lines)
|
|
|
|
function sum(values) {
|
|
return values.reduce((total, value) => {
|
|
return total + value;
|
|
}, 0);
|
|
}
|
|
|
|
let multipliedLineHeights = this._lines.slice(0, -1).map(line => line.measurements.height * this.lineHeight);
|
|
let combinedLineHeight = sum(multipliedLineHeights) + this._lines[this._lines.length - 1].measurements.height;
|
|
|
|
return {
|
|
height: Math.ceil(combinedLineHeight),
|
|
width: Math.ceil(Math.max.apply(null, this._lines.map(line => line.measurements.width)))
|
|
}
|
|
}
|
|
}
|
|
}, options));
|
|
|
|
return textObject;
|
|
}
|