Sesuaikan Bentuk Presentasi dalam JavaScript
Gambaran Umum
Artikel ini menjelaskan cara menyesuaikan bentuk presentasi di Aspose.Slides dengan mengedit geometri bentuk melalui titik edit dan jalur geometri. Artikel ini menunjukkan cara bekerja dengan GeometryPath untuk memodifikasi bentuk yang ada, melakukan operasi pengeditan jalur dasar, menambah atau menghapus titik, dan menerapkan geometri yang diperbarui kembali ke sebuah bentuk.
Artikel ini juga menunjukkan cara membuat bentuk kustom dan komposit, membangun bentuk dengan sudut melengkung, menentukan apakah geometri bentuk tertutup, memeriksa elemen bentuk, dan mengonversi kontur teks Java AWT menjadi jalur geometri.
Ubah Bentuk dengan Titik Edit
Di PowerPoint, Anda dapat menggunakan Edit Points untuk memodifikasi sebuah persegi:
- Pindahkan sudut ke dalam atau ke luar.
- Sesuaikan kelengkungan pada suatu titik.
- Tambahkan titik baru.
Mengedit titik memungkinkan Anda mengubah kontur sebuah bentuk atau menggunakan bentuk yang ada sebagai dasar untuk bentuk baru.
Tips Pengeditan Bentuk

Saat mengedit bentuk PowerPoint, ingatlah konsep-konsep berikut:
- Sebuah bentuk (atau jalurnya) dapat berupa tertutup atau terbuka.
- Jalur sebuah bentuk terdiri dari titik jangkar yang dihubungkan oleh segmen.
- Sebuah segmen dapat lurus atau melengkung. Titik jangkar dan pegangan kontrol menentukan bentuknya.
- Titik jangkar ada sebagai titik sudut, titik lurus, atau titik halus:
- Pada titik sudut, segmen yang bersebelahan dapat bertemu pada sudut.
- Pada titik halus, kedua pegangan kontrol sejajar dan berjarak sama dari titik jangkar.
- Pada titik lurus, kedua pegangan kontrol sejajar tetapi dapat memiliki jarak yang berbeda dari titik jangkar.
- Memindahkan titik jangkar atau menyesuaikan pegangannya mengubah kontur bentuk.
Untuk mengedit bentuk PowerPoint melalui titik edit, Aspose.Slides menyediakan kelas GeometryPath.
- Sebuah instance GeometryPath mewakili jalur geometri dari objek GeometryShape.
- Untuk mengambil GeometryPath dari instance GeometryShape, Anda dapat menggunakan metode GeometryShape.getGeometryPaths.
- Untuk mengatur GeometryPath untuk sebuah bentuk, Anda dapat menggunakan metode berikut: GeometryShape.setGeometryPath untuk bentuk dengan satu jalur dan GeometryShape.setGeometryPaths untuk bentuk dengan banyak jalur.
- Untuk menambahkan segmen, Anda dapat menggunakan metode di bawah GeometryPath.
- Dengan menggunakan metode GeometryPath.setStroke dan GeometryPath.setFillMode, Anda dapat mengatur tampilan untuk jalur geometri.
- Dengan menggunakan metode GeometryPath.getPathData, Anda dapat mengambil jalur geometri dari sebuah GeometryShape sebagai array segmen jalur.
- Untuk mengakses opsi penyesuaian geometri bentuk tambahan, Anda dapat membaca sebuah java.awt.Shape melalui PathIteratornya dan memutar ulang segmen pada sebuah GeometryPath.
Operasi Pengeditan Sederhana
Gunakan metode berikut untuk mengedit jalur geometri. Overload yang menerima indeks akan menyisipkan segmen pada posisi berbasis nol dalam array segmen jalur.
| Operation | Method |
|---|---|
| Menambahkan atau menyisipkan garis lurus. | GeometryPath.lineTo |
| Menambahkan atau menyisipkan kurva Bézier kubik dengan dua titik kontrol dan satu titik akhir. | GeometryPath.cubicBezierTo |
| Menambahkan atau menyisipkan kurva Bézier kuadratik dengan satu titik kontrol dan satu titik akhir. | GeometryPath.quadraticBezierTo |
| Menambahkan sebuah busur elips dengan dimensi dan sudut yang ditentukan dalam derajat. | GeometryPath.arcTo |
| Menutup gambar saat ini dengan menghubungkan titik akhirnya ke titik awal. | GeometryPath.closeFigure |
| Mengatur titik awal sebuah gambar. | GeometryPath.moveTo |
| Menghapus segmen pada indeks berbasis nol. | GeometryPath.removeAt |
Menambahkan Titik Kustom ke Bentuk
Contoh ini menyisipkan dua titik ke dalam bentuk persegi panjang menggunakan GeometryPath.lineTo dan menerapkan jalur yang diedit dengan GeometryShape.setGeometryPath. Koordinat tersebut bersifat lokal terhadap bentuk: kedua titik baru berada di tengahnya, 100 poin dari kiri dan 50 poin dari atas. Indeks segmen 1 dan 4 menempatkannya pada tepi atas dan bawah, menarik tepi tersebut ke dalam.
const slides = require("aspose.slides.via.java");
const presentation = new slides.Presentation();
try {
const slide = presentation.getSlides().get_Item(0);
const shape = slide.getShapes().addAutoShape(slides.ShapeType.Rectangle, 100, 100, 200, 100);
const geometryPath = shape.getGeometryPaths()[0];
geometryPath.lineTo(100, 50, 1);
geometryPath.lineTo(100, 50, 4);
shape.setGeometryPath(geometryPath);
} finally {
presentation.dispose();
}

Menghapus Titik dari Bentuk
Contoh ini mengubah kontur berbentuk hati dengan menghapus segmen pada indeks berbasis nol 2 menggunakan GeometryPath.removeAt. Menerapkan jalur yang dimodifikasi dengan GeometryShape.setGeometryPath memperbarui kontur bentuk.
const slides = require("aspose.slides.via.java");
const presentation = new slides.Presentation();
try {
const slide = presentation.getSlides().get_Item(0);
const shape = slide.getShapes().addAutoShape(slides.ShapeType.Heart, 100, 100, 300, 300);
const path = shape.getGeometryPaths()[0];
path.removeAt(2);
shape.setGeometryPath(path);
} finally {
presentation.dispose();
}

Membuat Bentuk Kustom
Contoh ini membuat bintang lima sudut dengan GeometryPath. Radius luar dan dalam yang bergantian sebesar 100 dan 50 poin menentukan ujung dan lekuk; langkah 72 derajat menempatkan lima ujung secara merata. Jalur ditutup dengan GeometryPath.closeFigure dan diterapkan ke bentuk persegi panjang menggunakan GeometryShape.setGeometryPath, menggantikan konturnya.
const slides = require("aspose.slides.via.java");
const java = require("java");
const points = [];
const outerRadius = 100;
const innerRadius = 50;
const angleStep = 72;
for (let angle = -90; angle < 270; angle += angleStep) {
let radians = angle * Math.PI / 180;
points.push({ x: outerRadius * Math.cos(radians) + outerRadius, y: outerRadius * Math.sin(radians) + outerRadius });
radians = (angle + angleStep / 2) * Math.PI / 180;
points.push({ x: innerRadius * Math.cos(radians) + outerRadius, y: innerRadius * Math.sin(radians) + outerRadius });
}
const starPath = new slides.GeometryPath();
starPath.moveTo(java.newFloat(points[0].x), java.newFloat(points[0].y));
for (let i = 1; i < points.length; i++) {
starPath.lineTo(java.newFloat(points[i].x), java.newFloat(points[i].y));
}
starPath.closeFigure();
const presentation = new slides.Presentation();
try {
const slide = presentation.getSlides().get_Item(0);
const shape = slide.getShapes().addAutoShape(slides.ShapeType.Rectangle, 100, 100, outerRadius * 2, outerRadius * 2);
shape.setGeometryPath(starPath);
} finally {
presentation.dispose();
}

Membuat Bentuk Kustom Komposit
Contoh ini mendefinisikan dua objek GeometryPath tertutup untuk sepertiga atas dan bawah sebuah bentuk. Menerapkan kedua jalur dengan GeometryShape.setGeometryPaths membuat satu bentuk komposit dengan celah di sepertiga tengahnya.
const slides = require("aspose.slides.via.java");
const java = require("java");
const presentation = new slides.Presentation();
try {
const slide = presentation.getSlides().get_Item(0);
const shape = slide.getShapes().addAutoShape(slides.ShapeType.Rectangle, 100, 100, 200, 100);
const topPath = new slides.GeometryPath();
topPath.moveTo(0, 0);
topPath.lineTo(shape.getWidth(), 0);
topPath.lineTo(shape.getWidth(), java.newFloat(shape.getHeight() / 3));
topPath.lineTo(0, java.newFloat(shape.getHeight() / 3));
topPath.closeFigure();
const bottomPath = new slides.GeometryPath();
bottomPath.moveTo(0, java.newFloat(shape.getHeight() / 3 * 2));
bottomPath.lineTo(shape.getWidth(), java.newFloat(shape.getHeight() / 3 * 2));
bottomPath.lineTo(shape.getWidth(), shape.getHeight());
bottomPath.lineTo(0, shape.getHeight());
bottomPath.closeFigure();
const paths = java.newArray("com.aspose.slides.GeometryPath", [topPath, bottomPath]);
shape.setGeometryPaths(paths);
} finally {
presentation.dispose();
}

Membuat Bentuk Kustom dengan Sudut Melengkung
Contoh ini menggabungkan segmen lurus dengan GeometryPath.arcTo untuk membuat bentuk dengan sudut melengkung ke dalam. Setiap ukuran sudut menentukan lebar dan tinggi busur dalam poin, dan sapuan -90 derajat menggambar seperempat elips berlawanan arah jarum jam. Jalur yang selesai diterapkan dengan GeometryShape.setGeometryPath, dan presentasi disimpan dalam format PPTX.
const slides = require("aspose.slides.via.java");
const shapeX = 20;
const shapeY = 20;
const shapeWidth = 300;
const shapeHeight = 200;
const leftTopSize = 50;
const rightTopSize = 20;
const rightBottomSize = 40;
const leftBottomSize = 10;
const presentation = new slides.Presentation();
try {
const slide = presentation.getSlides().get_Item(0);
const shape = slide.getShapes().addAutoShape(slides.ShapeType.Custom, shapeX, shapeY, shapeWidth, shapeHeight);
const geometryPath = new slides.GeometryPath();
geometryPath.moveTo(leftTopSize, 0);
geometryPath.lineTo(shapeWidth - rightTopSize, 0);
geometryPath.arcTo(rightTopSize, rightTopSize, 180, -90);
geometryPath.lineTo(shapeWidth, shapeHeight - rightBottomSize);
geometryPath.arcTo(rightBottomSize, rightBottomSize, -90, -90);
geometryPath.lineTo(leftBottomSize, shapeHeight);
geometryPath.arcTo(leftBottomSize, leftBottomSize, 0, -90);
geometryPath.lineTo(0, leftTopSize);
geometryPath.arcTo(leftTopSize, leftTopSize, 90, -90);
geometryPath.closeFigure();
shape.setGeometryPath(geometryPath);
presentation.save("output.pptx", slides.SaveFormat.Pptx);
} finally {
presentation.dispose();
}
Menentukan Apakah Geometri Bentuk Tertutup
Pembantu berikut memeriksa apakah setiap jalur geometri yang tidak kosong berakhir dengan segmen penutup. Ia membaca GeometryPath.getPathData dan membandingkan perintah segmen akhir PathSegment.getPathCommand dengan PathCommandType.Close. Ia mengembalikan false ketika tidak ada jalur yang tidak kosong. Pemeriksaan ini memeriksa perintah akhir setiap jalur; tidak memeriksa setiap subgambar dalam sebuah jalur. Contoh mencetak true untuk sebuah persegi panjang.
const slides = require("aspose.slides.via.java");
function isGeometryClosed(geometryShape) {
let hasNonemptyPath = false;
for (const geometryPath of geometryShape.getGeometryPaths()) {
const segments = geometryPath.getPathData();
if (segments.length === 0) {
continue;
}
hasNonemptyPath = true;
const lastSegment = segments[segments.length - 1];
if (lastSegment.getPathCommand() !== slides.PathCommandType.Close) {
return false;
}
}
return hasNonemptyPath;
}
const presentation = new slides.Presentation();
try {
const slide = presentation.getSlides().get_Item(0);
const shape = slide.getShapes().addAutoShape(slides.ShapeType.Rectangle, 100, 100, 200, 100);
const closed = isGeometryClosed(shape);
console.log(closed);
} finally {
presentation.dispose();
}
Ekstrak dan Periksa Elemen Bentuk
Gunakan GeometryShape.createShapeElements untuk memeriksa sebuah bentuk yang ada sebagai elemen yang berisi titik jalur dan jenis titik. Gunakan setiap ShapeElement yang dikembalikan untuk mengambil array titik dan tipe melalui metode getPathPoints dan getPathTypes. Representasi ini berguna untuk analisis kontur atau mengirim geometri ke alat gambar kustom.
Contoh ini membuka input.pptx, menemukan bentuk geometri pertama langsung pada slide pertama, dan mencetak segmen jalurnya. Gunakan presentasi yang berisi bentuk dengan segmen lurus dan melengkung untuk melihat kedua jenis output. Ia tidak mencari di dalam grup.
const slides = require("aspose.slides.via.java");
const java = require("java");
const presentation = new slides.Presentation("input.pptx");
try {
const slide = presentation.getSlides().get_Item(0);
let shape = null;
for (let index = 0; index < slide.getShapes().size(); index++) {
const candidate = slide.getShapes().get_Item(index);
if (java.instanceOf(candidate, "com.aspose.slides.GeometryShape")) {
shape = candidate;
break;
}
}
if (shape == null) {
console.log("No geometry shape found on the first slide.");
} else {
for (const shapeElement of shape.createShapeElements()) {
const points = shapeElement.getPathPoints();
const types = shapeElement.getPathTypes();
console.log("Shape element:");
for (let i = 0; i < points.length; i++) {
const pointType = types[i] & 0x07; // Pertahankan tipe segmen, kecuali flag.
switch (pointType) {
case 0:
console.log("Start figure at " + points[i]);
break;
case 1:
console.log("Line to " + points[i]);
break;
case 3:
console.log("Cubic Bezier: controls " + points[i] + ", " + points[i + 1] + "; end " + points[i + 2]);
i += 2; // Consume both control points and the endpoint.
break;
}
if ((types[i] & 0x80) != 0) {
console.log("Close subpath back to its starting point.");
}
}
}
}
} finally {
presentation.dispose();
}
Array berkorespondensi berdasarkan indeks: points[i] adalah sebuah titik dan types[i] menggambarkan perannya. Tipe 0 memulai sebuah gambar, dan tipe 1 menggambar garis dari titik sebelumnya ke titik saat ini. Segmen Bézier kubik dimulai pada titik akhir sebelumnya dan menggunakan tiga entri tipe-3 berurutan: dua titik kontrol diikuti oleh titik akhir baru. Loop mengkonsumsi ketiga entri tersebut sekaligus dan memeriksa titik akhir untuk penutupan.
Jenis titik juga mengandung flag. Mask dengan 0x07 untuk mengidentifikasi tipe segmen, dan uji 0x80 secara terpisah untuk mendeteksi subpath tertutup. Misalnya, 129 (0x81) berarti titik akhir garis yang menutup subpath, dan 131 (0x83) berarti titik akhir Bézier yang menutup satu. Java menyimpan flag ini dalam byte bertanda; masking mempertahankan nilai bit yang dimaksud. Membandingkan nilai mentah hanya dengan 1 atau 3 akan melewatkan kasus ini. Flag lain, seperti dash (0x10) dan marker (0x20), tidak mengubah tipe segmen dasar.
Koordinat dan transformasi. Titik diukur dalam poin (1/72 inci), dengan X meningkat ke kanan dan Y meningkat ke bawah. Untuk bentuk yang tidak dikelompokkan, koordinat yang diekstrak sudah mencakup posisi yang dikembalikan oleh getX dan getY serta mencerminkan lebar dan tinggi saat ini. Misalnya, sebuah persegi panjang tidak diputar pada (100, 200) dengan ukuran 120 × 80 memiliki batas kontur (100, 200)–(220, 280). Jangan menambahkan posisi bentuk lagi. Kurangi X dan Y-nya untuk memperoleh koordinat relatif terhadap bingkai yang tidak diputar.
Titik yang diekstrak tidak menerapkan rotasi bentuk, yang dikembalikan oleh getRotation, atau pembalikan horizontal dan vertikal. Untuk mereproduksi kontur yang ditampilkan, terapkan transformasi tersebut di sekitar pusat bentuk. Untuk bentuk yang dikelompokkan, perhitungkan juga pemetaan koordinat grup dan transformasinya; jangan mengasumsikan bahwa titik yang diekstrak adalah koordinat slide yang ter-render akhir atau menerapkan translasi atau skala dua kali jika sudah tercermin dalam bingkai anak.
Inspeksi vs pengeditan. Array yang diekstrak menggambarkan kontur; mengubahnya tidak memperbarui bentuk asli. Pilih pendekatan ini ketika analisis atau kode gambar Anda memerlukan array titik/tipe. Gunakan getGeometryPaths ketika Anda membutuhkan perintah geometri dalam sistem koordinat lokal bentuk atau ingin mengedit geometri tersebut. Terapkan jalur yang diedit melalui setGeometryPath atau setGeometryPaths.
Mengonversi Shape Java AWT ke GeometryPath
Contoh ini menggabungkan kontur persegi panjang dengan teks yang dikonversi menjadi geometri. Metode setFillMode pada kontur menonaktifkan isinya. Sebuah GlyphVector membuat kontur teks dalam sebuah java.awt.Shape. PathIterator‑nya menyediakan segmen move, line, quadratic, cubic, dan closing, yang contoh ini memutar ulang pada sebuah GeometryPath.
Jembatan Java menggunakan nilai float dan byte eksplisit untuk parameter Java yang bersesuaian. Iterator menulis koordinat ke dalam array float Java; refleksi membaca nilai yang diperbarui kembali ke JavaScript. Teks menggunakan font Arial 40 poin. Kontur dipindahkan 20 poin secara horizontal dan diposisikan dengan bagian atas visualnya 10 poin di bawah tepi atas bentuk. Jalur teks diisi, sementara persegi panjang asli tetap menjadi kontur. Menerapkan kedua jalur dengan GeometryShape.setGeometryPaths menghasilkan satu bentuk yang berisi persegi panjang dan teks.
const slides = require("aspose.slides.via.java");
const java = require("java");
const presentation = new slides.Presentation();
try {
const slide = presentation.getSlides().get_Item(0);
const shape = slide.getShapes().addAutoShape(slides.ShapeType.Rectangle, 100, 100, 300, 100);
const originalPath = shape.getGeometryPaths()[0];
originalPath.setFillMode(java.newByte(slides.PathFillModeType.None));
const font = java.newInstanceSync("java.awt.Font", "Arial", java.getStaticFieldValue("java.awt.Font", "PLAIN"), 40);
const image = java.newInstanceSync("java.awt.image.BufferedImage", 100, 100, java.getStaticFieldValue("java.awt.image.BufferedImage", "TYPE_INT_ARGB"));
const graphics = image.createGraphics();
let graphicsPath;
try {
const fontContext = graphics.getFontRenderContext();
const glyphVector = font.createGlyphVector(fontContext, "Text in shape");
const textBounds = glyphVector.getVisualBounds();
const baseline = java.newFloat(-textBounds.getY() + 10);
graphicsPath = glyphVector.getOutline(java.newFloat(20), baseline);
} finally {
graphics.dispose();
}
const textPath = new slides.GeometryPath();
const pathIterator = graphicsPath.getPathIterator(null);
const coordinates = java.newArray("float", [0, 0, 0, 0, 0, 0]);
while (!pathIterator.isDone()) {
const segmentType = pathIterator.currentSegment(coordinates);
const points = [];
for (let i = 0; i < 6; i++) {
const coordinate = java.callStaticMethodSync("java.lang.reflect.Array", "getFloat", coordinates, i);
points.push(java.newFloat(coordinate));
}
switch (segmentType) {
case 0: // Pindah ke.
textPath.moveTo(points[0], points[1]);
break;
case 1: // Garis ke.
textPath.lineTo(points[0], points[1]);
break;
case 2: // Kurva Bezier Kuadratik.
textPath.quadraticBezierTo(points[0], points[1], points[2], points[3]);
break;
case 3: // Kurva Bezier Kubik.
textPath.cubicBezierTo(points[0], points[1], points[2], points[3], points[4], points[5]);
break;
case 4: // Tutup gambar.
textPath.closeFigure();
break;
}
pathIterator.next();
}
textPath.setFillMode(java.newByte(slides.PathFillModeType.Normal));
const paths = java.newArray("com.aspose.slides.GeometryPath", [originalPath, textPath]);
shape.setGeometryPaths(paths);
} finally {
presentation.dispose();
}

FAQ
Apa yang terjadi pada isi dan garis luar setelah mengganti geometri?
Gaya tetap melekat pada bentuk; hanya kontur yang berubah. Isi dan garis luar secara otomatis diterapkan pada geometri baru.
Bagaimana cara memutar bentuk kustom secara benar bersama geometri nya?
Gunakan metode setRotation pada bentuk; geometri berputar bersama bentuk karena terikat pada sistem koordinat bentuk itu sendiri.
Apakah saya dapat mengonversi bentuk kustom menjadi gambar untuk “mengunci” hasilnya?
Ya. Ekspor area slide yang diperlukan atau bentuk itu sendiri ke format raster; ini menyederhanakan pekerjaan selanjutnya dengan geometri yang kompleks.