[GastForen Programme Print/Bildbearbeitung Adobe InDesign Skriptwerkstatt Skript: Parallelogramm bzw. Scheren von Textrahmen / Bildrahmen ohne Verzerrung

  • Suche
  • Hilfe
  • Lesezeichen
  • Benutzerliste
Print/Bildbearbeitung - Photos, Layout, Design
Themen
Beiträge
Moderatoren
Letzter Beitrag

Skript: Parallelogramm bzw. Scheren von Textrahmen / Bildrahmen ohne Verzerrung

lowtone
Beiträge gesamt: 149

1. Jun 2016, 13:02
Beitrag # 1 von 8
Bewertung:
(4647 mal gelesen)
URL zum Beitrag
Beitrag als Lesezeichen
Hallo Forum,
ich möchte euch gerne ein Skript zur Verfügung und zur Verbesserung stellen, dass wir letztens für ein Layout entwickelt haben.

AUFGABE: Eine Broschüre hat als Layout-Stilmittel lauter Parallelogramme. Auch Textrahmen und Bildrahmen haben meist diese Form, der Winkel der Seitenkanten soll immer einheitlich sein.

PROBLEM: Sobald man mit dem Scheren-Werkzeug arbeitet, werden Schriften und Bilder verzerrt. Sobald man einen Textrahmen (z. B. wg. Übersatz) in der Höhe / Breite verändert, verändert sich der Winkel der Seitenkanten. Die Punkte von Hand auszurichten ist lästig und unpräzise.

IDEE: Ein Skript fragt den Winkel ab und wendet die Berechnung auf alle markierten Objekte an. Das Skript verschiebt die Eckpunkte der Rahmen, um die gewünschte Form zu erstellen.

Ich habe mich in der Adobe-Beispielssammlung an das Skript “Path Effects“ gehalten und es nach meinen Ansprüchen umgebaut.
Das ist der aktuelle Stand, der recht gut funktioniert, aber sicherlich noch Probleme und Bugs hat oder schlanke programmiert werden könnte!? Ich bin gespannt, wer etwas damit anfangen kann.
Natürlich und würde mich freuen, anhand von Verbesserungsvorschlägen mein Wissen über Skripte zu erweitern.

> Entwickelt und getestet unter InDesign CS6.

Viel Spaß.
Simon


Code
//Parallelogrammjsx 
//An InDesign CS6 JavaScript by Simon Wehr, www.wehrundweissweiler.de
/*
@@@BUILDINFO@@@ Parallelogramm_0104.jsx !Version! Wed Jun 01 2016 12:47:01 GMT+0200
*/
//Parallelogramm: Makes a parallelogramm with a defined angle
///
main();

function main() {
//Make certain that user interaction (display of dialogs, etc.) is turned on.
app.scriptPreferences.userInteractionLevel = UserInteractionLevels.interactWithAll;
var myObjectList = new Array;
if (app.documents.length != 0) {
if (app.selection.length != 0) {

// check selected objects wether they are TextFrame, Rectangle or Polygon
for (var myCounter = 0; myCounter < app.selection.length; myCounter++) {
switch (app.selection[myCounter].constructor.name) {
case "TextFrame":
case "Rectangle":
case "Polygon":
myObjectList.push(app.selection[myCounter]);
break;
}
}

if (myObjectList.length != 0) {
myDisplayDialog(myObjectList);
} else {
alert("Please select a rectangle or text frame and try again.");
}
} else {
alert("Please select an object and try again.");
}
} else {
alert("Please open a document, select an object, and try again.");
}
}

// open the dialog where to enter the angle
function myDisplayDialog(myObjectList) {
myDialog = app.dialogs.add({
name: "Parallelogramm"
});
with(myDialog) {
with(dialogColumns.add()) {

staticTexts.add({
staticLabel: "Winkel:"
});
with(dialogColumns.add()) {
var myAngleEditbox = angleEditboxes.add({
editValue: 10
});
}
}
}
var myReturn = myDialog.show();
if (myReturn == true) {
//Get the values from the dialog box.
var myAngle = myAngleEditbox.editValue;
myDialog.destroy();
myParallelogram(myObjectList, myAngle);
} else {
myDialog.destroy();
}
}

function myParallelogram(myObjectList, myAngle) {

for (var myObjectCounter = 0; myObjectCounter < myObjectList.length; myObjectCounter++) {
// collect the values of the selected object
var myObject = myObjectList[myObjectCounter];
var myBounds = myObject.geometricBounds;
var myHeight = myBounds[2] - myBounds[0];
var myWidth = myBounds[3] - myBounds[1];

// calculate the angle
var Pi = 3.14159;
var myRadAngle = myAngle * Pi / 180;
var myOffset = myHeight * (Math.tan(myRadAngle));

var myPath = myObject.paths.item(0);
var myPathPointTR = myPath.pathPoints.item(3); // Get the Top Right Anchor
var myTRAnchorX = myPathPointTR.anchor[0]; // Get TR Anchor X Value
var myPathPointBR = myPath.pathPoints.item(2); // Get the Bottom Right Anchor
var myBRAnchorX = myPathPointBR.anchor[0]; // Get BR Anchor X Value
if (myTRAnchorX == myBRAnchorX) {
/*
If the original shape is rectangular, the width of the slant will be added. (Only the first time)
*/
var myNewPointArray = new Array(4);
myNewPointArray[0] = [myBounds[1] + myOffset, myBounds[0]];
myNewPointArray[1] = [myBounds[1], myBounds[2]];
myNewPointArray[2] = [myBounds[3], myBounds[2]];
myNewPointArray[3] = [myBounds[3] + myOffset, myBounds[0]];
} else {
/*
If the original form already is a parallelogram, the width of the slant will be included. This way the object is prevented from growing in width due to repeated execution of the script.
*/
var myNewPointArray = new Array(4);
// if the angle is positive
if (myOffset >= 0) {
myNewPointArray[0] = [myBounds[1] + myOffset, myBounds[0]];
myNewPointArray[1] = [myBounds[1], myBounds[2]];
myNewPointArray[2] = [myBounds[3] - myOffset, myBounds[2]];
myNewPointArray[3] = [myBounds[3], myBounds[0]];
}
// if the angle is negative
if (myOffset < 0) {
myNewPointArray[0] = [myBounds[1], myBounds[0]];
myNewPointArray[1] = [myBounds[1] - myOffset, myBounds[2]];
myNewPointArray[2] = [myBounds[3], myBounds[2]];
myNewPointArray[3] = [myBounds[3] + myOffset, myBounds[0]];
}
}

// set the anchor points of the selected object to the above calculated values
myObject.paths.item(0).entirePath = myNewPointArray;
}
}

X

Skript: Parallelogramm bzw. Scheren von Textrahmen / Bildrahmen ohne Verzerrung

Hans Haesler
  
Beiträge gesamt: 5826

2. Jun 2016, 09:27
Beitrag # 2 von 8
Beitrag ID: #550079
Bewertung:
(4541 mal gelesen)
URL zum Beitrag
Beitrag als Lesezeichen
Hallo Simon,

besten Dank für Deinen Beitrag.

Ich habe das Script kurz ausprobiert. Es funktioniert wie erwartet.

Aber 1: Wenn ein Objekt mehr als vier Ecken hat, wird es in ein Viereck verwandelt.
Also entweder den Fall "Polygon" nicht behandeln oder das Script erweitern.

Aber 2: Wenn einem Rahmen ein Drehwinkel zugewiesen ist (z.B. 10°), dann ist das Ergebnis nicht in Ordnung.
Abhilfe: Zuerst den Drehwinkel speichern, vorübergehend auf 0° setzen, nach dem Umwandeln den Drehwinkel wieder zuweisen.

[ Ach ja ... ich hätte vor dreissig Jahren solch ein Script gebrauchen können. In einer Zeitschrift wurde ein Projekt vorgestellt. Und ich hatte die Idee, die Texte der Opposition so schräge darzustellen. Doch das war mit einem Harris-Satzsystem. Da war keine Winkelangabe möglich. Ich musste mir mit den Einzügen behelfen: z.B. erste Zeile vorne 30 mm und hinten 0 mm; letzte Zeile 0 mm und –30 mm. Dazwischen eine automatische Anpassung. Bei einer anderen Zeilenanzahl mussten andere Werte eingegeben werden, um denselben Winkel zu bekommen ... ]

Gruss, Hans


als Antwort auf: [#550052]

Skript: Parallelogramm bzw. Scheren von Textrahmen / Bildrahmen ohne Verzerrung

lowtone
Beiträge gesamt: 149

2. Jun 2016, 10:00
Beitrag # 3 von 8
Beitrag ID: #550081
Bewertung:
(4525 mal gelesen)
URL zum Beitrag
Beitrag als Lesezeichen
Hallo Hans,
das mit dem Drehwinkel behalte ich mal im Hinterkopf. Momentan habe ich keinen Bedarf das einzupflegen, aber es klingt nach einer sinnvollen Erweiterung.

Zum Polygon: Ja, hier ist in der Tat das Verhalten etwas unsauber. Zum einen habe ich das Skript Parallelogramm genannt, von daher hat das Polygon eben Pech! ;-) Aber ich habe das Polygon aus Gründen eingebunden und vllt. kann mir hier auch jemand helfen:
Ursprünglich hatte ich nur »Textframe« und »Rectangle« zugelassen.
ABER: Wenn ich einen Rechteckrahmen mit einem Bild fülle (aka ein Bild platziere) habe ich ein »Rectangle« als Constructor Name. Wende ich nun das Skript an, wird daraus ein »Polygon« und ich kann das Skript nicht erneut anwenden, weil Polygone nicht zugelassen werden.
Gibt es dafür eine Lösung?

Aktuell könnte man das Skript natürlich so anpassen, dass es bei einem Polygon die Ecken zählt und Wenn Ecken > 4 eine Warnmeldung ausgibt / nicht bearbeitet. Wenn ich aber ein viereckiges, unregelmäßiges Polygon anwähle, wird es ja auch zu einem Parallelogramm umgeformt, also müsste man da eigentlich auch warnen …
Eigentlich müsste man Polygone folglich gar nicht behandeln, aber dann habe ich wieder das Problem von oben … Hmpf.
Was nun?

Beste Güße
Simon

PS: Die Geschichte vom Harris-Satzsystem klingt abenteuerlich, Hans.


als Antwort auf: [#550079]

Skript: Parallelogramm bzw. Scheren von Textrahmen / Bildrahmen ohne Verzerrung

Hans Haesler
  
Beiträge gesamt: 5826

2. Jun 2016, 11:18
Beitrag # 4 von 8
Beitrag ID: #550090
Bewertung:
(4478 mal gelesen)
URL zum Beitrag
Beitrag als Lesezeichen
Hallo Simon,

als Abhilfe für das Drehwinkel-Problem könnten die folgenden Zeilen eingefügt werden.
Und zwar bevor die 'geometricBounds' erfasst werden.

Code
	var myAngle = myObject.rotationAngle; 
var myRestoreAngle = false;
if (myAngle%90 != 0) {
myObject.rotationAngle = 0;
myRestoreAngle = true;
}

Und am Ende die Wiederherstellung, falls notwendig (wenn die "Flagge" 'myRestoreAngle' den Wert 'true' hat):

Code
	if (myRestoreAngle) { 
myObject.rotationAngle = myAngle;
}

Das Erweitern, um Polygone korrekter zu behandeln, wird schwieriger sein.
Aber ich bin mir fast sicher, dass sich schon einer dahintergesetzt hat. :-)

Gruss, Hans


als Antwort auf: [#550081]

Skript: Parallelogramm bzw. Scheren von Textrahmen / Bildrahmen ohne Verzerrung

lowtone
Beiträge gesamt: 149

2. Jun 2016, 11:26
Beitrag # 5 von 8
Beitrag ID: #550093
Bewertung:
(4472 mal gelesen)
URL zum Beitrag
Beitrag als Lesezeichen
Hallo Hans,
besten Dank für die Ergänzung.
Code
if (myAngle%90 != 0) {  
myObject.rotationAngle = 0;
myRestoreAngle = true;
}


Einen Moment habe ich gebraucht, um die Modulo-Gechichte zu kapieren. Aber das ist clever um in einem Aufwasch auch 90°, 180°, 270° und 360° (gibt es nicht, oder?) abzufangen, richtig? Wieder was gelernt …
Beste Grüße
Simon


als Antwort auf: [#550090]

Skript: Parallelogramm bzw. Scheren von Textrahmen / Bildrahmen ohne Verzerrung

lowtone
Beiträge gesamt: 149

2. Jun 2016, 11:47
Beitrag # 6 von 8
Beitrag ID: #550094
Bewertung:
(4464 mal gelesen)
URL zum Beitrag
Beitrag als Lesezeichen
Ha, da habe ich einen Moment gebraucht … Du hast die Variable myAngle genannt, die bereits für den Winkel der Seitenkanten belegt war. Das kann natürlich nur zu Fehlern führen ;-)
Ich habe sie in myRotation geändert, jetzt läuft’s prima.

Also dann:
Code
//Parallelogramm.jsx 
//An InDesign CS6 JavaScript by Simon Wehr, www.wehrundweissweiler.de
/*
@@@BUILDINFO@@@ Parallelogramm_0105.jsx !Version! Thu Jun 02 2016 11:30:37 GMT+0200
*/
//Parallelogramm: Makes a parallelogramm with a defined angle
///
main();

function main() {
//Make certain that user interaction (display of dialogs, etc.) is turned on.
app.scriptPreferences.userInteractionLevel = UserInteractionLevels.interactWithAll;
var myObjectList = new Array;
if (app.documents.length != 0) {
if (app.selection.length != 0) {

// check selected objects wether they are TextFrame, Rectangle or Polygon
for (var myCounter = 0; myCounter < app.selection.length; myCounter++) {
switch (app.selection[myCounter].constructor.name) {
case "TextFrame":
case "Rectangle":
case "Polygon":
myObjectList.push(app.selection[myCounter]);
break;
}
}

if (myObjectList.length != 0) {
myDisplayDialog(myObjectList);
} else {
alert("Please select a rectangle or text frame and try again.");
}
} else {
alert("Please select an object and try again.");
}
} else {
alert("Please open a document, select an object, and try again.");
}
}

// open the dialog where to enter the angle
function myDisplayDialog(myObjectList) {
myDialog = app.dialogs.add({
name: "Parallelogramm"
});
with(myDialog) {
with(dialogColumns.add()) {

staticTexts.add({
staticLabel: "Winkel:"
});
with(dialogColumns.add()) {
var myAngleEditbox = angleEditboxes.add({
editValue: 10
});
}
}
}
var myReturn = myDialog.show();
if (myReturn == true) {
//Get the values from the dialog box.
var myAngle = myAngleEditbox.editValue;
myDialog.destroy();
myParallelogram(myObjectList, myAngle);
} else {
myDialog.destroy();
}
}

function myParallelogram(myObjectList, myAngle) {

for (var myObjectCounter = 0; myObjectCounter < myObjectList.length; myObjectCounter++) {
// collect the values of the selected object
var myObject = myObjectList[myObjectCounter];

// get myObject’s rotation angle and save it. Set myObject’s rotation angle to 0 for further processing – it will be restored later.
var myObjectRotation = myObject.rotationAngle;
var myRestoreRotation = false;
if (myObjectRotation%90 != 0) {
myObject.rotationAngle = 0;
myRestoreRotation = true;
}

var myBounds = myObject.geometricBounds;
var myHeight = myBounds[2] - myBounds[0];
var myWidth = myBounds[3] - myBounds[1];

// calculate the offset according to the slant’s angle
var Pi = 3.14159;
var myRadAngle = myAngle * Pi / 180;
var myOffset = myHeight * (Math.tan(myRadAngle));

var myPath = myObject.paths.item(0);
var myPathPointTR = myPath.pathPoints.item(3); // Get the Top Right Anchor
var myTRAnchorX = myPathPointTR.anchor[0]; // Get TR Anchor X Value
var myPathPointBR = myPath.pathPoints.item(2); // Get the Bottom Right Anchor
var myBRAnchorX = myPathPointBR.anchor[0]; // Get BR Anchor X Value
if (myTRAnchorX == myBRAnchorX) {
/*
If the original shape is rectangular, the width of the slant will be added. (Only the first time)
*/
var myNewPointArray = new Array(4);
myNewPointArray[0] = [myBounds[1] + myOffset, myBounds[0]];
myNewPointArray[1] = [myBounds[1], myBounds[2]];
myNewPointArray[2] = [myBounds[3], myBounds[2]];
myNewPointArray[3] = [myBounds[3] + myOffset, myBounds[0]];
} else {
/*
If the original form already is a parallelogram, the width of the slant will be included. This way the object is prevented from growing in width due to repeated execution of the script.
*/
var myNewPointArray = new Array(4);
// if the angle is positive
if (myOffset >= 0) {
myNewPointArray[0] = [myBounds[1] + myOffset, myBounds[0]];
myNewPointArray[1] = [myBounds[1], myBounds[2]];
myNewPointArray[2] = [myBounds[3] - myOffset, myBounds[2]];
myNewPointArray[3] = [myBounds[3], myBounds[0]];
}
// if the angle is negative
if (myOffset < 0) {
myNewPointArray[0] = [myBounds[1], myBounds[0]];
myNewPointArray[1] = [myBounds[1] - myOffset, myBounds[2]];
myNewPointArray[2] = [myBounds[3], myBounds[2]];
myNewPointArray[3] = [myBounds[3] + myOffset, myBounds[0]];
}
}

// set the anchor points of the selected object to the above calculated values
myObject.paths.item(0).entirePath = myNewPointArray;
if (myRestoreRotation) {
myObject.rotationAngle = myObjectRotation;
}
}
}



als Antwort auf: [#550090]

Skript: Parallelogramm bzw. Scheren von Textrahmen / Bildrahmen ohne Verzerrung

Hans Haesler
  
Beiträge gesamt: 5826

2. Jun 2016, 12:05
Beitrag # 7 von 8
Beitrag ID: #550097
Bewertung:
(4442 mal gelesen)
URL zum Beitrag
Beitrag als Lesezeichen
Hallo Simon,

Zitat Einen Moment habe ich gebraucht, um die Modulo-Gechichte zu kapieren

Ja, richtig. Dieses Detail hatte ich absichtlich nicht kommentiert.
Denn schliesslich sind wir hier in der Skriptwerkstatt.

Allerdings hatte ich diese Zeilen aus der Erinnerung getippt, ohne sie ausführlich zu testen.

Hätte ich tun sollen. Dann hätte ich auch gemerkt, dass meine Variable 'myAngle' später mit der schon vorhandenen kollidiert.

Man könnte auch ganz einfach jeden Rahmen auf Null drehen ...

Code
  var myObject = myObjectList[myObjectCounter]; 
var myRotation = myObject.rotationAngle;
if (myRotation != 0) {
myObject.rotationAngle = 0;
}

... und dann wieder zurück, falls notwendig:

Code
	if (myRotation != 0) { 
myObject.rotationAngle = myRotation;
}


Gruss, Hans


als Antwort auf: [#550094]

Skript: Parallelogramm bzw. Scheren von Textrahmen / Bildrahmen ohne Verzerrung

lowtone
Beiträge gesamt: 149

2. Jun 2016, 12:42
Beitrag # 8 von 8
Beitrag ID: #550104
Bewertung:
(4407 mal gelesen)
URL zum Beitrag
Beitrag als Lesezeichen
Ja, so hätte ich das gelöst. Aber die Lösung mit Modulo finde ich interessanter, auch für den Lerneffekt für spätere Skripte.


als Antwort auf: [#550097]
X