SVG getScreenCTM
copy const el = document.body .appendChild ( document.createElement `div` ) ; el.innerHTML = ` < svg width= "200" height= "200" viewBox= "0 0 200 200" > < rect class= "rect" transform= "translate(50, 50) scale(1.2) rotate(25)" fill= "purple" x= "0" y= "0" width= "50" height= "50" /> </ svg> `; const box = document.body .appendChild ( document.createElement `div` ) ; Object .assign ( box.style , { position: 'absolute' , left: 0 , top: 0 , width: '50px' , height: '50px' , transformOrigin: '0 0' , outline: '5px solid red' } ) ; const rect = document.querySelector ( '.rect' ) ; const { a, b, c, d, e, f} = rect.getScreenCTM ( ) box.style .transform = ` matrix( ${ [ a, b, c, d, e, f] } ) `;
Try it out…
The transformation matrix of an SVG element can be obtained using getScreenCTM
or getCTM
. The latter of which will be relative to the SVG coordinate space, vs the coordinate space of the page.
Here we take the matrix data from getScreenCTM
and use it on a div to place a border over an SVG rect
node. This is great for layering HTML on top of SVG.
Snippet Zone Code Highlighter I wrote a naive syntax highlighter a few weeks ago. Here it is rendering the code for itself.
:
This is not a perfect highlighter, but it was fun to create and I will definitely use it in the Snippet Zone Github repository once I get that set up.
There is some css that goes with the highlighter, it’s pretty boring, but here it is anyway:
copy .hh { white- space: pre- wrap; font- family: monaco, monospace; line- height: 1.5 ; font- size: .8em; background: rgb( 3 , 21 , 36 ) ; color: rgba( 156 , 221 , 254 , 1 ) ; padding: 1em; } .hh b { font- weight: normal; } .hh i { color: #1ad6ae; } .hh u { color: rgb( 255 , 195 , 252 ) ; text- decoration: none; } .num { color: #b5cea8; } .str , .str b { color: #ce9178; } .par { color: white; font- weight: bold; } .brk { color: white; font- weight: bold; } .o { color: rgb( 0 , 151 , 221 ) ; } .obj { color: rgb( 52 , 206 , 47 ) ; font- weight: bold ! important; } .w { color: #1ad6ae; font- style: italic; } .k { color: aqua; } .cmt { color: gray ! important; } .cmt b { color: gray ! important; }
I have no idea why I used such bad class names there 😛
Complementary HSL
copy const a = document.body .appendChild ( document.createElement ( 'div' ) ) , b = document.body .appendChild ( document.createElement ( 'div' ) ) ; let degA = degB = 0 ; const size = { width: '100px' , height: '100px' } ; Object .assign ( a.style , size) ; Object .assign ( b.style , size) ; function loop( ) { degA += 1 ; degB = degA + 180 ; a.style .background = `hsl( ${ degA} deg, 100 %, 50 % ) `; b.style .background = `hsl( ${ degB} deg, 100 %, 50 % ) `; requestAnimationFrame( loop) ; } loop( ) ;
Try it out…
In HSL a hue difference of 180 degrees between two values will create a set of complimentary colors.
Make a Grid
copy const cellSize = 25 ; const cols = 10 ; const rows = 20 ; function makeDot( x, y) { const dot = document.body .appendChild ( document.createElement ( 'div' ) ) ; dot.classList .add ( 'cell' ) ; Object .assign ( dot.style , { position: 'absolute' , left: `${ x} px`, top: `${ y} px`, width: `${ cellSize} px`, height: `${ cellSize} px`, outline: '1px solid black' , cursor: 'pointer' , background: 'gray' } ) ; return dot; } for ( let y = 0 ; y < rows; y++ ) { for ( let x = 0 ; x < cols; x++ ) { makeDot( x * cellSize, y * cellSize) ; } } // make a cell red when it is rolled over document.addEventListener ( 'mouseover' , e => { if ( e.target .classList .contains ( 'cell' ) ) { e.target .style .background = 'red' ; } } ) ;
Try it out…
Here is a simple example for arranging divs in a grid.
Proxy Quick DOM
copy const spec = { get ( o, key) { return o[ key] != null ? o[ key] : o[ key] = ( ...args ) => { const el = document.createElement ( key) ; args.forEach ( arg => { if ( typeof arg === 'string' ) { const span = document.createElement ( 'span' ) ; span.innerHTML = arg; el.appendChild ( span) ; } else if ( typeof arg === 'object' ) { if ( arg.tagName != null ) { el.appendChild ( arg) ; } else { for ( let i in arg) { el.setAttribute ( i, arg[ i] ) ; } } } } ) ; return el; } } , set ( o, key, v) { o[ key] = v; } } const dom = new Proxy( { } , spec) ; document.body .appendChild ( dom.div ( dom.button ( 'cool' ) , dom.h2 ( 'some text' , { style: 'font-style: italic' } ) , dom.br ( ) , dom.input ( { placeholder: 'zevan' } ) ) ) ; const { div, input, label } = dom; document.body .appendChild ( div( label( 'Slider:' , { for : 'slider' , style: 'padding:1em;display:block' } , input( { id: 'slider' , type: 'range' } ) ) ) ) ;
Try it out…
In this snippet a proxy is used that makes all html node tagNames
valid methods. Each method can take strings and HTMLElements
as arguments in any order to create a dom structure. This may look familiar to people who have looked a bit deeper into the inner workings of some of the popular UI libraries of the last decade.