Created
December 19, 2019 01:13
-
-
Save jseppi/23d7229cf16337df8cc4484db3af25a5 to your computer and use it in GitHub Desktop.
Render font previews // source https://jsbin.com/lomovel
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html> | |
<head> | |
<meta charset="utf-8" /> | |
<title>Render font previews</title> | |
<meta | |
name="viewport" | |
content="initial-scale=1,maximum-scale=1,user-scalable=no" | |
/> | |
<script src="https://api.tiles.mapbox.com/mapbox-gl-js/v1.5.0/mapbox-gl.js"></script> | |
<link | |
href="https://api.tiles.mapbox.com/mapbox-gl-js/v1.5.0/mapbox-gl.css" | |
rel="stylesheet" | |
/> | |
<link | |
href="https://api.mapbox.com/mapbox-assembly/v0.24.0/assembly.min.css" | |
rel="stylesheet" | |
/> | |
<script | |
async | |
defer | |
src="https://api.mapbox.com/mapbox-assembly/v0.24.0/assembly.js" | |
></script> | |
<style> | |
body { | |
margin: 0; | |
padding: 0; | |
background: #3e3e3e; | |
} | |
.preview-image { | |
border: 1px solid yellow; | |
display:block; | |
margin-top: 10px; | |
} | |
</style> | |
</head> | |
<body> | |
<div id="render_map_1" style="position:absolute;top:-200px;width:310px; height: 30px; visibility: hidden;" class="border"></div> | |
<script id="jsbin-javascript"> | |
mapboxgl.accessToken = | |
"pk.eyJ1IjoianNlcHBpbWJ4IiwiYSI6ImNqbGU1ODdtMzBpZjUzcG1pMWJnaHB2aHgifQ.xGVwKUpyJ-S5iyaLq7GFLA"; | |
const owner = "jseppimbx"; | |
// TODO: aim for parity with current implementation (ie same width and height) | |
// even if it cuts off some previews. But maybe add a little more height, like 30px. | |
// | |
// TODO: remove cropping | |
// These would be rendered in workspace upon application mount | |
const renderMap = new mapboxgl.Map({ | |
container: "render_map_1", | |
center: [0, 0], | |
zoom: 0, | |
pitch: 0, | |
bearing: 0, | |
fadeDuration: 0, | |
preserveDrawingBuffer: true, | |
localIdeographFontFamily: false | |
}); | |
let renderMapBusy = false; | |
const renderCanvas = document.createElement('canvas'); | |
const renderCtx = renderCanvas.getContext('2d'); | |
// ----- | |
function generateFontPreviewStyle({ owner, name, text, color }) { | |
return { | |
version: 8, | |
glyphs: `mapbox://fonts/${owner}/{fontstack}/{range}.pbf`, | |
sources: { | |
font: { | |
type: "geojson", | |
data: { | |
type: "FeatureCollection", | |
features: [ | |
{ | |
type: "Feature", | |
geometry: { | |
type: "Point", | |
coordinates: [-107.5, 33] | |
}, | |
properties: {} | |
} | |
] | |
} | |
} | |
}, | |
layers: [ | |
{ | |
id: "preview", | |
source: "font", | |
type: "symbol", | |
layout: { | |
"text-justify": "left", | |
"text-anchor": "top-left", | |
"text-field": text, | |
"text-font": [name], | |
"text-max-width": 20, | |
"text-size": 20, | |
'text-line-height': 5 | |
}, | |
paint: { | |
"text-color": color, | |
"text-halo-color": color, | |
"text-halo-width": 0.3, | |
"text-halo-blur": 0 | |
} | |
} | |
] | |
}; | |
} | |
// ***** redux-like stuff | |
const state = {}; | |
state.fontPreviewsToRender = new Set(); | |
state.renderedFontPreviews = {}; | |
function makeFontKey(name, color, text) { | |
return `${name}^${color}^${text}`; | |
} | |
function fontKeyToParams(key) { | |
const parts = key.split("^"); | |
return { | |
name: parts[0], | |
color: parts[1], | |
text: parts[2] | |
}; | |
} | |
function addFontPreviewToRender(name, color, text) { | |
const key = makeFontKey(name, color, text); | |
if (!state.fontPreviewsToRender.has(key)) { | |
state.fontPreviewsToRender.add(key); | |
} | |
} | |
function getFontPreviewsToRender() { | |
const paramsToRender = []; | |
state.fontPreviewsToRender.forEach(key => { | |
const params = fontKeyToParams(key); | |
paramsToRender.push(params); | |
}); | |
return paramsToRender; | |
} | |
function saveRenderedFontPreviewData(name, color, text, dataURL) { | |
const key = makeFontKey(name, color, text); | |
state.renderedFontPreviews[key] = dataURL; | |
if (state.fontPreviewsToRender.has(key)) { | |
state.fontPreviewsToRender.delete(key); | |
} | |
} | |
// ***** fake output helpers | |
function addImage(name, color, text) { | |
const img = document.createElement("img"); | |
const key = makeFontKey(name, color, text); | |
const dataURL = state.renderedFontPreviews[key] | |
img.src = dataURL; | |
img.classList.add("preview-image"); | |
document.body.appendChild(img); | |
} | |
// ------------------- | |
function trimCanvas(canvas) { | |
// From https://stackoverflow.com/a/58882518 | |
const context = canvas.getContext("2d"); | |
const topLeft = { | |
x: canvas.width, | |
y: canvas.height, | |
update(x, y) { | |
this.x = Math.min(this.x, x); | |
this.y = Math.min(this.y, y); | |
} | |
}; | |
const bottomRight = { | |
x: 0, | |
y: 0, | |
update(x, y) { | |
this.x = Math.max(this.x, x); | |
this.y = Math.max(this.y, y); | |
} | |
}; | |
const imageData = context.getImageData(0, 0, canvas.width, canvas.height); | |
for (let x = 0; x < canvas.width; x++) { | |
for (let y = 0; y < canvas.height; y++) { | |
const alpha = imageData.data[y * (canvas.width * 4) + x * 4 + 3]; | |
if (alpha !== 0) { | |
topLeft.update(x, y); | |
bottomRight.update(x, y); | |
} | |
} | |
} | |
const width = bottomRight.x - topLeft.x; | |
const height = bottomRight.y - topLeft.y; | |
const croppedCanvas = context.getImageData( | |
topLeft.x, | |
topLeft.y, | |
width, | |
height | |
); | |
canvas.width = width; | |
canvas.height = height; | |
context.putImageData(croppedCanvas, 0, 0); | |
return canvas; | |
} | |
function trimWebglCanvas(webglCanvas, callback) { | |
renderCanvas.width = webglCanvas.width; | |
renderCanvas.height = webglCanvas.height; | |
const img = new Image(); | |
img.onload = () => { | |
renderCtx.drawImage(img, 0, 0); | |
const trimmed = trimCanvas(renderCanvas); | |
callback(trimmed); | |
}; | |
img.src = webglCanvas.toDataURL(); | |
} | |
// ***** render component stuff | |
const demoFontsToRender = [ | |
"Cascadia Code Regular", | |
"Homemade Apple Regular", | |
"Open Sans Regular", | |
"Komika Hand Bold Italic", | |
"Komika Hand Bold", | |
"Komika Hand Italic", | |
"Komika Hand Regular", | |
"Komika Parch Regular", | |
"Komika Title - Axis Regular", | |
"Komika Title - Kaps Regular", | |
"Komika Title - Paint Regular", | |
"Komika Title - Wide Regular", | |
"Komika Title Regular" | |
]; | |
const color = "#ff00ff"; | |
demoFontsToRender.forEach(name => { | |
addFontPreviewToRender(name, color, name); | |
}); | |
// get initial list of job params | |
const initialJobParams = getFontPreviewsToRender(); | |
let i = 0; | |
const windowMethod = "requestAnimationFrame"; | |
function processRenderJobs(jobParams) { | |
if (i > 100) { | |
console.log("emergency brake"); | |
return; | |
} | |
if (renderMapBusy) { | |
// requeue | |
window[windowMethod](() => processRenderJobs(jobParams)); | |
return; | |
} | |
// else | |
const jobStart = Date.now(); | |
renderMapBusy = true; | |
const [params, ...remainingParams] = jobParams; | |
const style = generateFontPreviewStyle({ | |
owner, | |
name: params.name, | |
text: params.text, | |
color: params.color | |
}); | |
renderMap.setStyle(style); | |
renderMap.once("idle", () => { | |
//trimWebglCanvas(renderMap.getCanvas(), cropped => { | |
//const dataURL = cropped.toDataURL(); | |
const dataURL = renderMap.getCanvas().toDataURL(); | |
// Save the rendered image data into state | |
saveRenderedFontPreviewData( | |
params.name, | |
params.color, | |
params.text, | |
dataURL | |
); | |
renderMapBusy = false; | |
console.log(`${params.name}: ${Date.now() - jobStart}ms`); | |
// TODO: instead of adding the image here, we'd i guess have | |
// the consuming components do something when store state is altered | |
// (via selector) due to saveRenderedFontPreviewData | |
addImage(params.name, params.color, params.text) | |
// we have more to process, so queue up the remaining | |
if (remainingParams.length) { | |
window[windowMethod](() => processRenderJobs(remainingParams)); | |
} else { | |
console.log(`Total time: ${Date.now() - start}ms`); | |
} | |
//}); | |
}); | |
} | |
const start = Date.now(); | |
window[windowMethod](() => processRenderJobs(initialJobParams)); | |
</script> | |
<script id="jsbin-source-javascript" type="text/javascript">mapboxgl.accessToken = | |
"pk.eyJ1IjoianNlcHBpbWJ4IiwiYSI6ImNqbGU1ODdtMzBpZjUzcG1pMWJnaHB2aHgifQ.xGVwKUpyJ-S5iyaLq7GFLA"; | |
const owner = "jseppimbx"; | |
// TODO: aim for parity with current implementation (ie same width and height) | |
// even if it cuts off some previews. But maybe add a little more height, like 30px. | |
// | |
// TODO: remove cropping | |
// These would be rendered in workspace upon application mount | |
const renderMap = new mapboxgl.Map({ | |
container: "render_map_1", | |
center: [0, 0], | |
zoom: 0, | |
pitch: 0, | |
bearing: 0, | |
fadeDuration: 0, | |
preserveDrawingBuffer: true, | |
localIdeographFontFamily: false | |
}); | |
let renderMapBusy = false; | |
const renderCanvas = document.createElement('canvas'); | |
const renderCtx = renderCanvas.getContext('2d'); | |
// ----- | |
function generateFontPreviewStyle({ owner, name, text, color }) { | |
return { | |
version: 8, | |
glyphs: `mapbox://fonts/${owner}/{fontstack}/{range}.pbf`, | |
sources: { | |
font: { | |
type: "geojson", | |
data: { | |
type: "FeatureCollection", | |
features: [ | |
{ | |
type: "Feature", | |
geometry: { | |
type: "Point", | |
coordinates: [-107.5, 33] | |
}, | |
properties: {} | |
} | |
] | |
} | |
} | |
}, | |
layers: [ | |
{ | |
id: "preview", | |
source: "font", | |
type: "symbol", | |
layout: { | |
"text-justify": "left", | |
"text-anchor": "top-left", | |
"text-field": text, | |
"text-font": [name], | |
"text-max-width": 20, | |
"text-size": 20, | |
'text-line-height': 5 | |
}, | |
paint: { | |
"text-color": color, | |
"text-halo-color": color, | |
"text-halo-width": 0.3, | |
"text-halo-blur": 0 | |
} | |
} | |
] | |
}; | |
} | |
// ***** redux-like stuff | |
const state = {}; | |
state.fontPreviewsToRender = new Set(); | |
state.renderedFontPreviews = {}; | |
function makeFontKey(name, color, text) { | |
return `${name}^${color}^${text}`; | |
} | |
function fontKeyToParams(key) { | |
const parts = key.split("^"); | |
return { | |
name: parts[0], | |
color: parts[1], | |
text: parts[2] | |
}; | |
} | |
function addFontPreviewToRender(name, color, text) { | |
const key = makeFontKey(name, color, text); | |
if (!state.fontPreviewsToRender.has(key)) { | |
state.fontPreviewsToRender.add(key); | |
} | |
} | |
function getFontPreviewsToRender() { | |
const paramsToRender = []; | |
state.fontPreviewsToRender.forEach(key => { | |
const params = fontKeyToParams(key); | |
paramsToRender.push(params); | |
}); | |
return paramsToRender; | |
} | |
function saveRenderedFontPreviewData(name, color, text, dataURL) { | |
const key = makeFontKey(name, color, text); | |
state.renderedFontPreviews[key] = dataURL; | |
if (state.fontPreviewsToRender.has(key)) { | |
state.fontPreviewsToRender.delete(key); | |
} | |
} | |
// ***** fake output helpers | |
function addImage(name, color, text) { | |
const img = document.createElement("img"); | |
const key = makeFontKey(name, color, text); | |
const dataURL = state.renderedFontPreviews[key] | |
img.src = dataURL; | |
img.classList.add("preview-image"); | |
document.body.appendChild(img); | |
} | |
// ------------------- | |
function trimCanvas(canvas) { | |
// From https://stackoverflow.com/a/58882518 | |
const context = canvas.getContext("2d"); | |
const topLeft = { | |
x: canvas.width, | |
y: canvas.height, | |
update(x, y) { | |
this.x = Math.min(this.x, x); | |
this.y = Math.min(this.y, y); | |
} | |
}; | |
const bottomRight = { | |
x: 0, | |
y: 0, | |
update(x, y) { | |
this.x = Math.max(this.x, x); | |
this.y = Math.max(this.y, y); | |
} | |
}; | |
const imageData = context.getImageData(0, 0, canvas.width, canvas.height); | |
for (let x = 0; x < canvas.width; x++) { | |
for (let y = 0; y < canvas.height; y++) { | |
const alpha = imageData.data[y * (canvas.width * 4) + x * 4 + 3]; | |
if (alpha !== 0) { | |
topLeft.update(x, y); | |
bottomRight.update(x, y); | |
} | |
} | |
} | |
const width = bottomRight.x - topLeft.x; | |
const height = bottomRight.y - topLeft.y; | |
const croppedCanvas = context.getImageData( | |
topLeft.x, | |
topLeft.y, | |
width, | |
height | |
); | |
canvas.width = width; | |
canvas.height = height; | |
context.putImageData(croppedCanvas, 0, 0); | |
return canvas; | |
} | |
function trimWebglCanvas(webglCanvas, callback) { | |
renderCanvas.width = webglCanvas.width; | |
renderCanvas.height = webglCanvas.height; | |
const img = new Image(); | |
img.onload = () => { | |
renderCtx.drawImage(img, 0, 0); | |
const trimmed = trimCanvas(renderCanvas); | |
callback(trimmed); | |
}; | |
img.src = webglCanvas.toDataURL(); | |
} | |
// ***** render component stuff | |
const demoFontsToRender = [ | |
"Cascadia Code Regular", | |
"Homemade Apple Regular", | |
"Open Sans Regular", | |
"Komika Hand Bold Italic", | |
"Komika Hand Bold", | |
"Komika Hand Italic", | |
"Komika Hand Regular", | |
"Komika Parch Regular", | |
"Komika Title - Axis Regular", | |
"Komika Title - Kaps Regular", | |
"Komika Title - Paint Regular", | |
"Komika Title - Wide Regular", | |
"Komika Title Regular" | |
]; | |
const color = "#ff00ff"; | |
demoFontsToRender.forEach(name => { | |
addFontPreviewToRender(name, color, name); | |
}); | |
// get initial list of job params | |
const initialJobParams = getFontPreviewsToRender(); | |
let i = 0; | |
const windowMethod = "requestAnimationFrame"; | |
function processRenderJobs(jobParams) { | |
if (i > 100) { | |
console.log("emergency brake"); | |
return; | |
} | |
if (renderMapBusy) { | |
// requeue | |
window[windowMethod](() => processRenderJobs(jobParams)); | |
return; | |
} | |
// else | |
const jobStart = Date.now(); | |
renderMapBusy = true; | |
const [params, ...remainingParams] = jobParams; | |
const style = generateFontPreviewStyle({ | |
owner, | |
name: params.name, | |
text: params.text, | |
color: params.color | |
}); | |
renderMap.setStyle(style); | |
renderMap.once("idle", () => { | |
//trimWebglCanvas(renderMap.getCanvas(), cropped => { | |
//const dataURL = cropped.toDataURL(); | |
const dataURL = renderMap.getCanvas().toDataURL(); | |
// Save the rendered image data into state | |
saveRenderedFontPreviewData( | |
params.name, | |
params.color, | |
params.text, | |
dataURL | |
); | |
renderMapBusy = false; | |
console.log(`${params.name}: ${Date.now() - jobStart}ms`); | |
// TODO: instead of adding the image here, we'd i guess have | |
// the consuming components do something when store state is altered | |
// (via selector) due to saveRenderedFontPreviewData | |
addImage(params.name, params.color, params.text) | |
// we have more to process, so queue up the remaining | |
if (remainingParams.length) { | |
window[windowMethod](() => processRenderJobs(remainingParams)); | |
} else { | |
console.log(`Total time: ${Date.now() - start}ms`); | |
} | |
//}); | |
}); | |
} | |
const start = Date.now(); | |
window[windowMethod](() => processRenderJobs(initialJobParams)); | |
</script></body> | |
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
mapboxgl.accessToken = | |
"pk.eyJ1IjoianNlcHBpbWJ4IiwiYSI6ImNqbGU1ODdtMzBpZjUzcG1pMWJnaHB2aHgifQ.xGVwKUpyJ-S5iyaLq7GFLA"; | |
const owner = "jseppimbx"; | |
// TODO: aim for parity with current implementation (ie same width and height) | |
// even if it cuts off some previews. But maybe add a little more height, like 30px. | |
// | |
// TODO: remove cropping | |
// These would be rendered in workspace upon application mount | |
const renderMap = new mapboxgl.Map({ | |
container: "render_map_1", | |
center: [0, 0], | |
zoom: 0, | |
pitch: 0, | |
bearing: 0, | |
fadeDuration: 0, | |
preserveDrawingBuffer: true, | |
localIdeographFontFamily: false | |
}); | |
let renderMapBusy = false; | |
const renderCanvas = document.createElement('canvas'); | |
const renderCtx = renderCanvas.getContext('2d'); | |
// ----- | |
function generateFontPreviewStyle({ owner, name, text, color }) { | |
return { | |
version: 8, | |
glyphs: `mapbox://fonts/${owner}/{fontstack}/{range}.pbf`, | |
sources: { | |
font: { | |
type: "geojson", | |
data: { | |
type: "FeatureCollection", | |
features: [ | |
{ | |
type: "Feature", | |
geometry: { | |
type: "Point", | |
coordinates: [-107.5, 33] | |
}, | |
properties: {} | |
} | |
] | |
} | |
} | |
}, | |
layers: [ | |
{ | |
id: "preview", | |
source: "font", | |
type: "symbol", | |
layout: { | |
"text-justify": "left", | |
"text-anchor": "top-left", | |
"text-field": text, | |
"text-font": [name], | |
"text-max-width": 20, | |
"text-size": 20, | |
'text-line-height': 5 | |
}, | |
paint: { | |
"text-color": color, | |
"text-halo-color": color, | |
"text-halo-width": 0.3, | |
"text-halo-blur": 0 | |
} | |
} | |
] | |
}; | |
} | |
// ***** redux-like stuff | |
const state = {}; | |
state.fontPreviewsToRender = new Set(); | |
state.renderedFontPreviews = {}; | |
function makeFontKey(name, color, text) { | |
return `${name}^${color}^${text}`; | |
} | |
function fontKeyToParams(key) { | |
const parts = key.split("^"); | |
return { | |
name: parts[0], | |
color: parts[1], | |
text: parts[2] | |
}; | |
} | |
function addFontPreviewToRender(name, color, text) { | |
const key = makeFontKey(name, color, text); | |
if (!state.fontPreviewsToRender.has(key)) { | |
state.fontPreviewsToRender.add(key); | |
} | |
} | |
function getFontPreviewsToRender() { | |
const paramsToRender = []; | |
state.fontPreviewsToRender.forEach(key => { | |
const params = fontKeyToParams(key); | |
paramsToRender.push(params); | |
}); | |
return paramsToRender; | |
} | |
function saveRenderedFontPreviewData(name, color, text, dataURL) { | |
const key = makeFontKey(name, color, text); | |
state.renderedFontPreviews[key] = dataURL; | |
if (state.fontPreviewsToRender.has(key)) { | |
state.fontPreviewsToRender.delete(key); | |
} | |
} | |
// ***** fake output helpers | |
function addImage(name, color, text) { | |
const img = document.createElement("img"); | |
const key = makeFontKey(name, color, text); | |
const dataURL = state.renderedFontPreviews[key] | |
img.src = dataURL; | |
img.classList.add("preview-image"); | |
document.body.appendChild(img); | |
} | |
// ------------------- | |
function trimCanvas(canvas) { | |
// From https://stackoverflow.com/a/58882518 | |
const context = canvas.getContext("2d"); | |
const topLeft = { | |
x: canvas.width, | |
y: canvas.height, | |
update(x, y) { | |
this.x = Math.min(this.x, x); | |
this.y = Math.min(this.y, y); | |
} | |
}; | |
const bottomRight = { | |
x: 0, | |
y: 0, | |
update(x, y) { | |
this.x = Math.max(this.x, x); | |
this.y = Math.max(this.y, y); | |
} | |
}; | |
const imageData = context.getImageData(0, 0, canvas.width, canvas.height); | |
for (let x = 0; x < canvas.width; x++) { | |
for (let y = 0; y < canvas.height; y++) { | |
const alpha = imageData.data[y * (canvas.width * 4) + x * 4 + 3]; | |
if (alpha !== 0) { | |
topLeft.update(x, y); | |
bottomRight.update(x, y); | |
} | |
} | |
} | |
const width = bottomRight.x - topLeft.x; | |
const height = bottomRight.y - topLeft.y; | |
const croppedCanvas = context.getImageData( | |
topLeft.x, | |
topLeft.y, | |
width, | |
height | |
); | |
canvas.width = width; | |
canvas.height = height; | |
context.putImageData(croppedCanvas, 0, 0); | |
return canvas; | |
} | |
function trimWebglCanvas(webglCanvas, callback) { | |
renderCanvas.width = webglCanvas.width; | |
renderCanvas.height = webglCanvas.height; | |
const img = new Image(); | |
img.onload = () => { | |
renderCtx.drawImage(img, 0, 0); | |
const trimmed = trimCanvas(renderCanvas); | |
callback(trimmed); | |
}; | |
img.src = webglCanvas.toDataURL(); | |
} | |
// ***** render component stuff | |
const demoFontsToRender = [ | |
"Cascadia Code Regular", | |
"Homemade Apple Regular", | |
"Open Sans Regular", | |
"Komika Hand Bold Italic", | |
"Komika Hand Bold", | |
"Komika Hand Italic", | |
"Komika Hand Regular", | |
"Komika Parch Regular", | |
"Komika Title - Axis Regular", | |
"Komika Title - Kaps Regular", | |
"Komika Title - Paint Regular", | |
"Komika Title - Wide Regular", | |
"Komika Title Regular" | |
]; | |
const color = "#ff00ff"; | |
demoFontsToRender.forEach(name => { | |
addFontPreviewToRender(name, color, name); | |
}); | |
// get initial list of job params | |
const initialJobParams = getFontPreviewsToRender(); | |
let i = 0; | |
const windowMethod = "requestAnimationFrame"; | |
function processRenderJobs(jobParams) { | |
if (i > 100) { | |
console.log("emergency brake"); | |
return; | |
} | |
if (renderMapBusy) { | |
// requeue | |
window[windowMethod](() => processRenderJobs(jobParams)); | |
return; | |
} | |
// else | |
const jobStart = Date.now(); | |
renderMapBusy = true; | |
const [params, ...remainingParams] = jobParams; | |
const style = generateFontPreviewStyle({ | |
owner, | |
name: params.name, | |
text: params.text, | |
color: params.color | |
}); | |
renderMap.setStyle(style); | |
renderMap.once("idle", () => { | |
//trimWebglCanvas(renderMap.getCanvas(), cropped => { | |
//const dataURL = cropped.toDataURL(); | |
const dataURL = renderMap.getCanvas().toDataURL(); | |
// Save the rendered image data into state | |
saveRenderedFontPreviewData( | |
params.name, | |
params.color, | |
params.text, | |
dataURL | |
); | |
renderMapBusy = false; | |
console.log(`${params.name}: ${Date.now() - jobStart}ms`); | |
// TODO: instead of adding the image here, we'd i guess have | |
// the consuming components do something when store state is altered | |
// (via selector) due to saveRenderedFontPreviewData | |
addImage(params.name, params.color, params.text) | |
// we have more to process, so queue up the remaining | |
if (remainingParams.length) { | |
window[windowMethod](() => processRenderJobs(remainingParams)); | |
} else { | |
console.log(`Total time: ${Date.now() - start}ms`); | |
} | |
//}); | |
}); | |
} | |
const start = Date.now(); | |
window[windowMethod](() => processRenderJobs(initialJobParams)); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment