mirror of
https://github.com/Doodle3D/Doodle3D-Core.git
synced 2024-12-22 11:03:48 +01:00
Add constants
This commit is contained in:
parent
393760b9d8
commit
c926984bb6
10
package-lock.json
generated
10
package-lock.json
generated
@ -22,6 +22,11 @@
|
||||
"resolved": "https://registry.npmjs.org/@doodle3d/clipper-lib/-/clipper-lib-6.4.2-b.tgz",
|
||||
"integrity": "sha512-glELSijsD9b+/0d9iOdasBwqH3s+xPxD59tJ7aXkBx7klugygGOMXn7PB05AdhVyA1OYMj7GUCegaQa7nvLtmQ=="
|
||||
},
|
||||
"@doodle3d/potrace-js": {
|
||||
"version": "0.0.6",
|
||||
"resolved": "https://registry.npmjs.org/@doodle3d/potrace-js/-/potrace-js-0.0.6.tgz",
|
||||
"integrity": "sha512-w1+sG3ClsSaQwo3ks5wl6QLe4aWEHBe8QePq0IeAcj+lypqo770sUcWVfEZWUFBumAhSlCJg3GRc8MsycHy8LA=="
|
||||
},
|
||||
"@doodle3d/threejs-export-obj": {
|
||||
"version": "0.0.4",
|
||||
"resolved": "https://registry.npmjs.org/@doodle3d/threejs-export-obj/-/threejs-export-obj-0.0.4.tgz",
|
||||
@ -958,6 +963,11 @@
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"bowser": {
|
||||
"version": "1.8.1",
|
||||
"resolved": "https://registry.npmjs.org/bowser/-/bowser-1.8.1.tgz",
|
||||
"integrity": "sha512-NMPaR8ILtdLSWzxQtEs16XbxMcY8ohWGQ5V+TZSJS3fNUt/PBAGkF6YWO9B/4qWE23bK3o0moQKq8UyFEosYkA=="
|
||||
},
|
||||
"brace-expansion": {
|
||||
"version": "1.1.8",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.8.tgz",
|
||||
|
@ -14,9 +14,11 @@
|
||||
"dependencies": {
|
||||
"@doodle3d/cal": "0.0.8",
|
||||
"@doodle3d/clipper-js": "^1.0.7",
|
||||
"@doodle3d/potrace-js": "0.0.6",
|
||||
"@doodle3d/threejs-export-obj": "0.0.4",
|
||||
"@doodle3d/threejs-export-stl": "0.0.3",
|
||||
"babel-plugin-inline-import": "^2.0.6",
|
||||
"bowser": "^1.8.1",
|
||||
"imports-loader": "^0.7.1",
|
||||
"memoizee": "^0.3.9",
|
||||
"proptypes": "^1.1.0",
|
||||
|
88
src/constants/contextTools.js
Normal file
88
src/constants/contextTools.js
Normal file
@ -0,0 +1,88 @@
|
||||
export const DUPLICATE = 'duplicate-tool';
|
||||
export const DELETE = 'delete-tool';
|
||||
export const COLOR_PICKER = 'color-picker-tool';
|
||||
export const ERASER_SIZE = 'eraser-size-tool';
|
||||
export const BRUSH_SIZE = 'brush-size-tool';
|
||||
export const FILL_TOGGLE = 'fill-toggle-tool';
|
||||
export const ALIGN = 'align-tool';
|
||||
export const ADVANCED = 'advanced-tool';
|
||||
|
||||
export const LIGHT_BLUE = 'color-light-blue';
|
||||
export const LIGHT_GREEN = 'color-light-green';
|
||||
export const LIGHT_PINK = 'color-light-pink';
|
||||
export const LIGHT_YELLOW = 'color-light-yellow';
|
||||
export const BLUE = 'color-blue';
|
||||
export const GREEN = 'color-green';
|
||||
export const PINK = 'color-pink';
|
||||
export const YELLOW = 'color-yellow';
|
||||
export const DARK_BLUE = 'color-dark-blue';
|
||||
export const DARK_GREEN = 'color-dark-green';
|
||||
export const DARK_PINK = 'color-dark-pink';
|
||||
export const DARK_YELLOW = 'color-dark-yellow';
|
||||
|
||||
export const COLORS = [
|
||||
LIGHT_BLUE,
|
||||
LIGHT_GREEN,
|
||||
LIGHT_PINK,
|
||||
LIGHT_YELLOW,
|
||||
BLUE,
|
||||
GREEN,
|
||||
PINK,
|
||||
YELLOW,
|
||||
DARK_BLUE,
|
||||
DARK_GREEN,
|
||||
DARK_PINK,
|
||||
DARK_YELLOW
|
||||
];
|
||||
|
||||
export const ERASER_SIZE_SMALL = 'eraser-size-small';
|
||||
export const ERASER_SIZE_MEDIUM = 'eraser-size-medium';
|
||||
export const ERASER_SIZE_LARGE = 'eraser-size-large';
|
||||
|
||||
export const ERASER_SIZE_TOOLS = [
|
||||
ERASER_SIZE_SMALL,
|
||||
ERASER_SIZE_MEDIUM,
|
||||
ERASER_SIZE_LARGE
|
||||
];
|
||||
|
||||
export const BRUSH_SIZE_SMALL = 'brush-size-small';
|
||||
export const BRUSH_SIZE_MEDIUM = 'brush-size-medium';
|
||||
export const BRUSH_SIZE_LARGE = 'brush-size-large';
|
||||
|
||||
export const BRUSH_SIZE_TOOLS = [
|
||||
BRUSH_SIZE_SMALL,
|
||||
BRUSH_SIZE_MEDIUM,
|
||||
BRUSH_SIZE_LARGE
|
||||
];
|
||||
|
||||
export const FILL_TOGGLE_FILL = 'fill-toggle-fill';
|
||||
export const FILL_TOGGLE_OUTLINE = 'fill-toggle-outline';
|
||||
|
||||
export const FILL_TOGGLE_TOOLS = [
|
||||
FILL_TOGGLE_FILL,
|
||||
FILL_TOGGLE_OUTLINE
|
||||
];
|
||||
|
||||
export const ALIGN_LEFT = 'align-left';
|
||||
export const ALIGN_HORIZONTAL = 'align-horizontal';
|
||||
export const ALIGN_RIGHT = 'align-right';
|
||||
export const ALIGN_TOP = 'align-top';
|
||||
export const ALIGN_VERTICAL = 'align-vertical';
|
||||
export const ALIGN_BOTTOM = 'align-bottom';
|
||||
|
||||
export const ALIGN_TOOLS = [
|
||||
ALIGN_LEFT,
|
||||
ALIGN_HORIZONTAL,
|
||||
ALIGN_RIGHT,
|
||||
ALIGN_TOP,
|
||||
ALIGN_VERTICAL,
|
||||
ALIGN_BOTTOM
|
||||
];
|
||||
|
||||
export const UNION = 'union-tool';
|
||||
export const INTERSECT = 'intersect-tool';
|
||||
|
||||
export const ADVANCED_TOOLS = [
|
||||
UNION,
|
||||
INTERSECT
|
||||
];
|
43
src/constants/d2Constants.js
Normal file
43
src/constants/d2Constants.js
Normal file
@ -0,0 +1,43 @@
|
||||
import * as contextTools from './contextTools.js';
|
||||
|
||||
export const LINE_WIDTH = 3;
|
||||
export const LINE_COLLISION_MARGIN = 4;
|
||||
export const MIN_ZOOM = 0.5;
|
||||
export const MAX_ZOOM = 10;
|
||||
export const CANVAS_SIZE = 100;
|
||||
export const GRID_SIZE = 10;
|
||||
export const IMAGE_GUIDE_TRANSPARENCY = 0.7;
|
||||
export const FILL_TRANSPARENCY = 0.9;
|
||||
export const LINE_TRANSPARENCY = 1.0;
|
||||
export const DESELECT_TRANSPARENCY = 0.2;
|
||||
// default flood fill tolereance of image trace
|
||||
export const DEFAULT_TRACE_TOLERANCE = 20;
|
||||
// initial scale of image inside workspace
|
||||
export const INITIAL_IMAGE_SCALE = 0.8;
|
||||
// big images can lead to performance penalties, images bigger then MAX_IMAGE_SIZE get scaled down
|
||||
export const MAX_IMAGE_SIZE = 1000;
|
||||
// TODO we want to use different snapping distances for mouse and for touch events
|
||||
export const SNAPPING_DISTANCE = 7.0;
|
||||
export const MAX_TRACE_TOLERANCE = 256;
|
||||
export const SELECTION_VIEW_MIN_SCALE = 50;
|
||||
export const SELECTION_VIEW_MIN_AXIS_SCALE = 80;
|
||||
export const POTRACE_OPTIONS = {
|
||||
turnpolicy: 'black',
|
||||
turdsize: 5.0,
|
||||
optcurve: false,
|
||||
alphamax: 0.5,
|
||||
opttolerance: 0.2
|
||||
};
|
||||
export const ERASER_SIZES = {
|
||||
[contextTools.ERASER_SIZE_SMALL]: 10,
|
||||
[contextTools.ERASER_SIZE_MEDIUM]: 30,
|
||||
[contextTools.ERASER_SIZE_LARGE]: 50
|
||||
};
|
||||
// sizes are in mm
|
||||
export const BRUSH_SIZES = {
|
||||
[contextTools.BRUSH_SIZE_SMALL]: 5,
|
||||
[contextTools.BRUSH_SIZE_MEDIUM]: 10,
|
||||
[contextTools.BRUSH_SIZE_LARGE]: 15
|
||||
};
|
||||
|
||||
export const CLIPPER_PRECISION = 100; // accurate to the hundredth
|
10
src/constants/d3Constants.js
vendored
Normal file
10
src/constants/d3Constants.js
vendored
Normal file
@ -0,0 +1,10 @@
|
||||
export const SCULPT_LIMIT = 0.6;
|
||||
export const DESELECT_TRANSPARENCY = 0.8;
|
||||
export const MIN_CAMERA_ZOOM = 10;
|
||||
export const MAX_CAMERA_ZOOM = 600;
|
||||
export const MAX_CAMERA_PAN = 150;
|
||||
// Legacy compensation. Compensating for the fact that we
|
||||
// used to devide the twist by the fixed sculpt steps.
|
||||
// TODO: move this to twist factor in interface
|
||||
// and converting old files on open once
|
||||
export const LEGACY_HEIGHT_STEP = 10;
|
1
src/constants/exportConstants.js
Normal file
1
src/constants/exportConstants.js
Normal file
@ -0,0 +1 @@
|
||||
export const LINE_WIDTH = 1.0;
|
48
src/constants/general.js
Normal file
48
src/constants/general.js
Normal file
@ -0,0 +1,48 @@
|
||||
import * as contextTools from './contextTools.js';
|
||||
import bowser from 'bowser';
|
||||
|
||||
export const SHAPE_CACHE_LIMIT = 50;
|
||||
export const IS_CORDOVA = typeof cordova !== 'undefined';
|
||||
export const MAX_ANGLE = 30; // if shape has an corner sharper then MAX_ANGLE said corner will be sharp (3D)
|
||||
export const PIXEL_RATIO = 1.0;
|
||||
// On android and iOS autofocus means the keyboard pops up for one second and then hides
|
||||
// Disable autofocus on these devices
|
||||
export const AUTO_FOCUS_TEXT_FIELDS = !(bowser.mobile || bowser.tablet);
|
||||
|
||||
export const COLOR_STRING_TO_HEX = {
|
||||
[contextTools.LIGHT_BLUE]: 0xc8e4f7,
|
||||
[contextTools.LIGHT_GREEN]: 0xcbe6c0,
|
||||
[contextTools.LIGHT_PINK]: 0xf8c4d8,
|
||||
[contextTools.LIGHT_YELLOW]: 0xf5f5c0,
|
||||
[contextTools.BLUE]: 0x92c8ef,
|
||||
[contextTools.GREEN]: 0x99cc81,
|
||||
[contextTools.PINK]: 0xf28bb1,
|
||||
[contextTools.YELLOW]: 0xebea7f,
|
||||
[contextTools.DARK_BLUE]: 0x50a8e4,
|
||||
[contextTools.DARK_GREEN]: 0x5aae31,
|
||||
[contextTools.DARK_PINK]: 0xe94481,
|
||||
[contextTools.DARK_YELLOW]: 0xdfde24
|
||||
};
|
||||
export const COLOR_HEX_TO_STRING = Object
|
||||
.entries(COLOR_STRING_TO_HEX)
|
||||
.reduce((obj, [key, value]) => {
|
||||
obj[value] = key;
|
||||
return obj;
|
||||
}, {});
|
||||
|
||||
// LEGACY
|
||||
// add old color codes to corresponding color strings
|
||||
// so old doodles with old colors are previewd correctly in color picker color selector
|
||||
COLOR_HEX_TO_STRING[0x96cbef] = contextTools.BLUE;
|
||||
COLOR_HEX_TO_STRING[0x9bca87] = contextTools.GREEN;
|
||||
COLOR_HEX_TO_STRING[0xf08eb2] = contextTools.PINK;
|
||||
COLOR_HEX_TO_STRING[0xfff59a] = contextTools.YELLOW;
|
||||
COLOR_HEX_TO_STRING[0x7098b3] = contextTools.DARK_BLUE;
|
||||
COLOR_HEX_TO_STRING[0x7ab063] = contextTools.DARK_GREEN;
|
||||
COLOR_HEX_TO_STRING[0xb36984] = contextTools.DARK_PINK;
|
||||
COLOR_HEX_TO_STRING[0xf5e872] = contextTools.DARK_YELLOW;
|
||||
COLOR_HEX_TO_STRING[0x00DDFF] = contextTools.BLUE;
|
||||
|
||||
export const REQUEST_CONFIG = {
|
||||
LARGE: { timeout: 0 }
|
||||
};
|
21
src/constants/index.js
Normal file
21
src/constants/index.js
Normal file
@ -0,0 +1,21 @@
|
||||
import * as contextTools from './contextTools.js';
|
||||
import * as d2Constants from './d2Constants.js';
|
||||
import * as d2Tools from './d2Tools.js';
|
||||
import * as d3Constants from './d3Constants.js';
|
||||
import * as d3Tools from './d3Tools.js';
|
||||
import * as exportConstants from './exportConstants.js';
|
||||
import * as general from './general.js';
|
||||
import * as saveConstants from './saveConstants.js';
|
||||
import * as shapeTypeProperties from './shapeTypeProperties.js';
|
||||
|
||||
export {
|
||||
contextTool,
|
||||
d2Constant,
|
||||
d2Tool,
|
||||
d3Constant,
|
||||
d3Tool,
|
||||
exportConstant,
|
||||
genera,
|
||||
saveConstant,
|
||||
shapeTypePropertie
|
||||
};
|
4
src/constants/saveConstants.js
Normal file
4
src/constants/saveConstants.js
Normal file
@ -0,0 +1,4 @@
|
||||
export const THUMBNAIL_WIDTH = 240 * 2; // multiply times 2 because retina
|
||||
export const THUMBNAIL_HEIGHT = 200 * 2;
|
||||
export const IMAGE_TYPE = 'image/jpeg';
|
||||
export const IMAGE_QUALITY = 1; // 0 - 1
|
2
src/d3/ShapeMesh.js
vendored
2
src/d3/ShapeMesh.js
vendored
@ -1,5 +1,5 @@
|
||||
import { Vector } from '@doodle3d/cal';
|
||||
import { applyMatrixOnPath } from '../math/vectorUtils.js';
|
||||
import { applyMatrixOnPath } from '../utils/vectorUtils.js';
|
||||
import { shapeToPointsCornered } from '../shape/shapeToPoints.js';
|
||||
import * as THREE from 'three';
|
||||
import { getPointsBounds, shapeChanged } from '../shape/shapeDataUtils.js';
|
||||
|
2
src/d3/ShapesManager.js
vendored
2
src/d3/ShapesManager.js
vendored
@ -1,4 +1,4 @@
|
||||
import { SHAPE_TYPE_PROPERTIES } from '../shape/shapeTypeProperties.js';
|
||||
import { SHAPE_TYPE_PROPERTIES } from '../constants/shapeTypeProperties.js';
|
||||
import * as THREE from 'three';
|
||||
import ShapeMesh from './ShapeMesh.js';
|
||||
|
||||
|
4
src/d3/createScene.js
vendored
4
src/d3/createScene.js
vendored
@ -2,9 +2,7 @@ import * as THREE from 'three';
|
||||
import ShapesManager from './ShapesManager.js';
|
||||
import ToonShaderRenderChain from './ToonShaderRenderChain.js';
|
||||
import { hasExtensionsFor } from '../utils/webGLSupport.js';
|
||||
|
||||
// TODO move to const
|
||||
export const CANVAS_SIZE = 100;
|
||||
import { CANVAS_SIZE } from '../constants/d2Constants.js';
|
||||
|
||||
const CANVAS_WIDTH = CANVAS_SIZE * 2;
|
||||
const CANVAS_HEIGHT = CANVAS_SIZE * 2;
|
||||
|
@ -3,5 +3,6 @@ import * as shape from './shape/index.js';
|
||||
import * as utils from './utils/index.js';
|
||||
import * as d3 from './d3/index.js';
|
||||
import * as components from './components/index.js';
|
||||
import * as constants from './constants/index.js';
|
||||
|
||||
export { math, shape, utils, d3, components };
|
||||
export { math, shape, utils, d3, components, constants };
|
||||
|
@ -1,3 +0,0 @@
|
||||
import * as vectorUtils from './vectorUtils';
|
||||
|
||||
export { vectorUtils };
|
@ -3,9 +3,7 @@ import { Vector, Matrix } from '@doodle3d/cal';
|
||||
import semver from 'semver';
|
||||
import { recursivePromiseApply } from '../utils/async.js';
|
||||
import { base64ToImage, base64ToVectorArray } from '../utils/binaryUtils.js';
|
||||
|
||||
// TODO use actual const
|
||||
const LEGACY_HEIGHT_STEP = 10;
|
||||
import { LEGACY_HEIGHT_STEP } from '../constants/d3Constants.js';
|
||||
|
||||
async function JSONToSketchData({ data, appVersion }) {
|
||||
let sketchData = JSON.parse(data, (key, value) => {
|
||||
|
@ -1,6 +1,5 @@
|
||||
import shapeToPoints from './shapeToPoints.js';
|
||||
import JSONToSketchData from './JSONToSketchData.js';
|
||||
import ShapeDataUtils from './shapeDataUtils.js';
|
||||
import shapeTypeProperties from './shapeTypeProperties.js';
|
||||
|
||||
export { shapeToPoints, JSONToSketchData, shapeTypeProperties };
|
||||
export { shapeToPoints, JSONToSketchData, ShapeDataUtils };
|
||||
|
@ -1,5 +1,6 @@
|
||||
import memoize from 'memoizee';
|
||||
import { Vector } from '@doodle3d/cal';
|
||||
import { SHAPE_CACHE_LIMIT } from '../constants/general.js';
|
||||
|
||||
export function shapeChanged(oldShapeData, newShapeData) {
|
||||
const pointsChanged = oldShapeData.points !== newShapeData.points;
|
||||
@ -17,10 +18,6 @@ export function shapeChanged(oldShapeData, newShapeData) {
|
||||
circleChanged || starChanged || textChanged || polyPoints || fillChanged || heartChanged;
|
||||
}
|
||||
|
||||
// TODO use actual const
|
||||
const SHAPE_CACHE_LIMIT = 10;
|
||||
|
||||
|
||||
export const getPointsBounds = memoize(getPointsBoundsRaw, { max: SHAPE_CACHE_LIMIT });
|
||||
export function getPointsBoundsRaw(compoundPaths, transform) {
|
||||
let points = compoundPaths.reduce((a, { points: b }) => a.concat(b), []);
|
||||
|
@ -2,11 +2,10 @@ import * as THREE from 'three';
|
||||
import memoize from 'memoizee';
|
||||
import { Vector } from '@doodle3d/cal';
|
||||
import ClipperShape from '@doodle3d/clipper-js';
|
||||
import { pathToVectorPath } from '../math/vectorUtils.js';
|
||||
|
||||
// TODO use actual const
|
||||
const SHAPE_CACHE_LIMIT = 10;
|
||||
const CLIPPER_PRECISION = 10;
|
||||
import { pathToVectorPath } from '../utils/vectorUtils.js';
|
||||
import { CLIPPER_PRECISION } from '../constants/d2Constants.js';
|
||||
import { MAX_ANGLE } from '../constants/d3Constants.js';
|
||||
import { SHAPE_CACHE_LIMIT } from '../constants/general.js';
|
||||
|
||||
const HEART_BEZIER_PATH = [
|
||||
new Vector(0.0, -0.5),
|
||||
@ -232,7 +231,6 @@ function shapeToPointsCorneredRaw(shapeData) {
|
||||
});
|
||||
}
|
||||
|
||||
const MAX_ANGLE = 30; // TODO Move to actual const
|
||||
// Adds point when angle between points is larger then MAX_ANGLE
|
||||
const maxAngleRad = (MAX_ANGLE / 360) * (2 * Math.PI);
|
||||
function addCorners(oldPath) {
|
||||
|
@ -5,9 +5,9 @@ import * as THREE from 'three';
|
||||
import ThreeBSP from 'three-js-csg';
|
||||
import ClipperShape from '@doodle3d/clipper-js';
|
||||
import ShapeMesh from '../d3/ShapeMesh.js';
|
||||
import { applyMatrixOnShape, pathToVectorPath } from '../math/vectorUtils.js';
|
||||
import { applyMatrixOnShape, pathToVectorPath } from '../utils/vectorUtils.js';
|
||||
import { shapeToPoints } from '../shape/shapeToPoints.js';
|
||||
import { SHAPE_TYPE_PROPERTIES } from '../shape/shapeTypeProperties.js';
|
||||
import { SHAPE_TYPE_PROPERTIES } from '../constants/shapeTypeProperties.js';
|
||||
import { bufferToBase64 } from '../utils/binaryUtils.js';
|
||||
|
||||
const THREE_BSP = ThreeBSP(THREE);
|
||||
|
@ -4,5 +4,7 @@ import * as dbUtils from './dbUtils.js';
|
||||
import * as imageUtils from './imageUtils.js';
|
||||
import * as exportUtils from './exportUtils.js';
|
||||
import * as webGLSupport from './webGLSupport.js';
|
||||
import * as vectorUtils from './vectorUtils.js';
|
||||
import * as textUtils from './textUtils.js';
|
||||
|
||||
export { dbUtils, asyncUtils, imageUtils, exportUtils, webGLSupport, binaryUtils };
|
||||
export { dbUtils, asyncUtils, imageUtils, exportUtils, webGLSupport, binaryUtils, vectorUtils, textUt };
|
||||
|
58
src/utils/textUtils.js
Normal file
58
src/utils/textUtils.js
Normal file
@ -0,0 +1,58 @@
|
||||
import { SHAPE_CACHE_LIMIT } from '../constants/general.js';
|
||||
import { Text } from '@doodle3d/cal';
|
||||
import { POTRACE_OPTIONS } from '../constants/d2Constants.js';
|
||||
import * as POTRACE from '@doodle3d/potrace-js';
|
||||
import ClipperShape from '@doodle3d/clipper-js';
|
||||
import { shapeToVectorShape } from './vectorUtils.js';
|
||||
import memoize from 'memoizee';
|
||||
|
||||
const MARGIN = 200;
|
||||
|
||||
export const createText = memoize(createTextRaw, { max: SHAPE_CACHE_LIMIT });
|
||||
export function createTextRaw(text, size, family, style, weight) {
|
||||
if (text === '') return [];
|
||||
|
||||
const { width, height, canvas } = createTextCanvas(text, size, family, style, weight);
|
||||
|
||||
// TODO merge with potrace in flood fill trace reducer
|
||||
const paths = POTRACE.getPaths(POTRACE.traceCanvas(canvas, POTRACE_OPTIONS));
|
||||
|
||||
const halfWidth = width / 2;
|
||||
const halfHeight = height / 2;
|
||||
const pathsOffset = paths.map(path => path.map(({ x, y }) => ({
|
||||
x: (x - halfWidth) / 10,
|
||||
y: (y - halfHeight) / 10
|
||||
})));
|
||||
|
||||
const shapes = new ClipperShape(pathsOffset, true, true, false)
|
||||
.fixOrientation()
|
||||
.seperateShapes()
|
||||
.map(shape => shape.mapToLower())
|
||||
.map(shapeToVectorShape);
|
||||
|
||||
return shapes;
|
||||
}
|
||||
|
||||
const textContext = new Text();
|
||||
export function createTextCanvas(text, size, family, style, weight) {
|
||||
textContext.size = size;
|
||||
textContext.family = family;
|
||||
textContext.style = style;
|
||||
textContext.weight = weight;
|
||||
|
||||
const canvas = document.createElement('canvas');
|
||||
const context = canvas.getContext('2d');
|
||||
|
||||
const width = Math.ceil(textContext.measure(context, text)) + 2 * MARGIN;
|
||||
const height = size + 2 * MARGIN;
|
||||
|
||||
canvas.width = width;
|
||||
canvas.height = height;
|
||||
|
||||
context.fillStyle = 'white';
|
||||
context.fillRect(0, 0, width, height);
|
||||
|
||||
textContext.drawText(context, text, MARGIN, height / 2);
|
||||
|
||||
return { width, height, canvas };
|
||||
}
|
Loading…
Reference in New Issue
Block a user