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
| Name | Description | Type |
|---|---|---|
isActive | Whether the free text tool is currently active | boolean |
fontColor | The currently configured font color (hex string), or null if using the default | string | null |
fontSize | The currently configured font size in points, or null if using the default (16pt) | number | null |
Methods
| Name | Description | Type |
|---|---|---|
activate | Activate the free text annotation tool. Deactivates any active text-selection tool (highlight, underline, strikethrough) | () => void |
deactivate | Deactivate the free text annotation tool | () => void |
setFontColor | Set 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 |
setFontSize | Set 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
<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><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><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><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>