Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

multiline-canvas-text

Package Overview
Dependencies
Maintainers
1
Versions
3
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

multiline-canvas-text - npm Package Compare versions

Comparing version 1.0.3 to 2.0.0

30

index.d.ts

@@ -11,5 +11,31 @@ export interface IFont {

canvas: HTMLCanvasElement;
lastCharacterPosition: IPoint;
cursor: IPoint;
lines: string[];
}
export declare function drawText(text: string, width: number, fontName: string, fontSize: number, lineSpacing?: number, color?: string): IDrawTextResult;
export declare const TextAlign: {
CENTER: string;
LEFT: string;
RIGHT: string;
};
/**
* Creates a canvas of the given width and renders the string into it
* @param {string} text
* @param {number} width
* @param {string} fontName
* @param {number} fontSize
* @param {number} lineSpacing
* @param {string} color
* @param {boolean} strokeText
* @param {string} align
* @returns {IDrawTextResult}
*/
export declare function drawText(text: string, width: number, fontName: string, fontSize: number, lineSpacing?: number, color?: string, strokeText?: boolean, align?: string): IDrawTextResult;
/**
* Breaks up a string into lines that fit within the supplied width.
* @param {string} text
* @param {number} width
* @param {string} fontName
* @param {number} fontSize
* @returns {string[]}
*/
export declare function fitText(text: string, width: number, fontName: string, fontSize: number): string[];

@@ -5,5 +5,22 @@ "use strict";

exports.drawText = drawText;
exports.fitText = fitText;
exports.TextAlign = void 0;
var _trimCanvas = require("./trimCanvas");
var TextAlign = {
CENTER: 'center',
LEFT: 'left',
RIGHT: 'right'
};
/**
* For a given string, returns a new string in which all the separate words (characters divided by a space) fit in the given width. Can add spaces into original words if they are too long.
* @param {string} text
* @param {number} availableWidth
* @param {IFont} font
* @returns {string}
*/
exports.TextAlign = TextAlign;
function splitIntoFittingWords(text, availableWidth, font) {

@@ -37,3 +54,12 @@ var splitResults = [];

}
/**
* Groups a given string into fitting parts. What a part is is defined by the character to split the original string on.
* @param {string} text
* @param {string} splitOn
* @param {number} availableWidth
* @param {IFont} font
* @returns {string[]}
*/
function groupText(text, splitOn, availableWidth, font) {

@@ -61,4 +87,17 @@ return text.split(splitOn).reduce(function (resultingLines, currentItem) {

}
/**
* Creates a canvas of the given width and renders the string into it
* @param {string} text
* @param {number} width
* @param {string} fontName
* @param {number} fontSize
* @param {number} lineSpacing
* @param {string} color
* @param {boolean} strokeText
* @param {string} align
* @returns {IDrawTextResult}
*/
function drawText(text, width, fontName, fontSize, lineSpacing, color) {
function drawText(text, width, fontName, fontSize, lineSpacing, color, strokeText, align) {
if (lineSpacing === void 0) {

@@ -72,25 +111,61 @@ lineSpacing = 0;

// for now, just add spacing to fix fonts falling ut of view sometimes (at the bottom specifically)
if (strokeText === void 0) {
strokeText = false;
}
if (align === void 0) {
align = 'center';
}
var alignModes = [TextAlign.LEFT, TextAlign.CENTER, TextAlign.RIGHT];
if (alignModes.indexOf(align) === -1) {
throw new Error("Invalid alignMode (possible options: " + alignModes.join(',') + ")");
} // for now, just add spacing to fix fonts falling ut of view sometimes (at the bottom specifically)
// padding will be removed by trimming canvas at the end
var padding = {
x: 10,
y: 15
};
var font = {
size: fontSize,
name: fontName
};
var lines = fitText(text, width, font); // create and init canvas
x: 20,
y: fontSize * 2
}; // todo this needs a better fix
var font = createFont(fontName, fontSize);
var lines = fitText(text, width - 2 * padding.x, fontName, fontSize); // create and init canvas
var canvas = document.createElement('canvas');
canvas.width = width + 2 * padding.x;
canvas.width = width; // + 2 * padding.x;
canvas.height = lines.length * fontSize + (lines.length - 1) * lineSpacing + 2 * padding.y;
var context = canvas.getContext('2d');
context.font = getCanvasFontProperty(font);
context.textAlign = 'center';
context.textBaseline = 'top'; // draw lines
context.textAlign = align;
context.textBaseline = 'top';
context.fillStyle = color;
context.strokeStyle = color; // draw lines
var centerX = canvas.width * 0.5;
var baseX;
switch (align) {
case TextAlign.RIGHT:
{
baseX = canvas.width - padding.x;
break;
}
case TextAlign.LEFT:
{
baseX = padding.x;
break;
}
case TextAlign.CENTER:
{
baseX = canvas.width * 0.5;
break;
}
}
var yOffset = 0;
var lastCharacterPosition = {
var cursor = {
x: canvas.width * 0.5,

@@ -100,5 +175,9 @@ y: yOffset

lines.forEach(function (line) {
context.fillStyle = color;
context.fillText(line, centerX, yOffset);
lastCharacterPosition = {
if (strokeText) {
context.strokeText(line, baseX, yOffset);
} else {
context.fillText(line, baseX, yOffset);
}
cursor = {
x: canvas.width * 0.5 + 0.5 * getTextWidth(line, font).width,

@@ -110,15 +189,45 @@ y: yOffset

return {
lastCharacterPosition: lastCharacterPosition,
lines: [],
lines: lines,
cursor: cursor,
canvas: (0, _trimCanvas.trimCanvas)(canvas)
};
}
/**
* Breaks up a string into lines that fit within the supplied width.
* @param {string} text
* @param {number} width
* @param {string} fontName
* @param {number} fontSize
* @returns {string[]}
*/
function fitText(text, width, font) {
function fitText(text, width, fontName, fontSize) {
var font = createFont(fontName, fontSize);
var fittingWords = splitIntoFittingWords(text, width, font);
return groupText(fittingWords, ' ', width, font);
}
/**
* Formats fontName and fontSize into a css string for canvas.
* @param {IFont} font
* @returns {string}
*/
function getCanvasFontProperty(font) {
return font.size + "px " + font.name;
}
}
/**
* Create IFont object
* @param {string} name
* @param {number} size
* @returns {IFont}
*/
var createFont = function createFont(name, size) {
return {
size: size,
name: name
};
};

4

package.json
{
"name": "multiline-canvas-text",
"version": "1.0.3",
"description": "Render multiline text to canvas",
"version": "2.0.0",
"description": "Render a string to canvas, breaking it up into multiple lines to fit the given width.",
"main": "./index.js",

@@ -6,0 +6,0 @@ "types": "./index.d.ts",

# multiline-canvas-text
Render a string to canvas, breaking it up into multiple lines to fit the given width.
## install
```sh
npm install multiline-canvas-text
```
## demo
Check out the [interactive example](https://petervdn.github.io/multiline-canvas-text/example/).
## usage
```javascript
import { drawText } from "multiline-canvas-text";
const text = 'The quick brown fox jumps over the lazy dog';
const width = 40; // width in pixels to fit the text
const font = 'Arial'; // font should be available in the page
const fontSize = 20; // in pixels
const lineSpacing = 1; // vertical spacing between the lines
const color = 'white'; // can be any valid css color string: 'black', #FFF', 'rgba(0,0,0,0.5)', etc
const strokeText = false; // true results in calling strokeText instead of fillText
const result = drawText(text, width, font, fontSize, lineSpacing, color, strokeText);
element.appendChild(result.canvas);
```
The result object contains 3 properties:
* `canvas`: The generated canvas element with the rendered text. This canvas has the width that was given to the `drawText` method, but can obviously vary in height.
* `lines`: An array that shows how the string was broken up into multiple lines, for example: `["The quick brown", "fox jumps over", "the lazy dog"]`
* `cursor`: if you are replicating an interactive textfield in canvas, you may want to add a blinking cursor to increase the user experience. The `cursor` property holds `x` and `y` values for where to draw it. **This value is not correct at the moment!**

@@ -8,14 +8,6 @@ "use strict";

function trimCanvas(canvas) {
var ctx = canvas.getContext('2d'); // create a temporary canvas in which we will draw back the trimmed text
var copy = document.createElement('canvas').getContext('2d'); // Use the Canvas Image Data API, in order to get all the
// underlying pixels data of that canvas. This will basically
// return an array (Uint8ClampedArray) containing the data in the
// RGBA order. Every 4 items represent one pixel.
var pixels = ctx.getImageData(0, 0, canvas.width, canvas.height); // total pixels
var l = pixels.data.length; // main loop counter and pixels coordinates
var x;
var ctx = canvas.getContext('2d');
var copy = document.createElement('canvas').getContext('2d');
var pixels = ctx.getImageData(0, 0, canvas.width, canvas.height);
var l = pixels.data.length;
var y; // an object that will store the area that isn't transparent

@@ -33,4 +25,3 @@

if (pixels.data[i + 3] !== 0) {
// find it's coordinates
x = i / 4 % canvas.width;
// find its coordinates
y = ~~(i / 4 / canvas.width); // store/update those coordinates

@@ -41,16 +32,15 @@ // inside our bounding box Object

bound.top = y;
}
} // if (bound.left === null) {
// bound.left = x;
// } else if (x < bound.left) {
// bound.left = x;
// }
//
// if (bound.right === null) {
// bound.right = x;
// } else if (bound.right < x) {
// bound.right = x;
// }
if (bound.left === null) {
bound.left = x;
} else if (x < bound.left) {
bound.left = x;
}
if (bound.right === null) {
bound.right = x;
} else if (bound.right < x) {
bound.right = x;
}
if (bound.bottom === null) {

@@ -67,6 +57,7 @@ bound.bottom = y;

var trimHeight = bound.bottom - bound.top;
var trimWidth = bound.right - bound.left; // get the zone (trimWidth x trimHeight) as an ImageData
var trimWidth = canvas.width; // do not trim horizontally
// get the zone (trimWidth x trimHeight) as an ImageData
// (Uint8ClampedArray of pixels) from our canvas
var trimmed = ctx.getImageData(bound.left, bound.top, trimWidth, trimHeight); // Draw back the ImageData into the canvas
var trimmed = ctx.getImageData(0, bound.top, trimWidth, trimHeight); // Draw back the ImageData into the canvas

@@ -73,0 +64,0 @@ copy.canvas.width = trimWidth;

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc