You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

155 lines
4.9 KiB
Vue

3 years ago
<template>
<header>
<div class="headline">
<h1>Starsy</h1>
<p>Starsystem<br/>Generator</p>
</div>
<div class="options">
<label>
Title Font
<select v-model="selectedFont">
<option v-for="f in labelFonts">{{ f }}</option>
</select>
</label>
<label>
Color Theme
<select v-model="selectedTheme" @change="setTheme">
<option v-for="t in themes">{{ t }}</option>
</select>
</label>
</div>
</header>
<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="star.radius" :cx="starCX" cy="150" />
3 years ago
<g class="object" :id="o.name" v-for="o in objects">
3 years ago
<g class="rings" v-for="i in o.rings">
<circle :r="o.radius - 5 + 2*i" :cx="o.distance" cy="150" />
</g>
<text :class="{ tilted: o.radius < 10 }" :x="o.distance" :y="140 - o.radius">{{ o.name }}</text>
3 years ago
<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" />
3 years ago
3 years ago
<g class="moon" v-for="m,i in o.moons">
3 years ago
<rect v-if="m.type === 'station'" class="station" :x="o.distance - 2" :y="158 + o.radius + 10*i" width="4" height="4" />
<circle v-else :r="m.radius" :cx="o.distance" :cy="160 + o.radius + 10*i" />
3 years ago
<text :x="o.distance + 5" :y="162 + o.radius + 10*i">{{ m.name }}</text>
</g>
3 years ago
3 years ago
</g>
<text id="designation" :class="`title-${selectedFont}`" x="980" y="30">{{ star.designation }}</text>
3 years ago
</svg>
<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>
3 years ago
</template>
<script setup>
import { ref, reactive, computed } from 'vue'
import steepCurve from './steep-curve'
3 years ago
const star = reactive({
designation: 'Sol',
radius: 400,
})
3 years ago
const starCX = computed(() => -1 * star.radius * steepCurve(star.radius, 50, 0.955))
const objects = ref([
3 years ago
{ type: 'planet', name: 'Mercury', radius: 1, distance: 100, moons: [], rings: [] },
{ type: 'planet', name: 'Venus', radius: 4, distance: 120, moons: [], rings: [] },
3 years ago
{ type: 'planet', name: 'Terra', radius: 4, distance: 140, moons: [
3 years ago
{ name: 'ISS', type: 'station' },
3 years ago
{ name: 'Luna', radius: 2 },
3 years ago
], rings: 0 },
3 years ago
{ type: 'planet', name: 'Mars', radius: 2, distance: 160, moons: [
3 years ago
{ name: 'MTO', type: 'station' },
3 years ago
{ name: 'Phobos', radius: 1 },
{ name: 'Daimos', radius: 1 },
3 years ago
], rings: 0 },
3 years ago
{ type: 'planet', name: 'Jupiter', radius: 40, distance: 260, moons: [
{ name: 'Io', radius: 2 },
{ name: 'Europa', radius: 2 },
{ name: 'Ganymede', radius: 4 },
{ name: 'Callisto', radius: 3 },
3 years ago
], rings: 1 },
3 years ago
{ type: 'planet', name: 'Saturn', radius: 36, distance: 410, moons: [
{ name: 'Mimas', radius: 1 },
{ name: 'Enceladus', radius: 1 },
{ name: 'Tethys', radius: 1 },
{ name: 'Dione', radius: 1 },
{ name: 'Rhea', radius: 1 },
{ name: 'Titan', radius: 3 },
{ name: 'Iapetus', radius: 1 },
3 years ago
], rings: 5 },
3 years ago
{ type: 'planet', name: 'Uranus', radius: 16, distance: 680, moons: [
{ name: 'Miranda', radius: 1 },
{ name: 'Ariel', radius: 1 },
{ name: 'Umbriel', radius: 1 },
{ name: 'Titania', radius: 1 },
{ name: 'Oberon', radius: 1 },
3 years ago
], rings: 2 },
3 years ago
{ type: 'planet', name: 'Neptune', radius: 15, distance: 950, moons: [
{ name: 'Triton', radius: 1 },
3 years ago
], rings: [] },
])
const selectedObject = ref(null)
function toggleObject (obj) {
selectedObject.value = selectedObject.value === obj ? null : obj
}
3 years ago
const labelFonts = ['douar', 'lack', 'xolonium']
const selectedFont = ref('xolonium')
3 years ago
const themes = ['default', 'retro', 'inverse', 'paper']
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()
3 years ago
</script>