diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/App.vue | 52 | ||||
| -rw-r--r-- | src/components/TileTree.vue | 70 | ||||
| -rw-r--r-- | src/tol.json | 52 |
3 files changed, 107 insertions, 67 deletions
diff --git a/src/App.vue b/src/App.vue index 274ec13..5c7c293 100644 --- a/src/App.vue +++ b/src/App.vue @@ -1,47 +1,16 @@ <script> import tol from './tol.json'; +import TileTree from "./components/TileTree.vue"; export default { data() { return { - drawnTol: tol.map(e => ({...e, children:[]})), + //tree: tol.map(e => ({...e, children:[]})), + tree: tol, width: document.documentElement.clientWidth, height: document.documentElement.clientHeight, } }, - computed: { - tiles(){ - //minSize, maxSize, - let nodes = this.drawnTol; - let spacing = 5; - let numCols = this.pickNumCols(nodes.length, this.width/this.height); - let numRows = Math.ceil(nodes.length / numCols); - let tileSz = Math.min( - ((this.width - spacing) / numCols) - spacing, - ((this.height - spacing) / numRows) - spacing); - let res = nodes.map((el, idx) => ({ - name: el.name, - x: (idx % numCols)*(tileSz + spacing) + spacing, - y: Math.floor(idx / numCols)*(tileSz + spacing) + spacing, - sz: tileSz, - })); - console.log(res) - return res; - } - }, methods: { - pickNumCols(numTiles, aspectRatio){ //account for tile-spacing? - //find number of columns with corresponding aspect-ratio closest to aspectRatio - let closest, smallestDiff = Number.MAX_VALUE; - for (let numCols = 1; numCols <= numTiles; numCols++){ - let ratio = numCols/Math.ceil(numTiles/numCols); - let diff = Math.abs(ratio - aspectRatio); - if (diff < smallestDiff){ - smallestDiff = diff; - closest = numCols; - } - } - return closest; - }, onResize(){ this.width = document.documentElement.clientWidth; this.height = document.documentElement.clientHeight; @@ -52,19 +21,16 @@ export default { }, unmounted(){ window.removeEventListener('resize', this.onResize); + }, + components: { + TileTree } } </script> <template> - <div class="bg-black h-[100vh]"> - <img v-for="tile in tiles" :src="'/src/assets/' + tile.name + '.jpg'" :alt="tile.name" :id="tile.name" - :width="tile.sz" :height="tile.sz" - :style="{position: 'absolute', left: tile.x + 'px', top: tile.y + 'px'}" - class="transition-all duration-300 ease-out border-2 border-amber-900" - /> - </div> +<div class="h-[100vh]"> + <tile-tree :tree="tree" :x="0" :y="0" :width="width" :height="height" isRoot></tile-tree> +</div> </template> -<style> -</style> diff --git a/src/components/TileTree.vue b/src/components/TileTree.vue new file mode 100644 index 0000000..233eb3c --- /dev/null +++ b/src/components/TileTree.vue @@ -0,0 +1,70 @@ +<script> +export default { + name: "tile-tree", + data(){ + return { + TILE_SPACING: 5, + HEADER_SZ: 20, + } + }, + props: { + tree: Object, + x: Number, + y: Number, + width: Number, + height: Number, + isRoot: Boolean, + }, + computed: { + childTiles(){ //add minSize, maxSize, + if (this.tree.children && this.tree.children.length){ + let nodes = this.tree.children; + let hOffset = (this.isRoot ? 0 : this.HEADER_SZ); + let adjustedHeight = this.height - hOffset; + let numCols = this.pickNumCols(nodes.length, this.width/adjustedHeight); + let numRows = Math.ceil(nodes.length / numCols); + let tileSz = Math.min( + ((this.width - this.TILE_SPACING) / numCols) - this.TILE_SPACING, + ((adjustedHeight - this.TILE_SPACING) / numRows) - this.TILE_SPACING); + return nodes.map((el, idx) => ({ + node: el, + x: (idx % numCols)*(tileSz + this.TILE_SPACING) + this.TILE_SPACING, + y: Math.floor(idx / numCols)*(tileSz + this.TILE_SPACING) + this.TILE_SPACING + hOffset, + sz: tileSz, + })); + } + } + }, + methods: { + pickNumCols(numTiles, aspectRatio){ //account for tile-spacing? + //find number of columns with corresponding aspect-ratio closest to aspectRatio + let closest, smallestDiff = Number.MAX_VALUE; + for (let numCols = 1; numCols <= numTiles; numCols++){ + let ratio = numCols/Math.ceil(numTiles/numCols); + let diff = Math.abs(ratio - aspectRatio); + if (diff < smallestDiff){ + smallestDiff = diff; + closest = numCols; + } + } + return closest; + } + } +} +</script> + +<template> +<div v-if="tree.children && tree.children.length > 0" class="border border-black" + :style="{position: 'absolute', left: x + 'px', top: y + 'px', width: + width + 'px', height: height + 'px'}"> + <div v-if="!isRoot" :style="{height: HEADER_SZ + 'px'}" class="text-center">{{tree.name}}</div> + <tile-tree v-for="child in childTiles" :tree="child.node" + :x="child.x" :y="child.y" :width="child.sz" :height="child.sz" + ></tile-tree> +</div> +<img v-else + :src="'/src/assets/' + tree.name + '.jpg'" :alt="tree.name" + :style="{position: 'absolute', left: x + 'px', top: y + 'px'}" :width="width" :height="height" + class="transition-all duration-300 ease-out border-2 border-amber-900" + /> +</template> + diff --git a/src/tol.json b/src/tol.json index dff1f4c..4752253 100644 --- a/src/tol.json +++ b/src/tol.json @@ -1,24 +1,28 @@ -[ - {"name": "Viruses"}, - {"name": "Archaea"}, - {"name": "Bacteria", - "children":[ - {"name":"Cyanobacteria"}, - {"name":"Proteobacteria"} - ] - }, - {"name": "Eukaryota", - "children":[ - {"name":"Amoebozoa"}, - {"name":"Plantae"}, - {"name":"Fungi"}, - {"name":"Metazoa", - "children":[ - {"name":"Cnidaria"}, - {"name":"Arthropoda"}, - {"name":"Vertebrata"} - ] - } - ] - } -] +{ + "name": "Root", + "children":[ + {"name": "Viruses"}, + {"name": "Archaea"}, + {"name": "Bacteria", + "children":[ + {"name":"Cyanobacteria"}, + {"name":"Proteobacteria"} + ] + }, + {"name": "Eukaryota", + "children":[ + {"name":"Amoebozoa"}, + {"name":"Plantae"}, + {"name":"Fungi"}, + {"name":"Metazoa", + "children":[ + {"name":"Cnidaria"}, + {"name":"Arthropoda"}, + {"name":"Vertebrata"} + ] + } + ] + } + ] +} + |
