import type { IShape } from "@thi.ng/geom-api" ; import { asPolygon } from "@thi.ng/geom/as-polygon" ; import { circle } from "@thi.ng/geom/circle" ; import { pointInside } from "@thi.ng/geom/point-inside" ; import { rect } from "@thi.ng/geom/rect" ; import { canvas } from "@thi.ng/hdom-canvas" ; import { start } from "@thi.ng/hdom/start" ; import { HALF_PI , PI } from "@thi.ng/math/api" ; import type { NodeInfo } from "@thi.ng/scenegraph" ; import { Node2D } from "@thi.ng/scenegraph/node2" ; import { cycle } from "@thi.ng/transducers/cycle" ; import { map } from "@thi.ng/transducers/map" ; import { range } from "@thi.ng/transducers/range" ; import type { ReadonlyVec , Vec } from "@thi.ng/vectors" ; import { cartesian2 } from "@thi.ng/vectors/cartesian" ; import { mulN2 } from "@thi.ng/vectors/muln" ; /**
 * Specialized scene graph node using @thi.ng/geom shapes as body.
 */ class GeomNode extends Node2D { constructor ( id , parent , t , r , s , body ) { super ( id , parent , t , r , s , body ) ; } param p containsLocalPoint ( p ) { return pointInside ( this . body , p ) ; } } let mouse = [ 0 , 0 ] ; let info ; const colors = cycle ( [ "#f00" , "#ff0" , "#06f" , "#70f" , "#666" , "#9f0" , "#0ff" , "#090" , "#f60" , ] ) ; const root = new Node2D ( "root" , null , [ 0 , 0 ] , 0 , 1 ) ; const hex = new GeomNode ( "main" , root , [ 300 , 300 ] , 0 , 200 , asPolygon ( circle ( 0.5 , { fill : "#0ff" } ) , 6 ) ) ; const triangle = new GeomNode ( "tri" , hex , [ 0 , 0 ] , PI / 4 , 1 , asPolygon ( circle ( 0.5 , { fill : "#f0f" } ) , 3 ) ) ; const satellites = [ ... map ( ( i ) => new GeomNode ( `sat-${ i }` , triangle , cartesian2 ( [ ] , [ 1 , i * HALF_PI ] ) , 0 , 0.2 , rect ( [ - 0.5 , - 0.5 ] , [ 1 , 1 ] , { fill : "#cf0" } ) ) , range ( 4 ) ) , ] ; const infoNode = new Node2D ( "info" , root , mouse , 0 , 1 , ( ) => [ "g" , { } , [ "g" , { stroke : "#999" , dash : [ 2 , 2 ] } , [ "hline" , { } , 0 ] , [ "vline" , { } , 0 ] ] , info ? [ "g" , { fill : "#fff" } , rect ( [ 0 , - 40 ] , [ 68 , 40 ] , { fill : "rgba(0,0,0,0.8)" } ) , [ "text" , { } , [ 8 , - 10 ] , `${ info . p ! [ 0 ] . toFixed ( 2 ) }, ${ info . p ! [ 1 ] . toFixed ( 2 ) }` , ] , [ "text" , { } , [ 8 , - 24 ] , `ID: ${ info . node . id }` ] , ] : undefined , ] ) ; const updateMouse = ( e ) => { mouse = [ e . offsetX , e . offsetY ] ; info = root . childForPoint ( mouse ) ; infoNode . translate = mouse ; } ; const selectNode = ( ) => info && ( info . node . body . attribs . fill = colors . next ( ) . value ) ; const app = ( ) => { hex . rotate += 0.005 ; mulN2 ( < Vec > triangle . scale , [ 1 , 1 ] , Math . sin ( hex . rotate * 5 ) * 0.3 + 0.7 ) ; satellites . forEach ( ( s ) => ( s . rotate += 0.02 ) ) ; root . update ( ) ; return [ "div.sans-serif.pl3" , [ "h1" , "hdom canvas scene graph demo" ] , [ "p" , "click on shapes to change their color..." ] , [ canvas , { width : 600 , height : 600 , onmousemove : updateMouse , onclick : selectNode , } , root , ] , ] ; } ; start ( app ) ;