Skill Level: Intermediate to Advanced
Acrobat 7 and Later
In Acrobat, the term “Layers” refers to Optional Content Groups (OCGs). OCGs are a mechanism for selectively controlling the visibility of page content. In Acrobat 7 (Professional and Standard) it is possible to both create and control these content layers through Acrobat JavaScript, giving the document developer a totally new ability to use dynamic content purely through scripting tools already available in Acrobat Professional. This is not another kind of form field or annotation, but true page content. OCGs are used to create multilayer pages (like a stack of transparencies), for everything from multi-language documents, layered views for architectural plans, to animated displays.
To the user, an OCG appears as a physical layer of content on a PDF page. Figure 1 shows the Layers Panel (Menu: View>Navigation Tabs>Layers). Each entry in this panel represents an OCG in the document. Clicking the mouse on one of the Show/Hide buttons toggles the visibility of the page content associated with that layer. In this figure 3 OCGs are displayed. The first one (MyLayer) is hidden and the other two are visible as indicated by their Show/Hide buttons.
It’s easy to get the impression that the drawn page content and the OCG layer are the same thing, or that the page contents associated with the OCG are on some kind of physical layer, but this is not true. OCGs are not visible objects on the document or even real layers. They are a logical construction inside the PDF file that has either a true or false state. Any drawn object can be attached to an OCG. If the state of the OCG is true the object is drawn, and if the state is false the object is not drawn, so the Show/Hide buttons in the Layers panel really control the state of the OCG. This is very different from the concept of layers in other programs like Adobe Photoshop®. However, OCG layers are added when some file formats are converted to PDF. Adobe InDesign®, Microsoft PowerPoint®, and Autodesk AutoCAD® files can all be converted to a layered PDF when appropriately set up. Unfortunately, there isn’t yet a tool in Acrobat that can arbitrarily attach OCGs to drawn objects on the page. OCGs are only available through third party tools, file conversions, and a couple operations built into Acrobat Professional. It’s these Acrobat operations we’ll be using in this article since they give us a way to create OCGs without relying on external tools. They are the Watermark and Backgrounds and Headers and Footers menu items. However, layers created in other ways can be manipulated with the same techniques discussed here.
OCGs were first added to the PDF specification in Acrobat 6. At the same time some basic JavaScript control over the OCGs was also added; i.e., the ability to list the existing OCGs and change OCG state. It was in Acrobat 7 that OCGs became really useful from JavaScript. The two most important features added were the ability to create an OCG layer with the Watermark functions, and the ability to rename an OCG.
Let’s get right into creating an OCG. For the following example you’ll need Acrobat Professional 7.0. First open up a PDF document. We’ll use this document as a scratch pad for trying out the OCG operations so make sure it’s a document you don’t mind altering, and has only a few pages. Next, bring up the JavaScript Console. If you’re unfamiliar with the JavaScript Console, read this tutorial.
Now we’re ready to begin. Enter and run the following line of code in the JavaScript Console.
this.addWatermarkFromText("Draft Copy");
This single line script will add the words “Draft Copy” to the center of all the document pages. This function has a large number of options for placing the text, controlling color, font, text size, and other parameters. There is also a related function, doc.addWatermarkFromFile(), that uses a PDF file to create the watermark. These functions also create an OCG layer to which the watermark is attached. Adding a Watermark, Background, Header, or Footer to the document from the Acrobat menus will also create an OCG.
Now activate the Layers Panel in Acrobat (Menu item: View>Navigation Tabs>Layers). The first thing to notice is that the panel is empty. No OCGs are listed. The layer we just created with the watermark function is hidden from the user, but it isn’t hidden from JavaScript. Run the following code in the Console.
this.getOCGs();
The doc.getOCGs() function returns an array of OCG Objects. The result of this operation (Figure 2) shows the document contains only a single OCG named Watermark, which is from the previous doc.addWatermarkFromText() operation. The watermark functions always give the newly created OCG the name Watermark. If you use the watermark function a second time, a new watermark is added to the document, but a new OCG is not created. Instead, both watermarks are part of the same OCG.
The following function is used to find an OCG with a specific name. It will be referenced in some of the following examples so please run it in the JavaScript Console now, and/or when you use that example.
function FindOCG(cName) { var aOCGs = this.getOCGs(); for(var i=0; aOCGs && i<aOCGs.length;i++) { if(aOCGs[i].name == cName) return aOCGs[i]; } return null; }
The OCG Object provides a limited set of functions and properties for manipulating the layer.
OCG Object Members: (R/W Read/Write)
Properties: | R/W | Description |
initState - | R/W | Sets and gets the OCG state when the PDF is opened |
locked - | R/W | Block changes to the OCG from the User Interface, can only be changed from JavaScript |
name - | R/W | Identifying Name of the OCG |
state - | R/W | On/Off (Visible/Hidden) value of the OCG |
|
|
|
Functions: | Description | |
getIntent() - | Gets the viewing intent of the OCG, two values: | |
setIntent() - | Sets the viewing intent of the OCG | |
setAction() - | Sets a JavaScript action to be evaluated each time the state of the layer changes |
The state property is used at runtime to toggle the visibility of the OCG. All the other properties make changes to the PDF. They are more useful at document design time for automating the creation of an OCG. If used at runtime, the document would have to be saved for the changes to stick. This is a big problem when the PDF is viewed in Reader.
As an example of Design Time usage we’ll make a multi-layer PDF. The basic sequence is to alternately create an OCG with one of the watermark functions and then rename it using the name property. The following code adds three OCGs to a document. Each text watermark is offset by a quarter inch from the next. Copy and paste this code into the Console, then run it.
This code uses the FindOCG() function defined earlier in this article. Make sure to run the FindOCG() code first, so that the following code will work.
// First rename any previous layers named Watermark var ocg = null; while( (ocg = FindOCG("Watermark")) != null) ocg.name = "PreviousWatermark"; // Add three OCG layers to current PDF this.addWatermarkFromText({cText:"One",aColor:color.red,nVertValue:18}); FindOCG("Watermark").name = "LayerOne"; this.addWatermarkFromText({cText:"Two",aColor:color.blue,nVertValue:36}); FindOCG("Watermark").name = "LayerTwo"; this.addWatermarkFromText({cText:"Three",aColor:color.green,nVertValue:54}); FindOCG("Watermark").name = "LayerThree";
The words “One”, “Two”, and “Three” should now appear slightly above the middle of the page in the colors red, blue, and green.
To allow the user to manipulate these OCGs, or to allow us to make changes in the OCGs that can’t be done from JavaScript, the OCGs must be visible in the Layers Panel (Figure 1). Inside the PDF, the OCGs that appear on this panel are referred to as the Order Array. From Acrobat JavaScript the doc.setOCGOrder() function is used to place OCGs into the Order Array. The following code makes all the OCGs in the PDF visible on the Layers Panel.
this.setOCGOrder(this.getOCGs());
All the OCGs should now be displayed on the Layers Panel.
Not all OCG properties can be set with JavaScript, and there are a couple important ones that currently can only be set from the OCG Properties Dialog. To display this dialog (Figure 3), right click on the OCG in the Layers Panel and select “Properties”.
Both the Visibility and Print parameters are defaulted to Always. This doesn’t block JavaScript from changing the state of an OCG, but Acrobat re-evaluates the state of an OCG every time the layered content is redrawn. This happens when the document page is scrolled, zoomed, printed, or when any changes to the window are made. If the visibility is set to Always or Never, then these states will override the JavaScript setting. Change them to the settings shown in Figure 3 for all three layers.
Now that we have 3 properly setup OCGs lets do a simple animation (see the example document below). To control this animation we’ll use an Acrobat Timer created with the app.setInterval() function. The interval function will use a counter to alternately turn the layers on and off. Start by placing the FindOCG() script, shown previously, in a Document Level script. We’ll use this function for locating the OCGs by name. Then place a button on the document and add the following code to the Mouse Down action.
OCGAnimation
Example document
Download [PDF, 18KB]
This code uses the FindOCG() function defined earlier in this article. Make sure to run the FindOCG() code first, so that the following code will work.
// When the PDF is first opened the "inc" variable does not exist // so we use it to signal initialization. This could be moved to // a document script. if(this.inc == null){ // Initialize layer states FindOCG("LayerOne").state = false; FindOCG("LayerTwo").state = false; FindOCG("LayerThree").state = false; // Initialize Counter Variable this.inc = -1; } // Array of layer Names, could be moved to a document script var aLayers = ["LayerOne","LayerTwo","LayerThree"]; // Timer Interval function, Could be moved to a document script function ToggleOCGs() { if(inc >= 0){ // Toggle the state of the previous OCG var ocg = FindOCG(aLayers[this.inc]); ocg.state = !ocg.state; } // Increment the counter, reset if necessary this.inc++; if(this.inc > 2) this.inc = 0; // Toggle the state of the next OCG var ocg = FindOCG(aLayers[this.inc]); ocg.state = !ocg.state; } //*** Main Button Code *** // Toggle Animation timer on and off based on the existence // of the iTimer variable if(this.iTimer){ // Timer exists so turn it off try{ app.clearInterval(this.iTimer); }finally{ this.iTimer = null; } event.target.buttonSetCaption("Start Animation"); }else{ // Timer does not exist so start it up this.iTimer = app.setInterval("ToggleOCGs();",500); event.target.buttonSetCaption("STOP Animation"); }
The first part of this script initializes all the OCGs to hidden. The second part defines an array of OCG names (to be used in the toggle function) and the function that will be used to toggle the OCG layers on and off. All of this code is initialization and can be moved to a document script. The last piece of code, the main button code, turns the timer on and off based on its current state, and sets the button’s label to reflect this.
The ToggleOCGs() function is called each time the timing interval is reached, 500 milliseconds. Its basic operation is to toggle the state of the current OCG, indicated by the counter value, then increment the counter and toggle the state of the next OCG. If everything is set up properly this has the effect of hiding the currently visible layer and making the next layer visible. The one exception to this sequence is the first time the function is called. In that case, all the OCGs are turned off, so we have to skip the lines of code that toggle the state of the previous OCG.
Any parameter in Acrobat or a PDF document accessible with JavaScript can be used to control the visibility of an OCG layer: the viewer’s language, the zoom factor, the document’s URL, the page number, a value in a form field, a button’s mouse down event, etc. This allows us a great deal of latitude in building PDF documents with content controllable through JavaScript.
In Acrobat 7, Optional Content Groups (OCGs) can be created and manipulated with JavaScript. Functions provided in the Document Object and the OCG Object allows for the creation of multiple layer documents, where each layer controls the visibility of content on the PDF page. These OCG layers can be controlled at runtime to create document effects like animations and multi-language documents.
Related topics: |
JavaScript |
Top Searches: |
Edit PDF create PDF Action Wizard |
Try Acrobat DC
Get started >
Learn how to
edit PDF.
Post, discuss and be part of the Acrobat community.
Join now >
1 comment
Comments for this tutorial are now closed.
Lori Kassuba
6, 2015-01-29 29, 2015Hi karthi,
You can set the layer visibility in the Layer Navigation pane on the left side.
Thanks,
Lori
karthi
1, 2015-01-28 28, 2015How to Sets the viewing intent of the OCG?
Thom Parker
7, 2014-09-16 16, 2014Giovanni,
Please look up the “addWatermarkFromFile” functions in the Acrobat JavaScript Reference. This function applies a PDF page as the watermark. This is one way to cover an entire page with the watermark. Be sure to look at the parameters for controlling the geometry of the applied watermark.
Giovanni
5, 2014-09-16 16, 2014Dear Thom, thanks for the tutorial it is very helpful indeed.
I also would like to ask you one question, I have read in other forums that it is possible to apply a watermark that covers the entire page, I’d be very grateful if you could explain briefly how to do that.
Thanks!
Thom Parker
4, 2014-09-10 10, 2014Hello Heath,
Here’s an article on popup menus
http://acrobatusers.com/tutorials/popup-menus-acrobat
Of course, the trick is generating the array that’s the input to the menu. Here’s a short bit of code that will help
var aOCGs = this.getOCGs();
if(aOCGs)
{
var aMenu = aOCGs.map(function(a){return a.name});
var cRtn = app.popUpMenu.apply(app,aMenu);
switch(cRtn)
{ ... Switch stuff for your specific operation ...}
}
Heath
7, 2014-09-09 09, 2014This was an awesome tutorial, thanks! How can apply the same but using a drop down menu?
Thom Parker
6, 2014-07-28 28, 2014Sue and Peter -
The code is correct, but it is possible that it is not being executed properly. Make sure the console window is empty before pasting the script into it. The select all of the code and press “Ctrl Enter”
Another possibility is that a special character got copied over, witch might cause a syntax error you can’t see. Hence the empty exception message. (Syntax error messages usually include the offending character)
Sue Mullen
5, 2014-07-28 28, 2014Hi Thom, I get the same error that Peter got. Do you have a fix for this?
Peter
6, 2014-06-17 17, 2014Hi Thom,
Thanks for the great service here! I’m really loving the site in general! I pasted your function directly into the JS Console, and here’s what I get:
function FindOCG(cName) {
var aOCGs = this.getOCGs();
for(var i=0; aOCGs && i<aOCGs.length;i++) {
if(aOCGs[i].name == cName) return aOCGs[i];
}
return null;
}
SyntaxError: syntax error
1:Console:Exec
undefined
Any tips on how I can fix this?
Kind regards,
Peter Hoeft
Thom Parker
7, 2014-05-06 06, 2014Hello Paul,
OCG layers are not interactive. You can actually put a script on a layer. But the script is only run when the layer state changes, not on clicks or other user actions.
But, you could put an invisible button over a piece of artwork, and then use the MouseUp event on the button.
Paul
1, 2014-05-03 03, 2014Hi Thom—
Is there any way to do hit tests on the artwork within layers? Can layers receive Mouse Up events? In other words, say I create a layer out of a single vector line; now I want to get a mouse click event when the user clicks the line (but not the empty space around it).
Any tips?
thx
PP
Comments for this tutorial are now closed.