Skip to content

Free Text Controller viewer>=4.2.0 & annotation>=1.5.0

AnnotationFreeTextControl

An instance object that allows programmatic control of the free text annotation tool. It requires the @vue-pdf-viewer/annotation@^1.5.0 plugin to be loaded. A console warning is shown if methods are called without it.

Plugin Required

annotationFreeTextControl is undefined when the annotation plugin is not passed to the Vue PDF component. Always use optional chaining: viewerRef.value?.annotationFreeTextControl?.activate().

Reactive State

NameDescriptionType
isActiveWhether the free text tool is currently activeboolean
fontColorThe currently configured font color (hex string), or null if using the defaultstring | null
fontSizeThe currently configured font size in points, or null if using the default (16pt)number | null

Methods

NameDescriptionType
activateActivate the free text annotation tool. Deactivates any active text-selection tool (highlight, underline, strikethrough)() => void
deactivateDeactivate the free text annotation tool() => void
setFontColorSet the default font color for newly created free text annotations. Accept any hex color string (e.g. '#FF0000'). Invalid values are silently ignored(color: string) => void
setFontSizeSet the default font size (in points) for newly created free text annotations. Must be a positive number. Invalid values are ignored(size: number) => void

Mutual Exclusivity

Activating the free text tool via activate() automatically deactivates any active text-selection annotation tool (highlight, underline, strikethrough). Conversely, activating a text-selection tool deactivates the free text tool. Only one annotation tool can be active at a time.

Bidirectional Sync

annotationFreeTextControl.isActive reflects the live state of the viewer. When a user activates or deactivates the free text tool via the built-in annotation toolbar, isActive updates reactively.

Example

vue
<script setup lang="ts">
import { ref, computed, watch } from 'vue'
import { VPdfViewer, type VPVInstance } from '@vue-pdf-viewer/viewer'
import VPdfAnnotationPlugin from '@vue-pdf-viewer/annotation'

const viewerRef = ref<VPVInstance>()

const annotationPlugin = VPdfAnnotationPlugin({
  // Hide the free text annotation button of the toolbar
  freeText: false
})

const annotationFreeTextControl = computed(() => viewerRef.value?.annotationFreeTextControl)

const freeTextButtonLabel = computed(() => {
  if (!annotationFreeTextControl.value) return 'Free Text (unavailable)'
  return annotationFreeTextControl.value.isActive ? 'Free Text (active)' : 'Free Text'
})

function onFreeTextClick() {
  annotationFreeTextControl.value?.activate()
}

function onDeactivate() {
  annotationFreeTextControl.value?.deactivate()
}

function onColorPick(color: string) {
  annotationFreeTextControl.value?.setFontColor(color)
}

function onFontSizePick(size: number) {
  annotationFreeTextControl.value?.setFontSize(size)
}

// Watch for tool activation changes (including those from the built-in toolbar)
watch(
  () => annotationFreeTextControl.value?.isActive,
  (isActive) => {
    console.log('Free text tool active:', isActive)
  }
)
</script>

<template>
  <div id="vpv">
    <!-- Custom toolbar -->
    <div class="my-toolbar">
      <button
        :class="{ active: annotationFreeTextControl?.isActive }"
        @click="onFreeTextClick"
      >
        {{ freeTextButtonLabel }}
      </button>
      <button @click="onDeactivate">Deactivate</button>
      <input
        type="color"
        :value="annotationFreeTextControl?.fontColor ?? '#000000'"
        @input="(e) => onColorPick((e.target as HTMLInputElement).value)"
      />
      <select @change="(e) => onFontSizePick(Number((e.target as HTMLSelectElement).value))">
        <option v-for="size in [10, 12, 14, 16, 18, 24, 32]" :key="size" :value="size">
          {{ size }}pt
        </option>
      </select>
    </div>

    <div :style="{ width: '100%', height: '100%' }">
      <VPdfViewer
        ref="viewerRef"
        src="https://raw.githubusercontent.com/mozilla/pdf.js/ba2edeae/web/compressed.tracemonkey-pldi-09.pdf"
        :plugins="[annotationPlugin]"
      />
    </div>
  </div>
</template>
<style scoped>
#vpv {
  width: 100%;
  height: 1490px;
  margin: 0 auto;
}
@media (max-width: 992px) {
  #vpv {
    width: 85%;
  }
}
@media (max-width: 1028px) {
  #vpv {
    width: 70%;
  }
}
</style>
vue
<script setup>
import { ref, computed, watch } from 'vue'
import { VPdfViewer } from '@vue-pdf-viewer/viewer'
import VPdfAnnotationPlugin from '@vue-pdf-viewer/annotation'

const viewerRef = ref()

const annotationPlugin = VPdfAnnotationPlugin({
  // Hide the free text annotation button of the toolbar
  freeText: false
})

const annotationFreeTextControl = computed(() => viewerRef.value?.annotationFreeTextControl)

function onFreeTextClick() {
  annotationFreeTextControl.value?.activate()
}

function onDeactivate() {
  annotationFreeTextControl.value?.deactivate()
}

function onColorPick(color) {
  annotationFreeTextControl.value?.setFontColor(color)
}

function onFontSizePick(size) {
  annotationFreeTextControl.value?.setFontSize(Number(size))
}

watch(
  () => annotationFreeTextControl.value?.isActive,
  (isActive) => {
    console.log('Free text tool active:', isActive)
  }
)
</script>

<template>
  <div id="vpv">
    <div class="my-toolbar">
      <button
        :class="{ active: annotationFreeTextControl?.isActive }"
        @click="onFreeTextClick"
      >
        Free Text
      </button>
      <button @click="onDeactivate">Deactivate</button>
      <input
        type="color"
        :value="annotationFreeTextControl?.fontColor ?? '#000000'"
        @input="(e) => onColorPick(e.target.value)"
      />
      <select @change="(e) => onFontSizePick(e.target.value)">
        <option v-for="size in [10, 12, 14, 16, 18, 24, 32]" :key="size" :value="size">
          {{ size }}pt
        </option>
      </select>
    </div>

    <div :style="{ width: '100%', height: '100%' }">
      <VPdfViewer
        ref="viewerRef"
        src="https://raw.githubusercontent.com/mozilla/pdf.js/ba2edeae/web/compressed.tracemonkey-pldi-09.pdf"
        :plugins="[annotationPlugin]"
      />
    </div>
  </div>
</template>
<style scoped>
#vpv {
  width: 100%;
  height: 1490px;
  margin: 0 auto;
}
@media (max-width: 992px) {
  #vpv {
    width: 85%;
  }
}
@media (max-width: 1028px) {
  #vpv {
    width: 70%;
  }
}
</style>
vue
<script lang="ts">
import { VPdfViewer, type VPVInstance } from '@vue-pdf-viewer/viewer'
import VPdfAnnotationPlugin from '@vue-pdf-viewer/annotation'
import { ref, computed, defineComponent, watch } from 'vue'

export default defineComponent({
  components: { VPdfViewer },
  setup() {
    const viewerRef = ref<VPVInstance>()

    const annotationPlugin = VPdfAnnotationPlugin({
      // Hide the free text annotation button of the toolbar
      freeText: false
    })

    const annotationFreeTextControl = computed(() => viewerRef.value?.annotationFreeTextControl)

    const onFreeTextClick = () => annotationFreeTextControl.value?.activate()
    const onDeactivate = () => annotationFreeTextControl.value?.deactivate()
    const onColorPick = (color: string) => annotationFreeTextControl.value?.setFontColor(color)
    const onFontSizePick = (size: number) => annotationFreeTextControl.value?.setFontSize(size)

    watch(
      () => annotationFreeTextControl.value?.isActive,
      (isActive) => {
        console.log('Free text tool active:', isActive)
      }
    )

    return {
      viewerRef,
      annotationPlugin,
      annotationFreeTextControl,
      onFreeTextClick,
      onDeactivate,
      onColorPick,
      onFontSizePick,
    }
  }
})
</script>

<template>
  <div id="vpv">
    <div class="my-toolbar">
      <button
        :class="{ active: annotationFreeTextControl?.isActive }"
        @click="onFreeTextClick"
      >
        Free Text
      </button>
      <button @click="onDeactivate">Deactivate</button>
      <input
        type="color"
        :value="annotationFreeTextControl?.fontColor ?? '#000000'"
        @input="(e) => onColorPick((e.target as HTMLInputElement).value)"
      />
      <select @change="(e) => onFontSizePick(Number((e.target as HTMLSelectElement).value))">
        <option v-for="size in [10, 12, 14, 16, 18, 24, 32]" :key="size" :value="size">
          {{ size }}pt
        </option>
      </select>
    </div>

    <div :style="{ width: '100%', height: '100%' }">
      <VPdfViewer
        ref="viewerRef"
        src="https://raw.githubusercontent.com/mozilla/pdf.js/ba2edeae/web/compressed.tracemonkey-pldi-09.pdf"
        :plugins="[annotationPlugin]"
      />
    </div>
  </div>
</template>
<style scoped>
#vpv {
  width: 100%;
  height: 1490px;
  margin: 0 auto;
}
@media (max-width: 992px) {
  #vpv {
    width: 85%;
  }
}
@media (max-width: 1028px) {
  #vpv {
    width: 70%;
  }
}
</style>
vue
<script>
import { VPdfViewer } from '@vue-pdf-viewer/viewer'
import VPdfAnnotationPlugin from '@vue-pdf-viewer/annotation'
import { ref, computed, defineComponent, watch } from 'vue'

export default defineComponent({
  components: { VPdfViewer },
  setup() {
    const viewerRef = ref()

    const annotationPlugin = VPdfAnnotationPlugin({
      // Hide the free text annotation button of the toolbar
      freeText: false
    })

    const annotationFreeTextControl = computed(() => viewerRef.value?.annotationFreeTextControl)

    const onFreeTextClick = () => annotationFreeTextControl.value?.activate()
    const onDeactivate = () => annotationFreeTextControl.value?.deactivate()
    const onColorPick = (color) => annotationFreeTextControl.value?.setFontColor(color)
    const onFontSizePick = (size) => annotationFreeTextControl.value?.setFontSize(Number(size))

    watch(
      () => annotationFreeTextControl.value?.isActive,
      (isActive) => {
        console.log('Free text tool active:', isActive)
      }
    )

    return {
      viewerRef,
      annotationPlugin,
      annotationFreeTextControl,
      onFreeTextClick,
      onDeactivate,
      onColorPick,
      onFontSizePick,
    }
  }
})
</script>

<template>
  <div id="vpv">
    <div class="my-toolbar">
      <button
        :class="{ active: annotationFreeTextControl?.isActive }"
        @click="onFreeTextClick"
      >
        Free Text
      </button>
      <button @click="onDeactivate">Deactivate</button>
      <input
        type="color"
        :value="annotationFreeTextControl?.fontColor ?? '#000000'"
        @input="(e) => onColorPick(e.target.value)"
      />
      <select @change="(e) => onFontSizePick(e.target.value)">
        <option v-for="size in [10, 12, 14, 16, 18, 24, 32]" :key="size" :value="size">
          {{ size }}pt
        </option>
      </select>
    </div>

    <div :style="{ width: '100%', height: '100%' }">
      <VPdfViewer
        ref="viewerRef"
        src="https://raw.githubusercontent.com/mozilla/pdf.js/ba2edeae/web/compressed.tracemonkey-pldi-09.pdf"
        :plugins="[annotationPlugin]"
      />
    </div>
  </div>
</template>
<style scoped>
#vpv {
  width: 100%;
  height: 1490px;
  margin: 0 auto;
}
@media (max-width: 992px) {
  #vpv {
    width: 85%;
  }
}
@media (max-width: 1028px) {
  #vpv {
    width: 70%;
  }
}
</style>