functionality mostly there, synth applied to menu, layout working

This commit is contained in:
suroh 2023-10-28 21:15:28 +02:00
parent b33f264c61
commit c45be77272
10 changed files with 179 additions and 233 deletions

View File

@ -1,8 +1,14 @@
const pluginWebc = require('@11ty/eleventy-plugin-webc')
const markdownIt = require('markdown-it')
const mdla = require('markdown-it-link-attributes')
// node requires
const fs = require('fs')
// webc plugin
const pluginWebc = require('@11ty/eleventy-plugin-webc')
// markdown plugin
const markdownIt = require('markdown-it')
const mdla = require('markdown-it-link-attributes')
// ~> config start
module.exports = (config) => {
// webc
config.addPlugin(pluginWebc, {

View File

@ -16,8 +16,6 @@
<style @raw="getBundle('css')" webc:keep></style>
<script type="module" @raw="getBundle('js')" webc:keep></script>
<!-- javascript -->
<!-- <script src="../assets/js/script.js" type="module" webc:keep></script> -->
<!-- tracking -->
</head>

View File

@ -9,9 +9,7 @@ class NavLink extends HTMLElement {
span.nextSibling.remove()
}
this.nextSibling.remove()
}
}
customElements.define('nav-link', NavLink)

View File

@ -0,0 +1,125 @@
import { Synth } from '../../assets/js/synth.js'
class NavPrimary extends HTMLElement {
categories = []
subs = []
audioEngine = null
masterGain = null
menuVoices = {}
connectedCallback() {
this.setupAudio()
this.categories = this.querySelectorAll('nav-link')
this.subs = this.querySelectorAll('ul')
this.activate()
window.addEventListener('popstate', () => {
this.activate()
})
this.categories.forEach(n => {
this.setupVoice(n)
n.addEventListener('click', () => {
const category = n.attributes.getNamedItem('category')
const link = n.attributes.getNamedItem('link')
if (link) {
history.pushState({}, '', link.value)
location.pathname = link.value
} else if (category) {
location.hash = category.value
}
})
n.addEventListener('mouseenter', () => {
const menuItem = this.querySelector('#menuItem h1')
menuItem.textContent = n.dataset.name
this.menuVoices[n.dataset.name].noteOn()
menuItem.classList.add('active')
})
n.addEventListener('mouseleave', () => {
const menuItem = this.querySelector('#menuItem h1')
this.menuVoices[n.dataset.name].noteOff()
menuItem.classList.remove('active')
})
})
const audioEl = this.querySelector('.audioToggle')
audioEl.addEventListener('click', () => this.toggleAudio())
}
activate() {
let active, toOpen
this.categories.forEach(c => {
const { value } = c.attributes.getNamedItem('category') || false
if (c.classList.contains('active')) {
c.classList.remove('active')
} else if (value == location.hash.replace('#', '')) {
c.classList.add('active')
}
})
this.subs.forEach(s => {
const { name } = s.dataset
if (name == location.hash.replace('#', '') || name == location.pathname) {
toOpen = s
} else if (s.classList.contains('active')){
active = s
}
})
if (active) {
active.addEventListener('transitionend', () => {
toOpen.classList.add('active')
}, { once: true })
active.classList.remove('active')
} else if (toOpen) {
toOpen.classList.add('active')
}
}
setupAudio() {
// AUDIO SETUP
this.audioEngine = new (window.AudioContext || window.webkitAudioContext)()
this.audioEngine.suspend()
this.masterGain = this.audioEngine.createGain()
this.masterGain.gain.value = 0.9
this.masterGain.connect(this.audioEngine.destination)
}
toggleAudio() {
const audioEl = this.querySelector('.audioToggle')
if (this.audioEngine.state == 'suspended') {
this.audioEngine.resume()
audioEl.classList.add('active')
} else {
this.audioEngine.suspend()
audioEl.classList.remove('active')
}
}
setupVoice(el) {
// create synthVoices per navItem
this.menuVoices[el.dataset.name] = new Synth(this.audioEngine)
this.menuVoices[el.dataset.name].gain.connect(this.masterGain)
}
}
customElements.define('nav-primary', NavPrimary)

View File

@ -1,5 +1,5 @@
<nav id="primary">
<nav-link link="/" data-name="~"><~</nav-link>
<nav-link link="/" data-name="<~"><~</nav-link>
<nav-link webc:for="c in categories" :category="c" :data-name="c"></nav-link>
<button class="audioToggle"></button>
@ -13,7 +13,7 @@
</ul>
</nav>
<section style="position: fixed; bottom: 0; left: 0; margin: 0; padding: 0; width: 100vw; height: 0px; overflow: visible; z-index: 100;mix-blend-mode: difference;">
<section id="menuItem" style="">
<h1 id="menuItem"></h1>
</section>
@ -21,76 +21,17 @@
<span>top</span>
</nav>
<script type="module">
class NavPrimary extends HTMLElement {
categories = []
subs = []
connectedCallback() {
this.categories = this.querySelectorAll('nav-link')
this.subs = this.querySelectorAll('ul')
this.activate()
window.addEventListener('popstate', (evt) => {
this.activate()
})
this.categories.forEach(n => {
n.addEventListener('click',() => {
const category = n.attributes.getNamedItem('category')
const link = n.attributes.getNamedItem('link')
if (link) {
history.pushState({}, '', link.value)
location.pathname = link.value
} else if (category) {
location.hash = category.value
}
})
})
}
activate() {
this.categories.forEach(i => {
const { value } = i.attributes.getNamedItem('category') || i.attributes.getNamedItem('link')
if (value != '/' && (value == location.hash.replace('#', '') || value == location.pathname)) {
i.classList.add('active')
} else {
i.classList.remove('active')
}
})
this.subs.forEach(s => {
const { name } = s.dataset
if (name == location.hash.replace('#', '') || name == location.pathname) {
s.classList.add('active')
} else {
s.classList.remove('active')
}
})
}
}
customElements.define('nav-primary', NavPrimary)
</script>
<script src="nav-primary.js" type="module"></script>
<style webc:scoped>
/* => CONTAINER */
nav {
display: flex;
gap: 0.25em;
margin: 1em var(--page-margin-inline) 0.5em;
font-size: 1.5em;
}
/* => LINKS */
nav-link {
padding-inline: 0.125em;
}
/* => AUDIO TOGGLE */
.audioToggle {
background: none;
@ -130,4 +71,38 @@ nav-link {
ul.active {
max-height: 50vh !important;
}
/* => POPUP TITLE */
#menuItem {
position: fixed;
bottom: 0;
left: 0;
margin: 0;
padding: 0;
width: 100vw;
height: 0px;
overflow: visible;
z-index: 100;
mix-blend-mode: difference;
}
#menuItem h1 {
position: absolute;
line-height: inherit;
bottom: -500px;
margin: 0;
padding: 0;
font-size: 33vw;
opacity: 0;
transform: translateY(100px);
transform-origin: bottom left;
mix-blend-mode: difference;
transition: opacity ease-in-out 0.1s, transform ease-in-out 0.1s;
}
#menuItem h1.active {
mix-blend-mode: difference;
opacity: 1 !important;
transform: translateY(-600px) !important;
}
</style>

View File

@ -3,14 +3,14 @@ layout: base.webc
---
<section class="page">
<div :if="imgFeat" class="imgFeat">
<img src="{{imgFeat}}" alt="">
<div webc:if="imgFeat" class="imgFeat">
<img :src="imgFeat" alt="">
</div>
<section class="text {{url}}" @raw="content">
<section class="text" @raw="content">
</section>
<section :if="gallery" class="imgs">
<img for="img of gallery" src="{{img}}" alt="">
<section webc:if="gallery" class="imgs">
<img webc:for="img of gallery" :src="img" alt="">
</section class="imgs">
</section>

View File

@ -114,27 +114,6 @@ nav#toTop.active > span:hover {
cursor: pointer;
}
h1#menuItem {
position: absolute;
line-height: inherit;
bottom: -500px;
margin: 0;
padding: 0;
font-size: 33vw;
opacity: 0;
transform: translateY(100px);
transform-origin: bottom left;
mix-blend-mode: difference;
transition: opacity ease-in-out 0.1s, transform ease-in-out 0.1s;
}
h1#menuItem.active {
mix-blend-mode: difference;
opacity: 1 !important;
transform: translateY(-600px) !important;
}
/* --> MAINPAGE CONSTRUCTION <-- */
nav#sub > ul {
margin: 0;

View File

@ -1,123 +0,0 @@
import {Synth} from '/assets/js/synth.js'
// audio for events
// AUDIO SETUP
const audioEngine = new (window.AudioContext || window.webkitAudioContext)()
audioEngine.suspend()
const masterGain = audioEngine.createGain()
const audioEl = document.querySelector('#audioToggle')
let audioAllowed = true
masterGain.gain.value = 0.9
masterGain.connect(audioEngine.destination)
const audioToggle = () => {
audioEl.classList.toggle('active')
if (audioEngine.state == 'suspended') {
audioEngine.resume()
audioAllowed = true
} else {
audioEngine.suspend()
audioAllowed = false
}
}
const audioEnable = () => {
if (audioEngine.state == 'suspended' && audioAllowed) {
audioEngine.resume()
}
}
audioEl.addEventListener('click', audioToggle)
// NAVIGATION
let primaryNav = document.querySelectorAll('nav#primary>span')
let subNav = document.querySelector('nav#sub')
let menuItem = document.querySelector('#menuItem')
let menuVoices = []
// check if any primaryNav items are active
const primaryActive = () => {
let active = false
for (let n of primaryNav) {
if (n.classList.contains('active')) {
active = true
}
}
return active
}
for (let n of primaryNav) {
// remove shitty firefox span spacing
n.nextSibling.parentNode.removeChild(n.nextSibling)
// create synthVoices per navItem
menuVoices[n.dataset.link] = new Synth(audioEngine)
menuVoices[n.dataset.link].gain.connect(masterGain)
// primary navigation click events
n.addEventListener('click', (e) => {
for (let _n of primaryNav) {
if (n === _n && n.dataset.link != '~') {
n.classList.toggle('active')
} else if (n.dataset.link == '~') {
window.location.href = '/'
} else {
_n.classList.remove('active')
}
}
// subnav is nav element
if (primaryActive()) {
subNav.classList.add('active')
} else {
subNav.classList.remove('active')
}
for (let s of subNav.children) {
if (s.id == n.dataset.link && primaryActive()) {
s.classList.add('active')
} else {
s.classList.remove('active')
}
}
})
// mouseover on primary nav for big botom text
n.addEventListener('mouseenter', () => {
// unsuspend sound on mouseenter
audioEnable()
if (n.dataset.link == '~') {
menuItem.textContent = '\u003C\u007E'
} else {
menuItem.textContent = n.dataset.link
}
menuItem.className = 'active'
menuVoices[n.dataset.link].noteOn()
})
n.addEventListener('mouseout', () => {
menuItem.className = 'inactive'
menuVoices[n.dataset.link].noteOff()
})
}
// SCROLL TO TOP NAVIGATION
const toTop = document.querySelector('nav#toTop')
toTop.addEventListener('click', (e) => {
window.scrollTo(0,0)
})
window.addEventListener('scroll', (e) => {
let scrollY = window.scrollY
if (scrollY > 50) {
toTop.classList.add('active')
} else {
toTop.classList.remove('active')
}
})

View File

@ -1,11 +0,0 @@
// importing scripts
import '/assets/js/interaction.js'
// 'page' load transitions
const pageSection = document.querySelector('section.page')
pageSection.addEventListener('load', (e) => {
console.log('div loaded?')
console.log(e.target)
alert('ehllo')
})

View File

@ -60,5 +60,4 @@ export class Synth {
// release
this.modGain.gain.setTargetAtTime(0.8, this.audio.currentTime + 0.4, 0.5)
}
}