MENGGUNAKAN JAVASCRIPT
Oleh:
JURUSAN INFORMATIKA
FAKULTAS TEKNIK INDUSTRI
UNIVERSITAS PEMBANGUNAN NASIONAL ”VETERAN”
YOGYAKARTA
2021
HALAMAN PENGESAHAN PRESENTASI
MENGGUNAKAN JAVASCRIPT
Disusun oleh:
KELOMPOK 5
Menyetujui
Dosen Pengampu
ii
KATA PENGANTAR
Puji syukur kami panjatkan kepada Tuhan Yang Maha Esa yang senantiasa
mencurahkan rahmat dan hidayah-Nya sehingga kami dapat menyelesaikan projek akhir
Grafika Komputer beserta laporannya yang berjudul Aplikasi Grafika Komputer
Menggunakan Bahasa Pemrograman Pascal.
Atas perhatian dari semua pihak yang membantu penulisan ini, kami ucapkan
terimakasih. Semoga laporan ini dapat dipergunakan seperlunya.
Penyusun
iii
DAFTAR ISI
HALAMAN PENGESAHAN ii
KATA PENGANTAR iii
BAB 1 TEORI DASAR 1
I.1 Pendahuluan 1
I.2 Sistem Grafika 1
1.2.1 Teknologi Display 1
1.2.2 Raster-Scan System 2
1.2.3 Random-Scan System 2
1.2.4 Peralatan input interaktif 3
I.3 Output Primitif 4
1.3.1 Titik dan Garis 4
1.3.2 Algoritma Pembentukan Garis 5
1.3.3 Algoritma Pembentukan Lingkaran dan Elips 7
1.3.4 Fill Area Primitif 10
I.4 Atribut Output Primitif 11
1.4.1 Atribut Titik 11
1.4.2 Atribut Kurva dan Garis 11
1.4.3 Warna dan Grayscale 12
I.5 Transformasi Dua Dimensi 12
1.5.1 Translasi 12
1.5.2 Rotasi 12
1.5.3 Skala 12
1.5.4 Matriks Transformasi 13
BAB II PERANCANGAN APLIKASI 14
2.1 Perancangan Menu 14
2.2 Perancangan Antar Muka Pengguna 16
BAB III IMPLEMENTASI PROGRAM 17
iv
3.1 Perangkat Keras yang Digunakan 17
3.2 Perangkat Lunak yang Digunakan 17
3.3 Tampilan dan Modul Program 18
3.3.1 Tampilan Program 18
3.3.2 Modul Program 24
BAB IV KESIMPULAN DAN SARAN 44
4.1 Kesimpulan 44
4.2 Saran 44
DAFTAR PUSTAKA 45
v
BAB 1
TEORI DASAR
I.1 Pendahuluan
Grafika komputer adalah bagian dari ilmu komputer yang berhubungan dengan
proses pembuatan maupun manipulasi gambar (visual) secara digital. Grafika komputer
adalah bagian dari ilmu komputer yang berkaitan dengan pembuatan dan manipulasi
gambar (visual) secara digital. Grafika komputer merupakan teknik-teknik dalam ilmu
komputer dan matematika untuk merepresentasikan dan memanipulasi data gambar
menggunakan komputer. Grafika komputer mempunyai bentuk sederhana yaitu grafika
komputer 2D yang selanjutnya dikembangkan menjadi grafika komputer 3D, image
processing atau pemrosesan citra, dan pattern recognition atau pengenalan pola. .Dan
grafik selalu identik dengan gambar yang berbentuk garis contoh seperti gambar persegi,
persegi panjang, segitiga, lingkaran dll.
Pada era perkembangan teknologi yang sangat pesat ini, banyak sekali teknologi
visual berupa gambar yang ditampilkan pada komputer dan diterapkan pada kehidupan
sehari-hari yang dapat ditemui misalnya pada televisi, handphone, koran dll. Selain itu juga
grafika komputer ditemukan pada bidang-bidang kedokteran, perancangan, game, animasi
dan tak terkecuali dalam bidang pendidikan.
Teknologi display merupakan alat alat yang memiliki output berupa video monitor
yang menggunakan sistem perancangan Cathode-Ray Tube (CRT). Cara kerjanya yaitu
menggunakan elektron gun dengan komponen utama yaitu cathode metal dan control grid
yang bisa memancarkannya melalui focusing system dan deflection system sehingga
1
pancaran elektron mengenai layar berupa lapisan fosfor. Intensitas pancaran elektron diatur
dengan tingkat tegangan pada control grid. Macam-macam fosfor yang berbeda dapat
digunakan pada CRT, kecuali warna, hal yang membedakan suatu fosfor dengan fosfor
lainnya yaitu persistence.
Raster-Scan System merupakan pancaran elektron yang bergerak baris per baris
dari atas ke bawah. Definisi gambar disimpan dalam memori yang disebut refresh buffer
atau frame buffer. Setiap titik pada layar disebut pixel (picture element). Refreshing rate
memiliki nilai 60 s/d 80 frame per detik. Horizontal retrace adalah kembalinya scan ke
bagian kiri layar setelah refreshing tiap scan line. Vertical retrace adalah kembalinya scan
ke atas setelah selesai satu frame (1/80 s/d 1/60 detik).
Dalam Random-Scan System, berkas elektron diarahkan hanya ke area layar tempat
gambar harus dibuat. Ini juga disebut tampilan vektor, karena menggambar satu garis pada
satu waktu. Itu dapat menggambar dan menyegarkan garis komponen gambar dalam urutan
tertentu. Pen plotter adalah contoh tampilan pemindaian acak. Jumlah baris mengatur
kecepatan refresh pada tampilan pemindaian acak. Area memori yang disebut file tampilan
2
refresh menyimpan definisi gambar sebagai serangkaian perintah menggambar garis.
Sistem kembali ke perintah baris pertama dalam daftar, setelah semua perintah
menggambar telah diproses. Sistem vektor berkualitas tinggi dapat menangani sekitar 100,
00 garis pendek pada kecepatan refresh ini. Penyegaran lebih cepat dapat membakar fosfor.
Untuk menghindari hal ini, setiap siklus penyegaran ditunda untuk mencegah laju
penyegaran lebih besar dari 60 bingkai per detik.
Peralatan input interaktif merupakan alat untuk mengolah grafik dan memasukkan
data. Beberapa macam input interaktif melengkapi sistem grafika, yaitu keyboard, untuk
memasukan karakter, untuk mengenali posisi atau orientasi. Contoh mouse, joystick, glove,
light pen. Pick, untuk menyeleksi entity suatu tampilan. Choice, untuk menyeleksi dari
suatu action atau pilihan yang tersedia. Misal peralatan button pada tablet dan mouse,
peralatan choice digunakan untuk memasukan perintah atau pilihan menu pada suatu
program grafik.
3
Gambar 1.2.4.1 Contoh Peralatan input interaktif
Output primitif adalah bentuk geometri dasar yang dapat digunakan untuk
membentuk objek yang lebih komplek. Dengan memasukkan output primitif tersebut
sebagai struktur yang lebih kompleks. Setiap output primitif mempunyai data koordinat
dan informasi lain tentang bagaimana cara objek ditampilkan pada layar.
4
1.3.2 Algoritma Pembentukan Garis
5
x += X_inc;
y += y_inc;
setpixel(round(x),round(y));
}
}
b. Algoritma Bresenham
Bresenham mengembangkan algoritma klasik yang lebih menarik, karena
hanya menggunakan perhitungan matematik dengan bantuan bilangan integer.
Dengan demikian tidak perlu membulatkan nilai posisi pixel setiap waktu.
Algoritma garis Bressenham disebut juga Midpoint Line Algorithm adalah
algoritma konversi penambahan nilai integer yang juga dapat diadaptasi untuk
menggambar sebuah lingkaran. Langkah - langkah untuk membentuk garis menurut
algoritma Bresenham:
6
else
{ y++;
p+=duaDyDx; }
setPixel(x,y);
}
};
1. Lingkaran
Lingkaran dapat dibuat dengan menggambarkan seperempat lingkaran,
karena bagian lain dapat dibuat sebagai bagian yang simetris. Penambahan x dapat
dilakukan dari 0 ke r sebesar unit step, yaitu menambahkan +y untuk setiap step.
Cara demikian kurang efisien karena menggunakan operasi perkalian dan akar.
2 2 2
Persamaan umum lingkaran adalah: 𝑥 + 𝑦 = 𝑟
2 2
Dimana r adalah radius lingkaran, sehingga: 𝑦 = ± (𝑟 − 𝑥)
a. Algoritma Simetris Delapan Titik
Proses pembuatan lingkaran dapat dilakukan dengan menentukan
suatu titik awal (x,y) maka terdapat tiga posisi lain, sehingga diperoleh
delapan titik. Dengan demikian sebenarnya hanya diperlukan untuk
menghitung segmen 45° dalam menentukan lingkaran selengkapnya.
Dengan titik pusat lingkaran yang tertentu, delapan titik simetris dapat
ditampilkan dengan procedure CirclePoint sebagai berikut:
7
penambahan semua jalur di sekeliling lingkaran. Algoritma ini diturunkan
dari algoritma Midpoint untuk pembentukan garis. Difokuskan pada bagian
45° dari suatu lingkaran, yaitu oktan kedua dari x=0 ke x=r/√2 dan
menggunakan procedure CirclePoints untuk menampilkan titik dari seluruh
lingkaran.
Langkah langkah untuk membentuk lingkaran algoritma Circle
Midpoint:
8
void circlePlotpoint(int xCenter, int yCenter, int x, int y)
{
SetPixel(xCenter + x, yCenter + y);
SetPixel(xCenter - x, yCenter + y);
SetPixel(xCenter + x, yCenter - y);
SetPixel(xCenter - x, yCenter - y);
SetPixel(xCenter + y, yCenter + x);
SetPixel(xCenter - y, yCenter + x);
SetPixel(xCenter + y, yCenter - x);
SetPixel(xCenter - y, yCenter - x);
}
2. Elips
Ellipse merupakan modifikasi dari bentuk lingkaran, dengan memasukkan
mayor dan minor axis pada prosedur lingkaran. Ellipse ditentukan oleh satu set titik
dengan memperhitungkan jumlah jarak dari kedua posisi (foci). Bila jarak ke kedua
foci dari sembarang titik P(x,y) pada elips diberi label d1 dan d2 maka persamaan
elips menjadi:
d1 + d2 = konstan
Untuk menggambarkan jarak d1 dan d2 dengan ketentuan koordinat masing
masing:
F1(x1,y1) dan F2(X2,Y2)
√((xx1)2+(yy1)2)2+√((xx2)2+(yy2)2=konstan
Dimana mayor dan minor axis ellipse dalam posisi paralel dengan sumbu x
dan sumbu y pada contoh ini, parameter rx disebut semi major axis dan ry disebut
semi minor axis, sehingga persamaan elips dengan parameter rx dan ry menjadi
((x•rc)/rx)2 + ((y•yc)/ry)2=1.
Pembentukan elips menurut algoritma Circle midpoint sebagai berikut:
9
yk+1k+1k+1+ry2
dengan 2rx yk+1k+1k+1=2rx2 yk k +2rx2 dan 2rx
yk+1k+1k+1=2rx2 yk k +2rx2
Teruskan sampai 2ry2x >= 2rx2 y
4. Tentukan nilai parameter pada bagian kedua menggunakan titik terakhir
(x0,y0) yang telah dihitung pada bagian pertama, sebagai berikut:
P2k+1=k+1=k+1=k+1=2ry2 2 (xo+1/2)2+2rx2 2 (yo1)2rx2 ry2
5. Setiap posisi yk pada bagian kedua, dimulai dengan k=0
a. Bila p2k> 0 maka titik selanjutnya adalah (xk, yk•1)
p2k+1k+1k+1=p2k+2rx2yk+1k+1k+1+rx2
b. Bila tidak, maka titik selanjutnya adalah (xk+1,yk•1) dan
p2k+1k+1k+1=pk+2ry2xk+1k+1k+12rx yk+1k+1k+1+ry2
6. Tentukan titik simetris pada ketiga kuadran lainnya
7. Gerakkan setiap posisi(x,y) pada garis melingkar dari elips dengan titik
pusat(xc,yc) dan tentukan nilai koordinat x=x+xc y=y+yc
8. Ulangi langkah untuk bagian pertama di atas, sehingga 2ry2x >= 2rx2y
Fill area (pengisian area) output primitif standar umumnya adalah warna solid atau
pola raster. Bentuk poligon paling mudah untuk diproses karena memiliki garis batas
(boundary) yang jelas. Ada dua macam dasar pendekatan fill area pada sistem raster:
● Dengan menentukan overlap interval untuk scan line yang melintasi area
(digunakan untuk bentuk-bentuk dasar seperti poligon, lingkaran, elips dan kurva
sederhana lainnya).
● Dengan memulai dari titik tertentu pada posisi di dalam poligon dan menggambar
secara menyebar ke pinggir sampai batas poligon (digunakan pada bentuk-bentuk
kurva yang kompleks).
10
warna garis batas. Proses pengisian dimulai dari titik (x,y) kemudian prosedur akan
memeriksa posisi titik tetangga apakah titik tersebut memiliki warna batas. Jika
tidak, warnai titik tersebut dengan warna isi. Selanjutnya periksa lagi posisi dan
warna titik tetangganya. Proses diulangi terus hingga seluruh titik pada area
pengisian telah diuji.
b. Algoritma Flood Fill
Pendekatan lain yang juga dapat digunakan untuk mengisi suatu bidang
poligon adalah dengan algoritma flood-fill. Metode ini dilakukan dari suatu titik
(x,y) dan mengganti seluruh warna pixel pada bidang tersebut dengan warna isi
yang diinginkan. Pada metode ini warna pixel yang diganti dengan warna isi yang
baru adalah warna lama (old color) yang telah ditentukan, tanpa melihat warna
batas (boundary color).
Titik dalam Grafika Komputer bisa didefinisikan sebagai suatu posisi tertentu
dalam suatu sistem koordinat. Sistem koordinat yang dipakai bisa Polar Coordinates atau
Cartesian Coordinates. Biasanya dalam pemrograman grafis, yang paling umum
digunakan adalah Cartesian Coordinates. Dalam Cartesian Coordinates, titik didefinisikan
sebagai kombinasi dua bilangan yang menentukan posisi tersebut dalam koordinat x dan y
(2D).
a. Kurva
Parameter untuk atribut kurva sama dengan atribut segmen garis. Kurva
dapat ditampilkan dengan berbagai warna, tebal, dot-dash(Style garis) dan pilihan
pen atau brush. Selain itu untuk pengisian suatu bidang tertentu termasuk memilih
warna antara solid dan pattern tertentu dan memilih warna pattern yang ada.
b. Garis
Atribut dasar untuk garis lurus adalah style (tipe garis), width (tebal) dan
color(warna). Dalam beberapa paket aplikasi grafik, garis dapat ditampilkan
dengan menggunakan Pen.
11
1.4.3 Warna dan Grayscale
Ketika suatu sistem menyediakan opsi warna, suatu parameter akan memberikan
indeks warna awal yang dimasukkan ke dalam daftar nilai atribut sistem. suatu prosedur
polyline kemudian akan menampilkan garis dengan warna tersebut dengan cara mengatur
warna tersebut di frame buffer pada lokasi pixel sepanjang garis tersebut dengan
menggunakan prosedur setPixel.
1.5.1 Translasi
Translasi dilakukan dengan penambahan translasi pada suatu titik koordinat dengan
translation vector atau shift vector, yaitu(tx, ty). Koordinat baru titik yang ditranslasi dapat
diperoleh dengan menggunakan rumus
x’ = x +tx
y’ = y+ty
Translasi adalah transformasi tanpa merubah bentuk objek (bentuk tetap). Setiap
titik pada objek akan ditranslasi dengan besaran yang sama dan titik yang ditranslasi
dipindahkan ke lokasi lain menurut garis lurus. Hal yang sama dilakukan untuk seluruh
titik pada objek dengan jarak sama untuk setiap titik.
1.5.2 Rotasi
Rotasi atau pemutaran objek dilakukan dengan menggeser semua titik P sejauh
sudut q dengan tr = 0 dan titik pusat pemutaran berada di titik (0,0), sehingga :
Qx = Px cos(θ) – Py sin(θ)
Qy = Px sin(θ) + Py cos(θ)
1.5.3 Skala
Transformasi skala adalah perubahan ukuran suatu objek. Koordinat baru diperoleh
dengan melakukan perkalian koordinat dengan scaling factor, yaitu (sx,sy) dimana sx
adalah scaling factor untuk sumbu x dan sy adalah scaling factor untuk sumbu y.
Koordinat baru titik yang diskala dapat diperoleh dengan x’ = x.sx dan y’= y.sy. Scaling
factor sx dan sy dapat diberikan sembarang nilai positif. Nilai lebih dari 1 menandakan
12
bahwa sebuah objek diperbesar sedang nilai nilai kurang dari 1 menunjukkan bahwa objek
diperkecil.
13
BAB II
PERANCANGAN APLIKASI
Program yang kami rancang memiliki 7 menu utama yaitu Shape, Line Draw, Fill
Color, Stroke Color, Move, Scale, dan Rotate yang masing-masing memiliki fungsi
tersendiri dan dipisahkan dengan tab/ menu bar untuk mempermudah.
1. Menu bar dengan icon persegi berisi menu shape, warna, dan warna garis yang bisa
diaplikasikan sesuai kebutuhan.
2. Menu bar dengan icon pen berisi line draw dan warnanya. Fitur berfungsi untuk
mengatur garis yang diperlukan dan dapat mengatur atribut seperti tebal garis, style
garis, dan warna garis
3. Menu bar dengan icon setting berisi scale dan rotate. Scale berisikan tools untuk
memperbesar atau memperkecil objek dimana berisikan fungsi zoom untuk
memperbesar dan memperkecil objek. Sedangkan untuk rotate berfungsi untuk
memutar sudut objek.
4. Menu bar dengan icon arah panah berisi translation/ move. Fitur ini berfungsi
untuk mengubah posisi objek di canvas.
14
Gambar 2.1.2. Menu Bar berisi Line Draw
15
Gambar 2.1.4. Menu Bar berisi move
Bagian perancangan User Interface atau Antar Muka pengguna di bagian utama
akan terdapat navbar, menu bar, dan canvas. Navbar berisi tulisan Computer Graphic dan
di sebelah kanan ada tombol untuk me-refresh canvas. Menu Bar berisi menu-menu untuk
keperluan menggambar. Canvas adalah tempat menggambar objek. Tampilan dari
antarmuka bisa dilihat di gambar 2.1.1 sampai 2.1.4.
16
BAB III
IMPLEMENTASI PROGRAM
Lenovo AMD 9 4 1 TB
● HTML
Visual Studio Code 1.58 ● CSS
● Javascript
17
3.3 Tampilan dan Modul Program
18
Gambar 3.3.1.3. Hasil fungsi shape segitiga
19
Gambar 3.3.1.5. Hasil fill color
20
Gambar 3.3.1.7. Hasil line draw dengan ukuran 1-5 solid
21
Gambar 3.3.1.9. Hasil line draw dengan warna merah solid
22
Gambar 3.3.1.11. Hasil rotasi persegi 30 derajat
23
Gambar 3.3.1.13. Hasil scaling 1.5
<!DOCTYPE html>
<html lang="en">
24
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width,
initial-scale=1.0" />
href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.1/dist/css/boo
tstrap.min.css"
rel="stylesheet"
integrity="sha384-+0n0xVW2eSR5OomGNYDnhzAbDsOXxcvSN1TPprVMTNDbi
YZCxYbOOl7+AMvyTG2x"
crossorigin="anonymous"
/>
<link
rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.
3/css/all.min.css"
/>
<title>GrafKom</title>
<style>
.custom-style-btn-arrow:hover {
cursor: pointer;
}
</style>
</head>
<body>
<nav>
<div class="navbar navbar-light bg-light">
<div class="container-fluid">
<a class="navbar-brand" href="#"> Computer Graphic
</a>
<div class="d-flex">
<button class="btn btn-success"
onclick="refreshCanvas()">
<i class="fas fa-sync-alt"></i>
</button>
</div>
</div>
</div>
<div class="nav nav-tabs" id="nav-tab" role="tablist">
<button
class="nav-link active"
id="nav-home-tab"
data-bs-toggle="tab"
data-bs-target="#nav-home"
type="button"
25
role="tab"
aria-controls="nav-home"
aria-selected="true"
>
<svg
xmlns="http://www.w3.org/2000/svg"
width="16"
height="16"
fill="currentColor"
class="bi bi-square-half"
viewBox="0 0 16 16"
>
<path
d="M8 15V1h6a1 1 0 0 1 1 1v12a1 1 0 0 1-1 1H8zm6
1a2 2 0 0 0 2-2V2a2 2 0 0 0-2-2H2a2 2 0 0 0-2 2v12a2 2 0 0 0 2
2h12z"
/>
</svg>
</button>
<button
class="nav-link"
id="nav-profile-tab"
data-bs-toggle="tab"
data-bs-target="#nav-profile"
type="button"
role="tab"
aria-controls="nav-profile"
aria-selected="false"
>
<svg
xmlns="http://www.w3.org/2000/svg"
width="16"
height="16"
fill="currentColor"
class="bi bi-vector-pen"
viewBox="0 0 16 16"
>
<path
fill-rule="evenodd"
d="M10.646.646a.5.5 0 0 1 .708 0l4 4a.5.5 0 0 1 0
.708l-1.902 1.902-.829 3.313a1.5 1.5 0 0 1-1.024 1.073L1.254
14.746 4.358 4.4A1.5 1.5 0 0 1 5.43
3.377l3.313-.828L10.646.646zm-1.8 2.908-3.173.793a.5.5 0 0
0-.358.342l-2.57 8.565 8.567-2.57a.5.5 0 0 0
.34-.357l.794-3.174-3.6-3.6z"
/>
<path
fill-rule="evenodd"
d="M2.832 13.228 8 9a1 1 0 1 0-1-1l-4.228
5.168-.026.086.086-.026z"
/>
</svg>
</button>
<button
26
class="nav-link"
id="nav-contact-tab"
data-bs-toggle="tab"
data-bs-target="#nav-contact"
type="button"
role="tab"
aria-controls="nav-contact"
aria-selected="false"
>
<svg
xmlns="http://www.w3.org/2000/svg"
width="16"
height="16"
fill="currentColor"
class="bi bi-sliders"
viewBox="0 0 16 16"
>
<path
fill-rule="evenodd"
d="M11.5 2a1.5 1.5 0 1 0 0 3 1.5 1.5 0 0 0
0-3zM9.05 3a2.5 2.5 0 0 1 4.9 0H16v1h-2.05a2.5 2.5 0 0 1-4.9
0H0V3h9.05zM4.5 7a1.5 1.5 0 1 0 0 3 1.5 1.5 0 0 0 0-3zM2.05
8a2.5 2.5 0 0 1 4.9 0H16v1H6.95a2.5 2.5 0 0 1-4.9
0H0V8h2.05zm9.45 4a1.5 1.5 0 1 0 0 3 1.5 1.5 0 0 0 0-3zm-2.45
1a2.5 2.5 0 0 1 4.9 0H16v1h-2.05a2.5 2.5 0 0 1-4.9
0H0v-1h9.05z"
/>
</svg>
</button>
<button
class="nav-link"
id="nav-translation-tab"
data-bs-toggle="tab"
data-bs-target="#nav-translation"
type="button"
role="tab"
aria-controls="nav-translation"
aria-selected="false"
>
<svg
xmlns="http://www.w3.org/2000/svg"
width="16"
height="16"
fill="currentColor"
class="bi bi-arrows-move"
viewBox="0 0 16 16"
>
<path
fill-rule="evenodd"
d="M7.646.146a.5.5 0 0 1 .708 0l2 2a.5.5 0 0
1-.708.708L8.5 1.707V5.5a.5.5 0 0 1-1 0V1.707L6.354 2.854a.5.5
0 1 1-.708-.708l2-2zM8 10a.5.5 0 0 1
.5.5v3.793l1.146-1.147a.5.5 0 0 1 .708.708l-2 2a.5.5 0 0 1-.708
0l-2-2a.5.5 0 0 1 .708-.708L7.5 14.293V10.5A.5.5 0 0 1 8
27
10zM.146 8.354a.5.5 0 0 1 0-.708l2-2a.5.5 0 1 1 .708.708L1.707
7.5H5.5a.5.5 0 0 1 0 1H1.707l1.147 1.146a.5.5 0 0
1-.708.708l-2-2zM10 8a.5.5 0 0 1 .5-.5h3.793l-1.147-1.146a.5.5
0 0 1 .708-.708l2 2a.5.5 0 0 1 0 .708l-2 2a.5.5 0 0
1-.708-.708L14.293 8.5H10.5A.5.5 0 0 1 10 8z"
/>
</svg>
</button>
</div>
</nav>
<div class="tab-content" id="nav-tabContent"
style="min-height: 150px">
<div
class="tab-pane fade show active"
id="nav-home"
role="tabpanel"
aria-labelledby="nav-home-tab"
>
<!-- Shape -->
<div
class="tab-pane fade show active container-fluid"
id="nav-home"
role="tabpanel"
aria-labelledby="nav-home-tab"
>
<div class="row py-3">
<div class="col-2">
<button
class="btn btn-sm btn-primary"
onclick="rectangle(200,200)"
>
<svg
xmlns="http://www.w3.org/2000/svg"
width="16"
height="16"
fill="currentColor"
class="bi bi-square"
viewBox="0 0 16 16"
>
<path
d="M14 1a1 1 0 0 1 1 1v12a1 1 0 0 1-1 1H2a1
1 0 0 1-1-1V2a1 1 0 0 1 1-1h12zM2 0a2 2 0 0 0-2 2v12a2 2 0 0 0
2 2h12a2 2 0 0 0 2-2V2a2 2 0 0 0-2-2H2z"
/>
</svg>
</button>
<button
class="btn btn-sm btn-warning text-white"
onclick="rectangle(300,200)"
>
<img src="img/rectangle.png" alt="" />
</button>
<button class="btn btn-sm btn-danger"
onclick="segitiga(100,100)">
28
<svg
xmlns="http://www.w3.org/2000/svg"
width="16"
height="16"
fill="currentColor"
class="bi bi-triangle"
viewBox="0 0 16 16"
>
<path
d="M7.938 2.016A.13.13 0 0 1 8.002 2a.13.13
0 0 1 .063.016.146.146 0 0 1 .054.057l6.857
11.667c.036.06.035.124.002.183a.163.163 0 0 1-.054.06.116.116 0
0 1-.066.017H1.146a.115.115 0 0 1-.066-.017.163.163 0 0
1-.054-.06.176.176 0 0 1 .002-.183L7.884 2.073a.147.147 0 0 1
.054-.057zm1.044-.45a1.13 1.13 0 0 0-1.96 0L.165
13.233c-.457.778.091 1.767.98 1.767h13.713c.889 0
1.438-.99.98-1.767L8.982 1.566z"
/>
</svg>
</button>
<button class="btn btn-sm btn-success"
onclick="lingkaran(80)">
<svg
xmlns="http://www.w3.org/2000/svg"
width="16"
height="16"
fill="currentColor"
class="bi bi-circle"
viewBox="0 0 16 16"
>
<path
d="M8 15A7 7 0 1 1 8 1a7 7 0 0 1 0 14zm0
1A8 8 0 1 0 8 0a8 8 0 0 0 0 16z"
/>
</svg>
</button>
</div>
<div class="col-2">
<div class="input-group input-group-sm
justify-content-center">
<span class="input-group-text"
for="stroke-color"
>Fill Color</span
>
<input
type="color"
class="form-control form-control-color"
id="fill-color-shape"
/>
</div>
</div>
<div class="col-2">
<div class="input-group input-group-sm
justify-content-center">
29
<span class="input-group-text"
for="stroke-color"
>Stroke Color</span
>
<input
type="color"
class="form-control form-control-color"
id="stroke-color-shape"
/>
</div>
</div>
</div>
</div>
<!-- End Shape -->
</div>
<div
class="tab-pane fade"
id="nav-profile"
role="tabpanel"
aria-labelledby="nav-profile-tab"
>
<div class="row py-3 me-0 ps-3">
<div class="col-2">
<label for="lineWidth"
>Line Width
<span class="badge bg-primary"
id="line-width-value"
>1</span
></label
>
<input
type="range"
class="form-range"
min="1"
max="5"
id="lineWidth"
/>
</div>
<div class="col-2">
<div class="input-group input-group-sm
justify-content-center">
<span class="input-group-text" for="stroke-color"
>Stroke Color</span
>
<input
type="color"
class="form-control form-control-color"
id="stroke-color"
/>
</div>
</div>
<div class="col-2">
<div class="input-group input-group-sm
justify-content-center">
30
<select class="form-select" id="line-type">
<option value="solid">Solid</option>
<option value="dashed">Dashed</option>
</select>
</div>
</div>
</div>
</div>
<div
class="tab-pane fade"
id="nav-contact"
role="tabpanel"
aria-labelledby="nav-contact-tab"
>
<!-- Rotate -->
<div class="row py-3 me-0 ps-3">
<div class="col">
<div class="row">
<div class="col-3">
<h5 class="card-title">Rotate</h5>
<div class="input-group flex-nowrap">
<span class="input-group-text"
id="addon-wrapping"
>Θ</span
>
<input
type="text"
class="form-control"
placeholder="Angle"
id="rotate-shape"
/>
<button class="btn btn-sm btn-success"
id="btn-rotate">
Rotate
</button>
</div>
</div>
<div class="col-3">
<h5 class="card-title">Scale</h5>
<div class="input-group flex-nowrap">
<span class="input-group-text"
id="addon-wrapping"
><i class="fas fa-expand-arrows-alt"></i
></span>
<input
type="text"
class="form-control"
placeholder="x"
id="scale-x-shape"
/>
<input
type="text"
class="form-control"
placeholder="y"
31
id="scale-y-shape"
/>
<button class="btn btn-sm btn-success"
id="btn-scale">
Scale
</button>
</div>
</div>
<!-- <div class="col-3">
<h5 class="card-title">Flip</h5>
<div
class="btn-group d-flex"
role="group"
aria-label="Basic example"
>
<button class="btn btn-primary"
onclick="flipHorizontal()">
<i class="fas fa-arrows-alt-h"></i>
</button>
<button class="btn btn-danger"
onclick="flipVertical()">
<i class="fas fa-arrows-alt-v"></i>
</button>
</div>
</div> -->
</div>
</div>
</div>
<!-- End Rotate -->
</div>
<div
class="tab-pane fade"
id="nav-translation"
role="tabpanel"
aria-labelledby="nav-contact-tab"
>
<!-- Translate -->
<div class="row py-3 me-0 justify-content-center">
<div class="col-4">
<!-- Tombol Baris Pertama -->
<div class="row text-center">
<!-- Tombol Kiri Atas -->
<div class="col">
<button
class="btn btn-sm btn-secondary arrow-btn
arrow-btn"
onclick="ataskiri()"
>
<i
class="custom-style-btn-arrow fas
fa-arrow-circle-up"
style="transform: rotate(-45deg)"
></i>
</button>
32
</div>
<!-- End Tombol Kiri Atas -->
33
<button
class="btn btn-sm btn-secondary arrow-btn"
onclick="tengahkanan()"
>
<i
class="custom-style-btn-arrow fas
fa-arrow-circle-right"
></i>
</button>
</div>
<!-- End Tombol tengah kanan -->
</div>
<!-- End Tombol Baris Kedua -->
34
style="transform: rotate(135deg)"
></i>
</button>
</div>
<!-- End Tombol bawah tengah kanan -->
</div>
<!-- End Tombol Baris Ketiga -->
</div>
</div>
<!-- End Translate -->
</div>
</div>
<div class="container-fluid">
<div class="row justify-content-between py-2">
<div class="col">
<canvas
id="canvas-view"
width="1310"
height="420"
style="border: 1px solid black; display: block;
margin: 0 auto"
></canvas>
</div>
</div>
</div>
<script
src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.1/dist/js/boots
trap.bundle.min.js"
integrity="sha384-gtEjrD/SeCtmISkJkNUaaKMoLD0//ElJ19smozuHV6z3I
ehds+3Ulb9Bn9Plx0x4"
crossorigin="anonymous"
></script>
<script src="paint.js"></script>
<script src="lib/linedraw.js"></script>
<script src="lib/translation.js"></script>
<script src="lib/rotate.js"></script>
<script src="lib/scale.js"></script>
<script src="lib/flip.js"></script>
</body>
</html>
35
const scaleXShape = document.querySelector("#scale-x-shape")
const scaleYShape = document.querySelector("#scale-y-shape")
let recentShape;
let recentCoordinateX;
let recentCoordinateY;
let recentSize = [];
36
titik(myImageData, x, y, red, green, blue)
}
}
}
}
getFillColorShape.addEventListener('change',function(e) {
fillColorShape = e.target.value
drawCanvas()
})
getStrokeColorShape.addEventListener('change',function(e) {
strokeColorShape = e.target.value
drawCanvas()
})
recentCoordinateX = startPointX
recentCoordinateY = startPointY
context.beginPath()
console.log(rotateShape);
if (rotateShape != 0) {
tempRotate.push('rectangle', rotateShape)
context.translate(startPointX + (panjang/2),
startPointY + (lebar/2));
context.rotate(Math.PI / 180 * rotateShape);
context.translate((startPointX + (panjang/2))*-1,
(startPointY + (lebar/2))*-1);
}
context.strokeStyle = strokeColorShape
context.fillStyle = fillColorShape
37
context.rect(startPointX,startPointY,panjang,lebar)
context.closePath();
drawCanvas()
}
recentCoordinateX = startPointX
recentCoordinateY = startPointY
context.beginPath();
if (rotateShape != 0) {
tempRotate.push('segitiga', rotateShape)
context.translate(canvasView.height/2,
canvasView.width/2);
context.rotate(Math.PI / 180 * rotateShape);
context.translate((canvasView.height/2)*-1,
(canvasView.width/2)*-1);
}
// context.moveTo(canvasView.width/2, canvasView.height/2 -
tinggi/2 );
// context.lineTo(canvasView.width/2 + alas/2
,canvasView.height/2 + tinggi/2);
// context.lineTo(canvasView.width/2 - alas/2
,canvasView.height/2 + tinggi/2);
context.moveTo(canvasView.width/2 + alas/2,
canvasView.height/2 - tinggi/2 );
context.lineTo(canvasView.width/2 + alas/2
,canvasView.height/2 - tinggi/2 + tinggi);
context.lineTo(canvasView.width/2 + alas/2
-alas,canvasView.height/2 -tinggi/2 +tinggi);
38
// context.moveTo(startPointX, startPointY+tinggi);
// context.lineTo(startPointX,startPointY);
// context.lineTo(startPointX+alas,startPointY);
// }
context.closePath();
drawCanvas()
}
function lingkaran(radius) {
refreshCanvas()
recentShape = 'lingkaran'
if (recentSize.length > 0) {
recentSize = []
}
recentSize.push(radius)
recentCoordinateX = canvasView.width/2
recentCoordinateY = canvasView.height/2
context.beginPath();
context.arc(recentCoordinateX, recentCoordinateY, radius,
Math.PI * 0, Math.PI * 2);
context.closePath();
drawCanvas()
}
function drawCanvas() {
context.fillStyle = fillColorShape
context.strokeStyle = strokeColorShape
context.fill()
context.stroke()
}
function refreshCanvas() {
rotateShape.value = 0
context.restore();
context.setTransform(1,0,0,1,0,0);
context.clearRect(0, 0, canvasView.width,
canvasView.height)
}
// Lebar garis
const getLineWidth = document.querySelector("#lineWidth")
let initialLineWidth = getLineWidth.value = 1
context.lineWidth = initialLineWidth;
getLineWidth.addEventListener('input',function(e) {
context.lineWidth = e.target.value
39
lineWidthView.innerHTML = e.target.value
})
// Warna Garis
const getStrokeColor = document.querySelector("#stroke-color")
context.strokeStyle = getStrokeColor.value; // initial brush
color
getStrokeColor.addEventListener('input',function(e) {
context.strokeStyle = e.target.value
})
// Type Garis
const getLineType = document.querySelector("#line-type")
const lineWidthView =
document.querySelector("#line-width-value")
let lineType = 'solid'
getLineType.addEventListener('change', function(e) {
lineType = e.target.value
})
function setMouseCoordinates(e) {
mouseX = e.clientX - boundings.left;
mouseY = e.clientY - boundings.top;
}
// Mouse ditekan
canvasView.addEventListener('mousedown',function(e) {
setMouseCoordinates(e)
isDrawing = true
// Mulai gambar
context.beginPath()
context.moveTo(mouseX, mouseY);
})
// Mouse Bergerak
canvasView.addEventListener('mousemove',function(e) {
setMouseCoordinates(e)
if(isDrawing){
if (lineType == 'solid') {
context.setLineDash([0]);
}else if (lineType == 'dashed') {
context.setLineDash([15]);
}
context.lineTo(mouseX, mouseY);
context.stroke();
}
})
// Mouse dilepas
canvasView.addEventListener('mouseup', function(e) {
setMouseCoordinates(e)
40
isDrawing = false
})
btnRotate.addEventListener('click', function(e) {
if (recentShape == 'rectangle') {
rectangle(recentSize[0], recentSize[1],
rotateShape.value)
}else if (recentShape == 'segitiga') {
segitiga(recentSize[0], recentSize[1],
rotateShape.value)
}
})
btnScale.addEventListener('click', function() {
let x = scaleXShape.value
let y = scaleYShape.value
if (scaleXShape.value==0) {
x = 1
}
if (scaleYShape.value==0) {
y=1
}
if (recentShape == 'rectangle') {
if (tempRotate[0] == 'rectangle') {
rectangle(recentSize[0]*x,
recentSize[1]*y,tempRotate[1])
return 0
}
rectangle(recentSize[0]*x, recentSize[1]*y)
}else if (recentShape == 'segitiga') {
segitiga(recentSize[0]*x, recentSize[1]*y)
}else if (recentShape == 'lingkaran') {
lingkaran(recentSize[0]*x)
}
})
function translation(oldNode, T) {
41
let recentX = oldNode.x + T.x
let recentY = oldNode.y + T.y
function ataskiri() {
moveObject(-10,-10)
}
function atastengah() {
moveObject(0,-10)
}
function ataskanan() {
moveObject(10,-10)
}
function tengahkiri() {
moveObject(-10,0)
}
function tengahkanan() {
moveObject(10,0)
}
function bawahkiri() {
moveObject(-10,10)
}
function bawahtengah() {
moveObject(0,10)
}
function bawahkanan() {
moveObject(10,10)
}
function moveObject(x, y) {
refreshCanvas()
if (recentShape == 'rectangle') {
context.beginPath();
if (tempRotate[0] == 'rectangle') {
context.translate(recentCoordinateX+x +
(recentSize[0]/2), recentCoordinateY+y + (recentSize[1]/2));
context.rotate(Math.PI / 180 * tempRotate[1]);
context.translate((recentCoordinateX+x +
(recentSize[0]/2))*-1, (recentCoordinateY+y +
(recentSize[1]/2))*-1);
}
context.rect(recentCoordinateX+x,recentCoordinateY+y,recentSize
[0], recentSize[1])
context.closePath();
42
drawCanvas()
}else if (recentShape == 'segitiga') {
context.beginPath();
context.moveTo(recentCoordinateX+x,
recentCoordinateY+y);
context.lineTo(recentCoordinateX+x,(recentCoordinateY+y)+recent
Size[1]);
context.lineTo((recentCoordinateX+x)-recentSize[0],recentCoordi
nateY+y+recentSize[1]);
context.closePath();
drawCanvas()
}else if (recentShape == 'lingkaran') {
console.log(recentSize[0]);
context.beginPath();
context.arc(recentCoordinateX+x, recentCoordinateY+y,
recentSize[0], Math.PI * 0, Math.PI * 2);
context.closePath();
drawCanvas()
}
recentCoordinateX = recentCoordinateX+x
recentCoordinateY = recentCoordinateY+y
}
43
BAB IV
KESIMPULAN DAN SARAN
4.1 Kesimpulan
4.2 Saran
Setelah melihat kesimpulan diatas, kami berharap bahwa pembaca dapat terlebih
dahulu memahami algoritma dan fungsi-fungsi yang terdapat pada javascript agar dapat
menyelesaikan masalah yang dihadapi dalam pembuatan aplikasi grafika komputer.
Pembaca juga diharapkan dapat terampil dalam menyusun tampilan website agar dapat
mengikuti perkembangan jaman dan nyaman digunakan oleh pengguna dengan menguasai
bahasa pemrograman yang digunakan dalam penyusunan tampilan.
44
DAFTAR PUSTAKA
https://repository.unikom.ac.id/40391/1/grafkom%202.pdf
http://dhityatriez.blogspot.com/2009/10/output-primitif.html
https://www.weare.id/output-primitif/
https://www.geeksforgeeks.org/random-scan-display/
http://rizkyfajar09.blogspot.com/2015/09/grafika-komputer-teknologi-display.html
45