- g9.js adalah library grafik interaktif yang menghubungkan data key-value numerik dengan fungsi render, sehingga saat pengguna menyeret elemen grafis, library ini mencari nilai data baru lalu menggambar ulang seluruh adegan
- API intinya hanya satu, yaitu
g9(initialData, render[, onChange]); API ini meneruskaninitialDatadan konteks gambar kerender(data, ctx)untuk menggambar titik, garis, lingkaran, gambar, dan lain-lain - Saat manipulasi seperti drag terjadi, g9 melakukan optimisasi pada ruang nilai data yang mungkin untuk menemukan nilai yang paling dekat dengan perubahan yang diinginkan, dan bila perlu meneruskan data baru lewat
onChange - Gallery menampilkan contoh secara bertahap, mulai dari pencerminan titik dasar hingga kurva Bézier, lingkaran yang didefinisikan oleh tiga titik, kubus, kurva naga, gambar, jam, LOGO Turtle, Grid Warp, dan Crank and Piston
- Dengan pola seperti
affects,ctx.pure,getData,setData,isManipulating, danMath.max/Math.min, pengguna dapat menyusun rentang variabel yang bisa dimanipulasi, re-rendering, serta penanganan input pengguna selama animasi
Alur kerja g9.js
- g9.js mengekspos satu fungsi tunggal
g9(initialData, render[, onChange]) - Pertama, buat data key-value yang berisi nilai numerik
- Contohnya menggunakan objek
initialDatasepertifoo: 10 - Dokumentasi terkait ada di initialData in the docs
- Contohnya menggunakan objek
- Data dan konteks gambar diteruskan ke
render(data, ctx), lalu fungsi render menentukan apa yang akan digambar berdasarkan nilai data- Contohnya menggambar titik dengan
ctx.point(data.foo, 17) - Dokumentasi terkait ada di render in the docs
- Contohnya menggambar titik dengan
- Saat pengguna menyeret elemen ke posisi baru, g9 mencari nilai dalam ruang nilai data yang mungkin yang menghasilkan perubahan terdekat
- Jika lingkaran diseret ke kiri, dalam contoh dapat dihasilkan data baru seperti
{foo: 8}
- Jika lingkaran diseret ke kiri, dalam contoh dapat dihasilkan data baru seperti
- Setelah data baru ditentukan, seluruh adegan dirender ulang agar tetap konsisten
- Jika callback
onChangedisediakan, g9 meneruskan data baru agar bagian lain di halaman bisa diperbarui
- Jika callback
- Seluruh API dapat dilihat di Docs
Bentuk dasar dan batasan data
- Contoh Basic adalah contoh paling minimal yang hanya memakai dua titik
- Fungsi render menggambar satu titik di
(x, y)dan titik lain di(y, x) - Saat satu titik diseret, titik lainnya bergerak seolah saling mencerminkan
- Fungsi render menggambar satu titik di
- Rings menempatkan titik-titik dalam bentuk dua lingkaran dengan memasukkan data
radiusdanangleke fungsi trigonometri- Titik bagian dalam digambar dengan warna merah
- Jika komentar pada
ctx.line(...)dibuka, garis dapat ditambahkan di antara titik pada kedua lingkaran
- The affects option menunjukkan opsi
affectsyang diterima bentuk dasar g9affectsmenentukan bagian data mana yang boleh diubah oleh suatu bentuk- Tiga garis memakai nilai
affectsyang berbeda - Satu garis hanya mengubah
l2_start_x,l2_start_y, sedangkan garis lain mengubahl3_start_x,l3_end_y
- Using Max and Min to limit a point's range of motion membatasi rentang gerak titik dengan
Math.max(Math.min(...))- Posisi titik tengah dibatasi di antara
x1 + 20danx3 - 20 - Titik terpisah menampilkan nilai
data.x2apa adanya
- Posisi titik tengah dibatasi di antara
Contoh kurva, geometri, dan 3D
- Bézier Curve adalah contoh yang mengubah animasi quadratic Bézier curve dari Wikipedia menjadi versi interaktif
- Data yang digunakan adalah koordinat
start,middle,end, serta nilait - Label
tween=ditampilkan, dan kurva halus dibentuk dari beberapa tahap segmen garis - Garis bantu tengah dan segmen kurva diberi
affects: ['t']
- Data yang digunakan adalah koordinat
- Three points define a circle mendefinisikan lingkaran dengan tiga titik
- Program menghitung segmen garis di antara tiga titik, titik tengah, dan garis tegak lurus
- Titik pusat hasil perhitungan diberi marker, lalu digambar lingkaran hijau dengan jari-jari berupa jarak ke titik pertama
- cube membuat simpul dan rusuk kubus, lalu menggambarnya sebagai garis 2D setelah melalui rotasi, translasi, dan proyeksi 3D
- Rotasi sumbu dihitung dengan fungsi
rx,ry,rz - Fungsi
projectmemproyeksikan dengan cara300 * p[0] / p[2],300 * p[1] / p[2] - Rusuk memakai
affects: ['ax', 'ay']sehingga nilai rotasi bisa diubah lewat drag
- Rotasi sumbu dihitung dengan fungsi
Fraktal, gambar prosedural, dan gambar
- dragon menggambar kurva naga dengan fungsi rekursif
dragon(...)- Datanya mencakup
squareness,fromX,fromY,toX,toY - Opsi garis memakai
affects: ['squareness']untuk memanipulasi bentuk kurva - Titik awal dan akhir ditandai dengan titik berjari-jari
5
- Datanya mencakup
- tree menggambar pohon secara rekursif
- Datanya adalah
deltaAngle,attenuation,startLength - Ujung cabang dan garis memakai
affects: ['deltaAngle', 'attenuation'] - Jika
n > 3, garis digambar cokelat, selain itu hijau - Callback
onChangemencetak data yang berubah ke konsol
- Datanya adalah
- LOGO Turtle simulator membuat antarmuka Turtle sederhana dengan
make_turtle(ctx)lalu menggambar garis secara berulang- Datanya adalah
rdantheta forwardbergerak mengikuti arah saat ini sambil menggambar garis, dandturnmengubah rotasi dalam derajat menjadi radian
- Datanya adalah
- Grid Warp menerapkan transformasi yang membuat titik-titik kisi melengkung
- Datanya adalah
spindanscale - Setelah menghitung jarak
rdan sudutthetatiap titik, besar rotasi diubah menjaditheta + data.spin * r - Titik digambar untuk kombinasi
i,jdari-10hingga10
- Datanya adalah
- image menggambar gambar dengan
ctx.image- URL gambar,
x,y, lebar200, dan tinggi200ditentukan
- URL gambar,
Mekanisme dan interaksi berbasis waktu
- Kevin Clock menggambar bentuk jam menggunakan data
time- Jarum menit menghitung titik ujung dengan
data.time / 60, sedangkan jarum detik menggunakandata.time, laluMath.cosdanMath.sin setIntervalmenambahtimesebesar0.01setiap 50ms- Waktu diperbarui dengan
getData()dansetData(data)hanya saatgraphics.isManipulatingtidak bernilai benar
- Jarum menit menghitung titik ujung dengan
- Crank and Piston menggambar struktur crank dan piston
- Datanya hanya
time - Warna housing berubah mengikuti nilai HSL yang dibuat dari
Math.cos(data.time) - Crank, poros, dan piston digambar dengan garis, persegi panjang, dan lingkaran
- Blok animasi diberi komentar; jika dibuka,
timeakan bertambah0.05setiap 10ms
- Datanya hanya
- tongs membentuk penjepit dengan rotasi dan pengulangan segmen garis
- Datanya adalah
a,b rotate(x, y, a)memutar koordinat, lalu dua baris segmen digambar dalam empat kali pengulangan- Callback
onChangemencetak data yang berubah ke konsol
- Datanya adalah
1 komentar
Pendapat di Hacker News
Saat mengambil dan menggerakkan node yang dirender pada kedalaman 5–6 tingkat dari pohon rekursif, terlihat seperti sihir bagaimana sisa pohonnya ikut bereaksi
Ini bekerja bahkan tanpa fungsi yang secara eksplisit menyimpulkan parameter awal pohon dari posisi node daun yang sembarang
Saya penasaran bagaimana ini diimplementasikan, dan seberapa baik kerjanya ketika posisi titik-titik tidak terhubung oleh fungsi yang cukup mulus
Atau bisa juga cukup memasukkan optimizer siap pakai
Ada banyak cara untuk memodelkan dan menyelesaikan masalah inverse kinematics
Metode-metode yang paling fleksibel biasanya mencari solusi aproksimasi dengan optimisasi iteratif, karena persamaan forward kinematics sulit dibalik dan ruang solusinya bisa saja kosong
Inti dari beberapa metode adalah memodelkan persamaan forward kinematics dengan ekspansi deret Taylor, yang bisa lebih mudah dibalik dan diselesaikan daripada sistem aslinya
Awalnya saya pikir ini API sederhana yang keren dan rapi, dan untuk melakukan hal yang sama saya lebih menyukainya daripada d3
Namun setelah membaca “ketika seseorang berinteraksi dengan grafik, misalnya mencoba menyeret elemen ke posisi baru, g9 mengoptimalkan di ruang nilai data yang mungkin untuk menemukan nilai yang paling mendekati perubahan itu”, ini terasa seperti manipulasi DOM yang cukup ajaib
Aplikasi yang perlu memanipulasi chart untuk mengubah data tampaknya kebanyakan cukup khusus, tetapi penggunaan untuk bersenang-senang itu universal
Kalau ada use case seperti itu, pasti akan sangat menyenangkan
Saya penasaran apakah Anda juga mencoba langsung contoh-contoh lain di halaman itu
Kalau pada beberapa frame pertama dari event drag Anda merata-ratakan kecepatan dan vektor, terus memperbarui rata-rata dengan lebih banyak frame, lalu mulai menggerakkan semuanya dengan ease-in-out yang mulus menuju titik akhir yang diprediksi, itu sudah cukup dekat dengan “mengoptimalkan di ruang nilai yang mungkin”
Saat ini pernah dibahas di HN dulu, ada beberapa komentar menarik: https://news.ycombinator.com/item?id=12572412
Saya ingin melihat penjelasan tentang cara kerjanya. Bagi saya ini terasa seperti ilmu hitam
Misalnya ada dua titik, satu di (0, 10) dan satu lagi di (10, 0), lalu titik kedua diseret ke (20, 0); bagaimana sistem tahu bahwa titik pertama juga harus dipantulkan sejauh jarak yang sama?
Sekali lagi, ini sihir, dan pembuatnya benar-benar hebat
Fungsi ini dihitung turunan parsial-nya terhadap variabel data, lalu fungsi tersebut diminimalkan untuk menemukan nilai data baru, kemudian semuanya dirender ulang dengan nilai data optimal yang baru
Yang agak membingungkan adalah apa yang biasanya disebut “data” di sini, dalam optimisasi matematis bisa disebut parameter, dan dalam statistik/machine learning bisa disebut bobot
Dalam machine learning, hal yang tetap akan disebut “data”, jadi di sini posisi elemen yang diseretlah yang menjadi data
Kelihatannya cukup keren
Satu hal yang disayangkan adalah tidak ada marker atau indikator pilihan, sehingga jika tidak membaca penjelasannya dulu, tidak terlalu jelas bahwa objeknya bisa diseret
Cara menyesuaikan ulang posisi objeknya juga agak membingungkan
Biasanya kita akan mendefinisikan pointer handler dan melakukan transformasi sesuai input, tetapi jika pemahaman saya benar, tampaknya engine ini berusaha mengotomatiskannya dengan tebakan terbaik
Beberapa tahun lalu saya melihat ini dan jadi bersemangat, lalu mem-porting-nya ke Pyodide agar berjalan di browser bersama library mirip PyTorch: https://srush.github.io/g9py/
Memang sedikit lebih tersendat dibanding JavaScript, tetapi fakta bahwa ini bisa berjalan saja sudah mengejutkan
Ini terasa seperti ilmu sihir. Sangat mengesankan
Tampaknya ada kesamaan dengan tool sketsa berbasis constraint pada 2D CAD
Saya tidak begitu tahu harus dipakai untuk apa, tetapi ini dibuat dengan sangat cerdik
Cara memandang masalahnya sangat berbeda, jadi saya perlu mencobanya langsung pada sesuatu agar bisa merasakannya
Ini bisa sangat berguna untuk menyampaikan trigonometri atau konsep matematika lain di lingkungan pendidikan
Ada banyak pembelajar visual yang kesulitan memetakan rumus ke ruang visual, dan menambahkan sedikit interaksi sangat membantu untuk memperkuat pemahaman