Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Rotate Keynote Document for use as an app Prototype
// Open Script Editor and Export this as an Application
//
// Then drop a keynote file on it in the Finder and it will properly resize
// and rotate everything so the Keynote file becomes usable as a prototype
// in the iPhone keynote app
// rotateDocument exported function
//
// Accepts a Keynote document and will rotate
// all the slides and elements in the slide 90 degrees
// counterclockwise.
//
// Useful for demoing a Keynote document on an actual device because
// Keynote for iOS is landscape only and will not "play" a document
// in portrait
function rotateDocument(doc) {
height = doc.height()
width = doc.width()
doc.height = width
doc.width = height
rotateSlides(doc)
}
// rotateSlides exported function
//
// Accepts a Keynote document and will rotate
// all the elements in all the slides 90 degrees counterclockwise
function rotateSlides(doc) {
for (j in doc.slides) {
slide = doc.slides[j]
rotateSlide(doc, slide)
}
}
function rotateSlide(doc, slide) {
// When resizing the slide, Keynote tries to still fit
// all the elements in the new size, causing them to shrink.
// The growthFactor controls how much we grow the elements in the slide
// to compensate for that shrinking
growthFactor = 1.777777778
slideHeight = doc.height()
slideWidth = doc.width()
function moveLine(item) {
moveShape(item, false)
}
// moveShape is the workhorse of this script
// It will rotate, move, and resize the element in the slide
//
// The hasTextObject argument is a boolean that specifies whether
// the element passed in can have a textObject. For example,
// a shape can have text (like the text inside of a round rectangle),
// but lines don't have text.
function moveShape(item, hasTextObject) {
position = item.position()
originalX = position.x
originalY = position.y
width = item.width()
height = item.height()
// After rotating 90 degress, the Y axis becomes the X axis
// The yCenterOffset offsets the item from the center of the Y axis
// after it's been rotated
yCenterOffset = Math.round((width / 2 - ((slideWidth / 2) - originalX)) * growthFactor)
originalRotation = item.rotation()
item.rotation = originalRotation + 90
newWidth = width * growthFactor
newHeight = height * growthFactor
item.width = newWidth
item.height = newHeight
if (hasTextObject) {
text = item.objectText
originalSize = text.size()
text.size = originalSize * growthFactor
}
newWidth = item.width()
centerXTarget = (slideHeight / 2) - (newWidth / 2) - yCenterOffset
item.position = $.NSMakePoint(originalY * growthFactor, centerXTarget)
}
function moveText(item) {
moveShape(item, true)
}
function moveImage(item) {
moveLine(item, true)
}
for (i in slide.shapes) {
shape = slide.shapes[i]
moveShape(shape, true)
}
for (i in slide.textItems) {
text = slide.textItems[i]
moveText(text)
}
for (i in slide.lines) {
line = slide.lines[i]
moveLine(line)
}
for (i in slide.images) {
image = slide.images[i]
moveImage(image)
}
}
Keynote = Application("Keynote")
app = Application.currentApplication()
app.includeStandardAdditions = true
function openDocuments(docs) {
firstDoc = docs[0]
doc = Keynote.open(firstDoc)
rotateDocument(doc)
app.displayNotification(firstDoc.toString() + " finished converting")
}
@sirbrillig

This comment has been minimized.

Copy link

sirbrillig commented Aug 1, 2014

This looks like Javascript. Is this the new JS Automation API for Yosemite?

@ericallam

This comment has been minimized.

Copy link
Owner Author

ericallam commented Aug 8, 2014

Yup, it is :)

@jarjoevis23

This comment has been minimized.

Copy link

jarjoevis23 commented Sep 8, 2014

this is not working for me, it isn't letting me compile it, it keeps giving me syntax errors
any help?

@HaoyangLi

This comment has been minimized.

Copy link

HaoyangLi commented Oct 4, 2014

Awesome! It works fine, except for grouped objects. And I used quite a few grouped objects in my keynote prototype...

So I added one for loop at the end of the moveShape function

"
for (i in slide.groups) {
group = slide.groups[i]

moveImage(group)

}
"
Problem solved! :)

Phil

@tomyang

This comment has been minimized.

Copy link

tomyang commented Oct 29, 2014

i got problem on using it, the warning message is "syntax error : a "/" can't go here", can i get help on this, thanks alot!

@werjefelt

This comment has been minimized.

Copy link

werjefelt commented Nov 24, 2014

Same for me. "/" can't go here

@marinlicina

This comment has been minimized.

Copy link

marinlicina commented Dec 7, 2014

For all the people experiencing the - "/" can't go here - problem: Set your language to Java Script (instead of AppleScript which is the default) in top left corner of the Script Editor window, directly below the red dot.

Image here: https://www.evernote.com/shard/s23/sh/444c98b6-1d75-424f-81b0-8f1f19cd4a7a/8e05fa47e5e4dfefd4d24fd5b458dbce/deep/0/Keynote_Rotator_and_Rotate_Keynote_Document_for_use_as_an_app_Prototype.png

@AdulteTerrible

This comment has been minimized.

Copy link

AdulteTerrible commented Dec 25, 2014

Hi Eric, thanks for the script!

Based on it, I made another, starting from a different premise: a copy of the dropped document is made and is rotated. This integrates better in my "tool chain".

A by-product of this approach is that rounding errors (introduced by using a "growthFactor") can be avoided. Have a look: https://github.com/AdulteTerrible/DuplicateAndRotateKeynoteDocumentDroplet/blob/master/Script

@scottdh

This comment has been minimized.

Copy link

scottdh commented Feb 4, 2015

@HaoyangLi - thanks for the suggestion regarding grouped elements! Unfortunately I'm still having problems with text in groups. The group seems to be rotated but the textboxes/text inside isn't resized. Means wherever I have text in groups, the text comes out looking tiny.

Do you have this problem too?

@morgler

This comment has been minimized.

Copy link

morgler commented Feb 11, 2015

Thanks. For me it does not work with objects outside the slide boundaries (e.g. for animating them in) and it does not work for objects on the master slide :(.

@jessemorano

This comment has been minimized.

Copy link

jessemorano commented Feb 18, 2015

The scripts above do not rotate the angles of transitions nor animation paths. For me, that's the whole point of going through all this trouble - to avoid even more trouble in Proto.io (a lovely tool, but much slower for animations generally).
Any ideas for how to rotate transition angles and motion paths??

@pawangiri

This comment has been minimized.

Copy link

pawangiri commented Apr 11, 2015

Works like charm, thanks guys for all the changes.

@dougzilla32

This comment has been minimized.

Copy link

dougzilla32 commented Jun 16, 2015

Excellent workaround! HaoyangLi's suggested patch for grouped objects works for me as well.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.