javascriptpdf-generationpdfkitnode-pdfkit

PDFkit : how to create text over rectangle like material ui textfield look?


I am learning PDFkit I am playing with a demo now I want to create a rectangle with text inside which looks like a material UI texfield.

The Expected results:

enter image description here

So far here is what I have.

var doc = new PDFDocument();
var stream = doc.pipe(blobStream());

    doc.rect(45, 165, 240, 22).fillAndStroke('#ddd', '#000');
    doc.fill('#F00').stroke();
    doc.fontSize(16);
    doc.text("Sample text", 50, 170, {lineBreak: false} );


doc.end();
stream.on('finish', function() {
  iframe.src = stream.toBlobURL('application/pdf');
});

You can run the example above here. : live demo

What do I need to add here to get what I want? any suggestion will be appreciated.

UPDATE I am struggling to remove the line where there is top text as image shows below .

enter image description here


Solution

  • Building PDF with a fixed set of objects can be a challenge.

    Normally using primitives a line would be drawn around the desired area but with a gap left before fill.

    Using PDFKit you may need to adapt as graphics workarounds thus adapting the example above, in comments I suggested simply add a background to the text as emulated here.

    you need to emulate the stroke clipping one human way is to overlay behind text or use a text box with background fill but will be noticed unless white on white as per image the computer way is draw the shape with a stroke line starting away from the label go all the way around the shape with rounded corners then stop short of other side of lable then fill the unclosed shape the colur will not bleed out (there is a clip/clipping function AFAIK also to try)

    enter image description here

    // create a document and pipe to a blob
    var doc = new PDFDocument();
    var stream = doc.pipe(blobStream());
    
        doc.rect(45, 165, 240, 52).fillAndStroke('#ddd', '#000');
        doc.rect(55, 154, 95, 22).fill('#fff', '#000');
        doc.fill('#F00').stroke();
        doc.fontSize(16);
        doc.text("Sample text", 60, 160, {lineBreak: false} );
    
    
    doc.end();
    stream.on('finish', function() {
      iframe.src = stream.toBlobURL('application/pdf');
    });
    

    you could make the white box smaller/higher so it only clips the edge of the grey area here I reduced size to 11.1 (can be any suited value) but its a flaky setting and for the text confusing as two background colours.

    enter image description here

    The better solution is to use the same background colour

    enter image description here

    // create a document and pipe to a blob
    var doc = new PDFDocument();
    var stream = doc.pipe(blobStream());
        doc.lineWidth(2);
        doc.lineJoin('round')
        doc.roundedRect(45, 165, 240, 52, 5).fillAndStroke('#ddd', '#000');
        doc.roundedRect(55, 154, 95, 22, 3).fillAndStroke('#ddd', '#000');
        doc.fill('#F00').stroke();
        doc.fontSize(16);
        doc.text("Sample text", 60, 159, {lineBreak: false} );
    
    
    doc.end();
    stream.on('finish', function() {
      iframe.src = stream.toBlobURL('application/pdf');
    });
    

    Or fancy

    enter image description here