star system settings dialog

main
koehr 2 years ago
parent 58712b0edf
commit f7abc517eb

@ -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>

@ -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;
}

@ -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…
Cancel
Save