Spaces:
Running
Running
File size: 2,908 Bytes
f2bee8a |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 |
import computedStyleToInlineStyle from 'computed-style-to-inline-style';
import LazyScratchBlocks from '../tw-lazy-scratch-blocks';
/**
* Given a blockId, return a data-uri image that can be used to create a thumbnail.
* @param {string} blockId the ID of the block to imagify
* @return {Promise} resolves to a data-url of a picture of the blocks
*/
export default function (blockId) {
const ScratchBlocks = LazyScratchBlocks.get();
// Not sure any better way to access the scratch-blocks workspace than this...
const block = ScratchBlocks.getMainWorkspace().getBlockById(blockId);
const blockSvg = block.getSvgRoot().cloneNode(true /* deep */);
// Once we have the cloned SVG, do the rest in a setTimeout to prevent
// blocking the drag end from finishing promptly.
return new Promise(resolve => {
setTimeout(() => {
// TW: Fixes issues caused by scratch-blocks block hiding
blockSvg.style.display = '';
// Strip entities that cannot be inlined
blockSvg.innerHTML = blockSvg.innerHTML.replace(/ /g, ' ');
// Create an <svg> element to put the cloned blockSvg inside
const NS = 'http://www.w3.org/2000/svg';
const svg = document.createElementNS(NS, 'svg');
svg.appendChild(blockSvg);
// Needs to be on the DOM to get CSS properties and correct sizing
document.body.appendChild(svg);
const padding = 10;
const extraHatPadding = 16;
const topPadding = padding + (blockSvg.getAttribute('data-shapes') === 'hat' ? extraHatPadding : 0);
const leftPadding = padding;
blockSvg.setAttribute('transform', `translate(${leftPadding} ${topPadding})`);
const bounds = blockSvg.getBoundingClientRect();
svg.setAttribute('width', bounds.width + (2 * padding));
svg.setAttribute('height', bounds.height + (2 * padding));
// We need to inline the styles set by CSS rules because
// not all the styles are set directly on the SVG. This makes the
// image styled the same way the block actually appears.
// TODO this doesn't handle images that are xlink:href in the SVG
computedStyleToInlineStyle(svg, {
recursive: true,
// Enumerate the specific properties we need to inline.
// Specifically properties that are set from CSS in scratch-blocks
properties: ['fill', 'font-family', 'font-size', 'font-weight']
});
const svgString = (new XMLSerializer()).serializeToString(svg);
// Once we have the svg as a string, remove it from the DOM
svg.parentNode.removeChild(svg);
resolve(`data:image/svg+xml;utf-8,${encodeURIComponent(svgString)}`);
}, 10);
});
}
|