I am trying to create an effect with Fabric JS where letters appear to be "embroidered" on a sweater like this:
I can achieve this effect in Photoshop by using this action.
My idea for getting it into a <canvas>
is to render out a png from Photoshop of every embroidered letter. Then, I will take each letter and place it on the canvas based on what the user types.
However this approach will not have correct kerning.
To fix this, I was trying to write out text in Fabric using the same font and then overlay each embroidered png on top of the letter it is replacing (and then hide the text itself).
Here’s how I render the text:
window.chest_text = new fabric.IText("NYC", {
fill: '#000',
fontSize: 12,
left: 210,
top: 100,
fontFamily: 'Graphik',
fontWeight: 500,
lineHeight: 1,
originX: 'center',
});
And then here’s how I render the embroidered letters:
var n_url = 'https://res.cloudinary.com/tricot/image/upload/v1598820746/tmp/n-embroidery-test.png'
var y_url = 'https://res.cloudinary.com/tricot/image/upload/v1598820745/tmp/y-embroidery-test.png'
var c_url = 'https://res.cloudinary.com/tricot/image/upload/v1598820745/tmp/c-embroidery-test.png'
fabric.Image.fromURL(n_url, function(img) {
img.set({
left: Math.round(window.chest_text.aCoords.bl.x),
top: window.chest_text.top
})
img.scaleToHeight(Math.floor(window.chest_text.__charBounds[0][0].height / 1.13), true)
canvas.add(img);
})
fabric.Image.fromURL(y_url, function(img) {
img.set({
left: Math.round(window.chest_text.aCoords.bl.x + window.chest_text.__charBounds[0][1].left),
top: window.chest_text.top
})
img.scaleToHeight(Math.floor(window.chest_text.__charBounds[0][1].height / 1.13), true)
canvas.add(img);
})
fabric.Image.fromURL(c_url, function(img) {
img.set({
left: Math.round(window.chest_text.aCoords.bl.x + window.chest_text.__charBounds[0][2].left),
top: window.chest_text.top
})
img.scaleToHeight(Math.floor(window.chest_text.__charBounds[0][2].height / 1.13), true)
canvas.add(img);
})
window.chest_text.opacity = 0.5
window.canvas.renderAll()
However I can’t get the embroidered letters to EXACTLY overlay the regular text (even though it’s the same font):
How can I achieve this? Is there a better way of getting kerning to work correctly?
2
Answers
Using line dash as the stitch and
ctx.globalCompositeOperation = "source-atop"
to draw only inside the text. Vary the stroke width to build stitches from inside of font out.
Unfortunately the line dash spacing is only true for the stroke center so the approach works for some characters but not all.
Can be improved upon as there was no effort to round stitchs (highlight and shadow color per stitch) but as there is no control over positioning of stitches at line joins i could not see the point of refining it further.
Will work with any font.
See snippet for demo and code.
If you manage to find the font you could use a font.
There is a font that might be closer to what you need, NCD Embroidery but you have to contact the designer to get a license.
You might even find the font in one of the Photoshop libraries (I’m not that familiar with Photoshop, so this is just a guess)
Registered the font in .css file.
and the code:
The results from the fonts:
fs Mom license
FS Ariapenciroman license
Fabric license