- g9.js एक interactive graphics library है, जो numeric key-value data को render function से जोड़ती है; जब user किसी graphic element को drag करता है, तो यह नए data values खोजकर पूरे scene को फिर से draw करती है
- मुख्य API सिर्फ
g9(initialData, render[, onChange])है, जोinitialDataऔर drawing context कोrender(data, ctx)में पास करके points, lines, circles, images आदि draw करता है - drag जैसी manipulation होने पर, g9 संभावित data-value space को optimize करके इच्छित बदलाव के सबसे करीब value ढूंढता है, और जरूरत पड़ने पर
onChangeसे नया data पास करता है - gallery basic point mirroring से लेकर Bézier curves, तीन points से define होने वाला circle, cube, dragon curve, images, clock, LOGO Turtle, Grid Warp, Crank and Piston तक के examples step-by-step दिखाती है
affects,ctx.pure,getData,setData,isManipulating,Math.max/Math.minजैसे patterns से manipulable variables की range, re-rendering, और animation के दौरान user input handling को configure किया जा सकता है
g9.js का operation flow
- g9.js एक single function
g9(initialData, render[, onChange])expose करता है - पहले numeric values वाला key-value data बनाया जाता है
- example में
foo: 10जैसाinitialDataobject इस्तेमाल होता है - संबंधित documentation initialData in the docs में है
- example में
- data और drawing context
render(data, ctx)को दिए जाते हैं, और render function data values के आधार पर तय करता है कि क्या draw करना है- example में
ctx.point(data.foo, 17)से point draw किया जाता है - संबंधित documentation render in the docs में है
- example में
- जब user किसी element को नई position पर drag करता है, तो g9 संभावित data-value space में सबसे करीबी बदलाव पैदा करने वाली value खोजता है
- circle को left की ओर drag करने पर example में
{foo: 8}जैसा नया data मिल सकता है
- circle को left की ओर drag करने पर example में
- नया data तय हो जाने पर consistency बनाए रखने के लिए पूरा scene फिर से render किया जाता है
- अगर
onChangecallback दिया गया हो, तो g9 नया data पास करता है ताकि page के दूसरे हिस्से update किए जा सकें
- अगर
- पूरा API Docs में देखा जा सकता है
Basic shapes और data constraints
- Basic example सिर्फ दो points इस्तेमाल करने वाला minimal example है
- render function एक point को
(x, y)पर और दूसरे point को(y, x)पर draw करता है - एक point को drag करने पर दूसरा point ऐसे move करता है जैसे वे एक-दूसरे के mirror हों
- render function एक point को
- Rings
radiusऔरangledata को trigonometric functions में डालकर points को दो circles के रूप में arrange करता है- inner points लाल रंग में draw किए जाते हैं
- commented-out
ctx.line(...)को enable करने पर दो circles के points के बीच lines जोड़ी जा सकती हैं
- The affects option g9 के basic shapes को मिलने वाला
affectsoption दिखाता हैaffectsspecify करता है कि shape data के किस हिस्से को बदल सकता है- तीन lines अलग-अलग
affectsvalues इस्तेमाल करती हैं - एक line सिर्फ
l2_start_x,l2_start_yबदलती है, और दूसरी linel3_start_x,l3_end_yबदलती है
- Using Max and Min to limit a point's range of motion
Math.max(Math.min(...))से point की movement range को limit करता है- middle point की position
x1 + 20औरx3 - 20के बीच सीमित रहती है - एक अलग point
data.x2value को ज्यों का त्यों दिखाता है
- middle point की position
Curves, geometry, 3D examples
- Bézier Curve Wikipedia के quadratic Bézier curve animation को interactive version में बदलने वाला example है
start,middle,endcoordinates औरtvalue को data के रूप में इस्तेमाल करता हैtween=label दिखाता है, और कई चरणों के line segments से smooth curve बनाता है- intermediate helper lines और curve segments में
affects: ['t']specify किया गया है
- Three points define a circle तीन points से circle define करता है
- तीन points के बीच line segments, midpoints, और perpendicular direction lines calculate करता है
- calculated center point पर point लगाता है, और पहले point तक की दूरी को radius मानकर green circle draw करता है
- cube cube के vertices और edges बनाकर 3D rotation, translation, और projection के बाद उन्हें 2D lines के रूप में draw करता है
rx,ry,rzfunctions से axis rotations calculate किए जाते हैंprojectfunction300 * p[0] / p[2],300 * p[1] / p[2]तरीके से projection करता है- edges
affects: ['ax', 'ay']का इस्तेमाल करते हैं, जिससे drag करके rotation values बदली जा सकती हैं
Fractals, procedural drawing, images
- dragon recursive function
dragon(...)से dragon curve draw करता है- data में
squareness,fromX,fromY,toX,toYशामिल हैं - line option
affects: ['squareness']का इस्तेमाल करके curve shape manipulate करता है - start और end points radius
5वाले points के रूप में दिखाए जाते हैं
- data में
- tree recursively tree draw करता है
- data
deltaAngle,attenuation,startLengthहै - branch endpoints और lines
affects: ['deltaAngle', 'attenuation']इस्तेमाल करते हैं - अगर
n > 3हो, तो line का color brown, वरना green रखा जाता है onChangecallback बदला हुआ data console में output करता है
- data
- LOGO Turtle simulator
make_turtle(ctx)से simple Turtle interface बनाता है और बार-बार lines draw करता है- data
rऔरthetaहै forwardcurrent direction में move करके line draw करता है, औरdturndegree-based rotation को radians में बदलता है
- data
- Grid Warp grid points को warp करने वाला transform apply करता है
- data
spinऔरscaleहै - प्रत्येक point की दूरी
rऔर anglethetacalculate करने के बादtheta + data.spin * rसे rotation amount बदलता है -10से10तक केi,jcombinations से points draw करता है
- data
- image
ctx.imageसे image draw करता है- image URL,
x,y, width200, height200specify करता है
- image URL,
Mechanical devices और time-based interaction
- Kevin Clock
timedata इस्तेमाल करके clock shape draw करता है- minute hand
data.time / 60, second handdata.timeका इस्तेमाल करकेMath.cos,Math.sinसे endpoints calculate करता है setIntervalहर 50ms मेंtimeको0.01बढ़ाता हैgraphics.isManipulatingtrue न होने पर हीgetData()औरsetData(data)से time update करता है
- minute hand
- Crank and Piston crank और piston structure draw करता है
- data सिर्फ
timeहै - housing color
Math.cos(data.time)से बने HSL value के अनुसार बदलता है - crank, shaft, और piston को lines, rectangles, circles से draw करता है
- animation block commented out है; enable करने पर यह हर 10ms में
timeको0.05बढ़ाने के लिए बना है
- data सिर्फ
- tongs rotation और repeated line segments से tongs जैसा shape बनाता है
- data
a,bहै rotate(x, y, a)से coordinates rotate करता है, और चार iterations में दो rows के line segments draw करता हैonChangecallback changed data को console में output करता है
- data
1 टिप्पणियां
Hacker News टिप्पणियां
रिकर्सिव ट्री की 5–6 स्तर गहराई पर render हुए node को पकड़कर हिलाने पर बाकी ट्री का react करना जादू जैसा दिखता है
किसी भी leaf node position से ट्री के शुरुआती parameters को स्पष्ट रूप से infer करने वाला function न होने पर भी यह काम करता है
उत्सुकता है कि यह कैसे implement किया गया है, और जब points की positions किसी ठीक-ठाक smooth function से जुड़ी नहीं होतीं तो यह कितना अच्छा काम करता है
या फिर कोई off-the-shelf optimizer डाल देने से भी काम हो सकता है
inverse kinematics problems को model और solve करने के कई तरीके हैं
उनमें सबसे flexible तरीके आम तौर पर iterative optimization से approximate solution ढूंढते हैं, क्योंकि forward kinematics equations को उल्टा solve करना कठिन होता है और solution space खाली भी हो सकता है
कई तरीकों का मूल विचार forward kinematics equations को Taylor series expansion से model करना है, जिसे मूल system की तुलना में उलटकर solve करना आसान हो सकता है
पहले मुझे लगा कि यह cool और साफ-सुथरा simple API है, और वही काम करने के लिए d3 से ज्यादा पसंद आएगा
लेकिन “जब कोई graphics के साथ interact करता है, जैसे किसी element को नई position पर drag करने की कोशिश करता है, तो g9 संभावित data values के space में optimize करके उस बदलाव के सबसे करीब वाली value ढूंढता है” पढ़ने के बाद, यह काफी जादुई DOM manipulation जैसा महसूस हुआ
जिन applications में chart को manipulate करके data बदलना हो, वे ज्यादातर काफी special लगती हैं, लेकिन मजे के लिए use करना universal है
ऐसा use case आए तो बहुत आनंद आएगा
उत्सुक हूं कि क्या आपने page के दूसरे examples भी खुद आजमाए हैं
drag event के शुरुआती कुछ frames में speed और vector का average लें, फिर और frames के साथ average को लगातार update करें, और predicted endpoint की ओर सब कुछ smooth ease-in-out से move करना शुरू कर दें, तो यह “संभावित values के space में optimization” के काफी करीब हो जाता है
पहले HN पर जब इस पर चर्चा हुई थी, तब कुछ दिलचस्प comments थे: https://news.ycombinator.com/item?id=12572412
यह कैसे काम करता है, इसका explanation देखना चाहूंगा। मुझे यह black magic जैसा लगता है
उदाहरण के लिए, दो points हैं, एक (0, 10) पर और दूसरा (10, 0) पर; अगर बाद वाले point को (20, 0) तक drag करें, तो system कैसे जानता है कि पहले point को भी उसी दूरी से reflect होना चाहिए?
फिर कहूंगा, यह magic है, और बनाने वाले ने सच में बहुत अच्छा काम किया है
इस function को data variables के संबंध में partial differentiate किया जाता है, function को minimize करके नए data values ढूंढे जाते हैं, फिर नए optimal data values से सब कुछ फिर से render किया जाता है
थोड़ा confusing इसलिए है क्योंकि यहां जिसे आम तौर पर “data” कहा जा रहा है, वह mathematical optimization में parameters, और statistics/machine learning में weights कहलाने वाली चीज है
machine learning में fixed चीज को “data” कहा जाएगा, इसलिए यहां dragged element की position data के बराबर है
काफी शानदार दिखता है
एक कमी यह है कि markers या selection indicators नहीं हैं, इसलिए explanation पहले न पढ़ें तो यह बहुत स्पष्ट नहीं होता कि objects को drag किया जा सकता है
object positions को readjust करने का तरीका भी थोड़ा confusing है
आम तौर पर pointer handler define करके input के हिसाब से transform किया जाता, लेकिन अगर मेरी समझ सही है तो engine उसे automate करने के लिए अपना best guess लगा रहा है
कुछ साल पहले इसे देखकर उत्साहित हुआ था, और browser में PyTorch जैसी library के साथ चलाने के लिए इसे Pyodide में port किया था: https://srush.github.io/g9py/
JavaScript से थोड़ा ज्यादा अटकता है, लेकिन शुरुआत में इसका चलना ही हैरान करने वाला है
यह witchcraft जैसा महसूस होता है। बेहद impressive है
2D CAD के constraint-based sketch tools से इसमें समानता दिखती है
इसे कहां इस्तेमाल करना चाहिए, यह ठीक से नहीं पता, लेकिन इसे सच में clever तरीके से बनाया गया है
problem को देखने का तरीका इतना अलग है कि intuition बनाने के लिए इसे किसी चीज में खुद इस्तेमाल करके देखना पड़ेगा
शिक्षा में trigonometry या दूसरे math concepts समझाने के लिए यह बहुत उपयोगी हो सकता है
कई visual learners को formulas को visual space से map करने में कठिनाई होती है, और थोड़ा interaction जोड़ने से समझ को मजबूत करने में बहुत मदद मिलती है