Message API/docs/components/pdf/rotate-pages
Rotate Pages
Rotate one or more pages in the active PDF with rotate-r and rotate-l.
The rotate actions change the orientation of existing pages in the active PDF. Both actions use `pageRange` to identify the affected pages.
Use `rotate-r` for clockwise rotation and `rotate-l` for counterclockwise rotation.
Rotate actions are direct page edits and should be paired with a `pageManipulationResult` listener.
Rotate right
viewerWindow.postMessage({
type: 'pageManipulation',
payload: {
requestId: 'rotate-r-1',
action: 'rotate-r',
pageRange: [[0, 2]]
}
}, '*');Rotate left
viewerWindow.postMessage({
type: 'pageManipulation',
payload: {
requestId: 'rotate-l-1',
action: 'rotate-l',
pageRange: [[4]]
}
}, '*');Use this full standalone HTML document when you want a minimal host page for rotating pages.
html
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>PDF Rotate Pages Demo</title>
<style>
body {
margin: 0;
font-family: Arial, sans-serif;
background: #0b1220;
color: #e5e7eb;
}
.app {
display: grid;
grid-template-columns: 320px 1fr;
gap: 12px;
min-height: 100vh;
padding: 12px;
}
.panel {
border: 1px solid #2f3b4f;
border-radius: 12px;
background: #111827;
padding: 12px;
display: grid;
gap: 10px;
align-content: start;
}
.stack {
display: grid;
gap: 8px;
}
.row {
display: flex;
gap: 8px;
flex-wrap: wrap;
}
input, button, select {
width: 100%;
border: 1px solid #2f3b4f;
border-radius: 8px;
background: #0f172a;
color: #e5e7eb;
padding: 8px 10px;
font: inherit;
box-sizing: border-box;
}
button {
width: auto;
cursor: pointer;
}
.pages {
display: grid;
gap: 8px;
max-height: 60vh;
overflow: auto;
}
.page {
border: 1px solid #2f3b4f;
border-radius: 10px;
background: #0d1728;
padding: 8px;
display: grid;
gap: 8px;
}
.page.active {
border-color: #22d3ee;
}
iframe {
width: 100%;
height: calc(100vh - 24px);
border: 1px solid #2f3b4f;
border-radius: 12px;
background: #04101c;
}
img {
max-width: 100%;
height: auto;
display: block;
background: #fff;
border-radius: 8px;
}
.meta {
font-size: 12px;
color: #9ca3af;
}
</style>
</head>
<body>
<div class="app">
<div class="panel">
<div class="stack">
<input id="viewerUrl" value="http://localhost:5173" />
<input id="fileUrl" placeholder="Public PDF URL" />
<div class="row">
<button id="loadViewerBtn">Load Viewer</button>
<button id="loadPdfBtn">Load PDF</button>
</div>
<div id="pages" class="pages"></div>
</div>
</div>
<iframe id="viewerFrame" title="PDF Rotate Pages Demo Viewer"></iframe>
</div>
<script>
const viewerFrame = document.getElementById('viewerFrame');
const viewerUrlInput = document.getElementById('viewerUrl');
const fileUrlInput = document.getElementById('fileUrl');
const pagesEl = document.getElementById('pages');
let latestPageList = null;
function post(type, payload) {
viewerFrame.contentWindow.postMessage({ type, payload }, '*');
}
function loadViewer() {
viewerFrame.src = viewerUrlInput.value.trim();
}
function loadPdf() {
post('view', {
fileUrl: fileUrlInput.value.trim(),
displayName: 'Demo User',
username: 'demo.user',
email: 'demo@example.com'
});
}
window.addEventListener('message', (event) => {
if (event.source !== viewerFrame.contentWindow) return;
const data = event.data;
if (!data || typeof data !== 'object') return;
if (data.type === 'pageList') {
latestPageList = data.payload;
renderPages(data.payload.pages);
}
onViewerMessage(data);
});
function renderPages(pages) {
if (!pagesEl) return;
pagesEl.innerHTML = '';
pages.forEach((page) => {
const item = document.createElement('div');
item.className = page.isSelected ? 'page active' : 'page';
const actions = pageActions(page);
item.innerHTML = [
page.thumbnailDataUrl
? '<img src="' + page.thumbnailDataUrl + '" width="' + (page.thumbnailWidth || 120) + '" height="' + (page.thumbnailHeight || 160) + '" />'
: '<div class="meta">No thumbnail data</div>',
'<div><strong>' + (page.label || ('Page ' + (page.index + 1))) + '</strong></div>',
'<div class="meta">' + (page.title || 'Default') + '</div>',
actions
].join('');
wirePageActions(item, page);
pagesEl.appendChild(item);
});
}
document.getElementById('loadViewerBtn').addEventListener('click', loadViewer);
document.getElementById('loadPdfBtn').addEventListener('click', loadPdf);
function pageActions() {
return '<div class="row"><button data-action="rotate-l">Rotate Left</button><button data-action="rotate-r">Rotate Right</button></div>';
}
function wirePageActions(item, page) {
item.querySelector('[data-action="rotate-l"]').addEventListener('click', () => {
post('pageManipulation', { requestId: 'rotate-l-' + page.index, action: 'rotate-l', pageRange: [[page.index]] });
});
item.querySelector('[data-action="rotate-r"]').addEventListener('click', () => {
post('pageManipulation', { requestId: 'rotate-r-' + page.index, action: 'rotate-r', pageRange: [[page.index]] });
});
}
function onViewerMessage(data) {
if (data.type === 'pageManipulationResult') console.log(data.payload);
}
</script>
</body>
</html>Complete HTML Example
Open the focused demo to test page rotation live.
PDF Rotate Pages Demo
Focused live demo for rotate-r and rotate-l.
Preview opens in a large modal for zoom-friendly review.
