8 poin oleh GN⁺ 2023-08-10 | 1 komentar | Bagikan ke WhatsApp
  • 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 meneruskan initialData dan konteks gambar ke render(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, dan Math.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
  • 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
  • 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}
  • Setelah data baru ditentukan, seluruh adegan dirender ulang agar tetap konsisten
    • Jika callback onChange disediakan, g9 meneruskan data baru agar bagian lain di halaman bisa diperbarui
  • 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
  • Rings menempatkan titik-titik dalam bentuk dua lingkaran dengan memasukkan data radius dan angle ke 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 affects yang diterima bentuk dasar g9
    • affects menentukan bagian data mana yang boleh diubah oleh suatu bentuk
    • Tiga garis memakai nilai affects yang berbeda
    • Satu garis hanya mengubah l2_start_x, l2_start_y, sedangkan garis lain mengubah l3_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 + 20 dan x3 - 20
    • Titik terpisah menampilkan nilai data.x2 apa adanya

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 nilai t
    • Label tween= ditampilkan, dan kurva halus dibentuk dari beberapa tahap segmen garis
    • Garis bantu tengah dan segmen kurva diberi affects: ['t']
  • 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 project memproyeksikan dengan cara 300 * p[0] / p[2], 300 * p[1] / p[2]
    • Rusuk memakai affects: ['ax', 'ay'] sehingga nilai rotasi bisa diubah lewat drag

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
  • 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 onChange mencetak data yang berubah ke konsol
  • LOGO Turtle simulator membuat antarmuka Turtle sederhana dengan make_turtle(ctx) lalu menggambar garis secara berulang
    • Datanya adalah r dan theta
    • forward bergerak mengikuti arah saat ini sambil menggambar garis, dan dturn mengubah rotasi dalam derajat menjadi radian
  • Grid Warp menerapkan transformasi yang membuat titik-titik kisi melengkung
    • Datanya adalah spin dan scale
    • Setelah menghitung jarak r dan sudut theta tiap titik, besar rotasi diubah menjadi theta + data.spin * r
    • Titik digambar untuk kombinasi i, j dari -10 hingga 10
  • image menggambar gambar dengan ctx.image
    • URL gambar, x, y, lebar 200, dan tinggi 200 ditentukan

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 menggunakan data.time, lalu Math.cos dan Math.sin
    • setInterval menambah time sebesar 0.01 setiap 50ms
    • Waktu diperbarui dengan getData() dan setData(data) hanya saat graphics.isManipulating tidak bernilai benar
  • 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, time akan bertambah 0.05 setiap 10ms
  • 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 onChange mencetak data yang berubah ke konsol

1 komentar

 
GN⁺ 2023-08-10
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

    • Dugaan saya, untuk objek yang digerakkan, mereka menghitung turunan parsial pengaruh tiap parameter dengan dua kali sampling fungsi, lalu menjalankan gradient descent biasa, kemudian mengulanginya sampai konvergen
      Atau bisa juga cukup memasukkan optimizer siap pakai
    • Sepertinya mirip dengan inverse kinematics
      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

    • Ini bukan untuk chart, melainkan untuk demo interaktif
      Saya penasaran apakah Anda juga mencoba langsung contoh-contoh lain di halaman itu
    • Dari sisi penerapan, ada banyak konsep STEM yang bisa disampaikan secara efektif jika interaksi diperbolehkan
    • Saya tidak akan menyebutnya sains tingkat tinggi
      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

    • Mereka mendefinisikan fungsi yang mengukur error antara posisi elemen yang digambar dan posisi baru yang diminta oleh aksi drag
      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
    • Matematika yang cukup maju tidak dapat dibedakan dari sihir, dan di sini ambang untuk “cukup maju” ternyata lebih rendah dari yang kita kira
  • 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

    • Secara potensial, sepertinya bisa dipakai untuk antarmuka drag-and-drop apa pun
      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