surveyjs / survey-pdf

Supplementary component to the SurveyJS Form Library to download surveys as PDF files and generate editable PDF forms.
https://surveyjs.io/pdf-generator/examples/survey-pdf-export/
Other
64 stars 32 forks source link

Read-only PDF - Radiogroup - Change Square shape Radio group UI to Circle Shapes #117

Open dk981234 opened 2 years ago

dk981234 commented 2 years ago
JaneSjs commented 1 month ago

For a read-only PDF: T20056 - UI Issue in PDF for Radio buttons https://surveyjs.answerdesk.io/internal/ticket/details/T20056


It's possible to override rendering of read-only Radiogroup questions by implementing a custom Radiogroup PDF brick. View CodeSandbox CustomRadiogroupBrick.tsx

import React from "react";
import {
  FlatRepository,
  RadioItemBrick,
  PdfBrick,
  SurveyHelper,
  IPdfBrick,
  FlatRadiogroup,
  TextBrick,
} from "survey-pdf";

class CustomRadioItemBrick extends PdfBrick {
  private rect;
  private context;

  constructor(controller, rect, context) {
    super(context.question, controller, rect);
    this.rect = rect;
    this.textColor = this.formBorderColor;
    this.context = context;
  }

  renderCircleBorders(controller: DocController, flat): void {
    if (!SurveyHelper.FORM_BORDER_VISIBLE) return;

    const minSide = Math.min(flat.width, flat.height);
    const visibleWidth =
      controller.unitHeight *
      SurveyHelper.VISIBLE_BORDER_SCALE *
      SurveyHelper.BORDER_SCALE;
    const visibleScale =
      SurveyHelper.formScale(controller, flat) + visibleWidth / minSide;

    const x: number = this.rect.xLeft;
    const y: number = this.rect.yTop;
    const centerX = x + flat.width / 2;
    const centerY = y + flat.height / 2;
    const radius = Math.min(flat.width, flat.height) / 2;

    const oldDrawColor: string = controller.doc.getDrawColor();

    controller.doc.setFillColor(255, 255, 255); 

    controller.doc.setDrawColor(flat.formBorderColor);
    controller.doc.setLineWidth(visibleWidth);
    controller.doc.circle(centerX, centerY, radius * visibleScale, "FD"); 

    controller.doc.setDrawColor(oldDrawColor);
  }

  async renderCheckmark(controller): void {
    if (this.context.checked) {
      let radiomarkerPoint = SurveyHelper.createPoint(this, true, true);
      let oldFontSize = this.controller.fontSize;
      this.controller.fontSize =
        oldFontSize * RadioItemBrick.RADIOMARKER_READONLY_FONT_SIZE_SCALE;
      let radiomarkerSize: ISize = this.controller.measureText(
        RadioItemBrick.RADIOMARKER_READONLY_SYMBOL
      );
      radiomarkerPoint.xLeft += this.width / 2.0 - radiomarkerSize.width / 2.0;
      radiomarkerPoint.yTop +=
        this.height / 2.0 - radiomarkerSize.height / 1.925;
      let radiomarkerFlat: IPdfBrick = await SurveyHelper.createTextFlat(
        radiomarkerPoint,
        this.question,
        this.controller,
        RadioItemBrick.RADIOMARKER_READONLY_SYMBOL,
        TextBrick
      );
      radiomarkerFlat.unfold()[0].textColor = this.textColor;
      this.controller.fontSize = oldFontSize;
      await radiomarkerFlat.render();
    }
  }
  async renderReadOnly() {
    this.renderCircleBorders(this.controller, this);
    this.renderCheckmark(this.controller);
  }
}

class CustomFlatRadiogroup extends FlatRadiogroup {
  generateFlatItem(rect, item, index, key, checked, context) {
    if (!this.question.isReadOnly) {
      return super.generateFlatItem(rect, item, index, key, checked, context);
    }
    const isChecked = this.isItemSelected(item, checked);
    return new CustomRadioItemBrick(this.controller, rect, {
      question: this.question,
      index: index,
      checked: isChecked,
      item: item,
    });
  }
}

FlatRepository.register("radiogroup", CustomFlatRadiogroup);

image