star system settings dialog
This commit is contained in:
parent
58712b0edf
commit
f7abc517eb
3 changed files with 140 additions and 13 deletions
69
src/App.vue
69
src/App.vue
|
@ -22,14 +22,14 @@
|
|||
|
||||
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" viewBox="0 0 1000 300">
|
||||
<line id="axis" x1="0" y1="150" x2="1000" y2="150" />
|
||||
<circle id="star" r="400" cx="-370" cy="150" />
|
||||
<circle id="star" :r="star.radius" :cx="starCX" cy="150" />
|
||||
|
||||
<g class="object" :id="o.name" v-for="o in objects">
|
||||
<g class="rings" v-for="i in o.rings">
|
||||
<circle :r="o.radius - 5 + 2*i" :cx="o.distance" cy="150" />
|
||||
</g>
|
||||
|
||||
<text :x="o.distance" :y="140 - o.radius">{{ o.name }}</text>
|
||||
<text :class="{ tilted: o.radius < 10 }" :x="o.distance" :y="140 - o.radius">{{ o.name }}</text>
|
||||
<circle v-if="o.type === 'planet'" :r="o.radius" :cx="o.distance" cy="150" />
|
||||
<line v-if="o.moons.length" :x1="o.distance" y1="150" :x2="o.distance" :y2="150 + o.radius + 10*o.moons.length" />
|
||||
|
||||
|
@ -41,20 +41,52 @@
|
|||
|
||||
</g>
|
||||
|
||||
<text id="label" :class="`title-${selectedFont}`" x="980" y="30">{{ label }}</text>
|
||||
<text id="designation" :class="`title-${selectedFont}`" x="980" y="30">{{ star.designation }}</text>
|
||||
</svg>
|
||||
|
||||
<div id="settings">
|
||||
</div>
|
||||
<section id="settings">
|
||||
<header>
|
||||
<h1>Star System Parameters</h1>
|
||||
<menu id="system-settings">
|
||||
<label>
|
||||
Name
|
||||
<input type="text" v-model="star.designation" />
|
||||
</label>
|
||||
<label>
|
||||
Star Size
|
||||
<input type="range" min="50" max="1500" v-model="star.radius" />
|
||||
({{ star.radius }})
|
||||
</label>
|
||||
</menu>
|
||||
</header>
|
||||
<menu id="object-list">
|
||||
<div class="menu-item" :class="{ open: selectedObject === o }" v-for="o in objects">
|
||||
<label @click="toggleObject(o)">{{ o.name }}</label>
|
||||
<div class="object-settings">
|
||||
<h2>{{ o.name }} settings</h2>
|
||||
<p>Distance from central star: {{ o.distance }}</p>
|
||||
<p>Radius: {{ o.radius }}</p>
|
||||
<p>Moons and Stations: {{ listMoons(o) }}</p>
|
||||
</div>
|
||||
</div>
|
||||
<button>add object</button>
|
||||
</menu>
|
||||
</section>
|
||||
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref } from 'vue'
|
||||
import { ref, reactive, computed } from 'vue'
|
||||
import steepCurve from './steep-curve'
|
||||
|
||||
const label = "Sol"
|
||||
const star = reactive({
|
||||
designation: 'Sol',
|
||||
radius: 400,
|
||||
})
|
||||
|
||||
const objects = [
|
||||
const starCX = computed(() => -1 * star.radius * steepCurve(star.radius, 50, 0.955))
|
||||
|
||||
const objects = ref([
|
||||
{ type: 'planet', name: 'Mercury', radius: 1, distance: 100, moons: [], rings: [] },
|
||||
{ type: 'planet', name: 'Venus', radius: 4, distance: 120, moons: [], rings: [] },
|
||||
{ type: 'planet', name: 'Terra', radius: 4, distance: 140, moons: [
|
||||
|
@ -91,10 +123,16 @@ const objects = [
|
|||
{ type: 'planet', name: 'Neptune', radius: 15, distance: 950, moons: [
|
||||
{ name: 'Triton', radius: 1 },
|
||||
], rings: [] },
|
||||
]
|
||||
])
|
||||
|
||||
const selectedObject = ref(null)
|
||||
|
||||
function toggleObject (obj) {
|
||||
selectedObject.value = selectedObject.value === obj ? null : obj
|
||||
}
|
||||
|
||||
const labelFonts = ['douar', 'lack', 'xolonium']
|
||||
const selectedFont = ref('lack')
|
||||
const selectedFont = ref('xolonium')
|
||||
|
||||
const themes = ['default', 'retro', 'inverse', 'paper']
|
||||
const selectedTheme = ref('default')
|
||||
|
@ -102,4 +140,15 @@ const selectedTheme = ref('default')
|
|||
function setTheme () {
|
||||
document.body.className = `theme-${selectedTheme.value}`
|
||||
}
|
||||
|
||||
function listMoons (obj) {
|
||||
if (!obj.moons || !obj.moons.length) return 'none'
|
||||
return obj.moons.reduce((acc, moon) => {
|
||||
let s = moon.name
|
||||
if (moon.type) s += ` (${moon.type})`
|
||||
acc.push(s)
|
||||
return acc
|
||||
}, []).join('; ')
|
||||
}
|
||||
setTheme()
|
||||
</script>
|
||||
|
|
76
src/app.css
76
src/app.css
|
@ -22,9 +22,12 @@
|
|||
:root {
|
||||
--bg-graphic: #000;
|
||||
--fg-graphic: #FFF;
|
||||
--hl-graphic: #FFB;
|
||||
--bg-app: #333;
|
||||
--fg-app: #EEE;
|
||||
--fill-star: #FFB;
|
||||
--bg-settings: var(--bg-graphic);
|
||||
--fg-settings: var(--fg-graphic);
|
||||
--title-font: xolonium;
|
||||
}
|
||||
|
||||
|
@ -45,37 +48,77 @@ body.theme-retro {
|
|||
--fg-app: #E4DCB5;
|
||||
--bg-graphic: #E4DCB5;
|
||||
--fg-graphic: #4B4839;
|
||||
--hl-graphic: #222;
|
||||
--fill-star: var(--fg-graphic);
|
||||
--bg-settings: var(--bg-graphic);
|
||||
--fg-settings: var(--fg-graphic);
|
||||
}
|
||||
body.theme-inverse {
|
||||
--bg-app: #333;
|
||||
--fg-app: #E4DCB5;
|
||||
--bg-graphic: #4B4839;
|
||||
--fg-graphic: #E4DCB5;
|
||||
--hl-graphic: #FF0;
|
||||
--fill-star: var(--fg-graphic);
|
||||
--bg-settings: var(--bg-graphic);
|
||||
--fg-settings: var(--fg-graphic);
|
||||
}
|
||||
body.theme-paper {
|
||||
--bg-app: #FFF;
|
||||
--fg-app: #000;
|
||||
--bg-graphic: #FFF;
|
||||
--fg-graphic: #000;
|
||||
--hl-graphic: #555;
|
||||
--fill-star: var(--fg-graphic);
|
||||
--bg-settings: #DDD;
|
||||
--fg-settings: #000;
|
||||
}
|
||||
|
||||
.title-douar { font-family: 'douar'; }
|
||||
.title-lack { font-family: 'lack'; }
|
||||
.title-xolonium { font-family: 'xolonium'; }
|
||||
|
||||
.menu-item {
|
||||
padding: 1em;
|
||||
}
|
||||
.menu-item > label {
|
||||
cursor: pointer;
|
||||
}
|
||||
.menu-item > label::before {
|
||||
content: "▸ ";
|
||||
}
|
||||
.menu-item.open > label::before {
|
||||
content: "▾ ";
|
||||
}
|
||||
.menu-item.open {
|
||||
background: var(--bg-settings);
|
||||
color: var(--fg-settings);
|
||||
}
|
||||
.menu-item > .object-settings {
|
||||
display: none;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
width: calc(100vw - 4em);
|
||||
margin-top: 1em;
|
||||
padding: 1em 2em;
|
||||
background: var(--bg-graphic);
|
||||
}
|
||||
.menu-item.open > .object-settings {
|
||||
display: block;
|
||||
}
|
||||
|
||||
svg { background: var(--bg-graphic); }
|
||||
line { stroke: var(--fg-graphic); }
|
||||
text.tilted { transform: rotate(-45deg) translate(0, 100%); transform-origin: left top; transform-box: fill-box; }
|
||||
#axis { stroke-width: 1; }
|
||||
#label { fill: var(--fg-graphic); text-anchor: end; }
|
||||
#designation { fill: var(--fg-graphic); text-anchor: end; }
|
||||
#star { fill: var(--fill-star); }
|
||||
.object { fill: var(--fg-graphic); text-anchor: middle; font-size: .6em; }
|
||||
.moon { text-anchor: start; font-size: .7em; }
|
||||
.object { fill: var(--fg-graphic); text-anchor: middle; font-size: .6em; cursor: pointer; }
|
||||
.object > line { stroke-width: .5; }
|
||||
.moon { text-anchor: start; font-size: .7em; }
|
||||
.rings { stroke: var(--fg-graphic); fill: none; transform: skew(-45deg); transform-origin: 50%; }
|
||||
.object:hover { fill: var(--hl-graphic); }
|
||||
.object:hover > line, .object:hover .rings { stroke: var(--hl-graphic); }
|
||||
|
||||
h1 {
|
||||
font-family: xolonium;
|
||||
|
@ -98,3 +141,30 @@ h1 {
|
|||
#settings {
|
||||
padding: 1em 2em;
|
||||
}
|
||||
#settings > header {
|
||||
display: flex;
|
||||
}
|
||||
#settings > header > h1 {
|
||||
min-width: 330px;
|
||||
}
|
||||
|
||||
#system-settings, #object-list {
|
||||
display: flex;
|
||||
width: calc(100vw - 4em);
|
||||
padding: 0;
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
#system-settings > label {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
min-width: 300px;
|
||||
margin: 0 1em;
|
||||
}
|
||||
#system-settings input {
|
||||
width: 220px;
|
||||
}
|
||||
#system-settings input[type="text"] {
|
||||
margin-left: 1em;
|
||||
padding: .5em 1em .4em;
|
||||
}
|
||||
|
|
8
src/steep-curve.js
Normal file
8
src/steep-curve.js
Normal file
|
@ -0,0 +1,8 @@
|
|||
// Thank you Ingo for your tremendous help with this one.
|
||||
|
||||
// This function returns a steep curve from [minX,0] to [infinity,maxY]
|
||||
// inc is tuned for x-values between minX and minX+100 describing a gentle curve
|
||||
export default function steepCurve (x, minX, maxY, inc=0.01) {
|
||||
// f(x) = maxY * (1 - e^(-(inc*x)+minX*inc))
|
||||
return maxY * (1 - Math.E ** (-(inc*x) + minX*inc))
|
||||
}
|
Loading…
Add table
Reference in a new issue