diff --git a/Gemfile.lock b/Gemfile.lock index 7b89849..74ad026 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -75,7 +75,7 @@ GEM minitest (>= 5.1) mutex_m tzinfo (~> 2.0) - acts_as_list (1.2.0) + acts_as_list (1.2.1) activerecord (>= 6.1) activesupport (>= 6.1) addressable (2.8.6) diff --git a/app/assets/stylesheets/application.css b/app/assets/stylesheets/application.css index 36991b6..1fa0bb5 100644 --- a/app/assets/stylesheets/application.css +++ b/app/assets/stylesheets/application.css @@ -84,6 +84,10 @@ --fs-xl: 2.8rem; --fs-2xl: 3.4rem; --fs-3xl: 5.6rem; + + --flip-deg: 0deg; + --flip-scale: 1; + --flip-rotate: 0deg; font: 10px/1.3 var(--ff-ikea); } @@ -132,6 +136,14 @@ header { main { margin: 0 1rem; + flex-grow: 1; +} + +footer { + font-size: 1.2rem; + line-height: 1.2; + margin: 1rem; + font-family: var(--ff-ikea); } .msg__container { @@ -362,7 +374,6 @@ input[type=range] { .link__branding { - & svg { width: 70px; height: auto; @@ -379,27 +390,48 @@ ul.card__stack { & a { text-decoration: none; color: var(--clr-black); + cursor: default; + } + } -.card, .link { - background-color: var(--clr-white); - box-shadow: var(--shadow); +.card-front, .card-back, .link { + background-color: var(--clr-white); border-radius: 12px; box-sizing: border-box; } -.card { +.card-front, .card-back, .link { + box-shadow: var(--shadow); +} + +.card__container { position: absolute; inset: 0 0 0 0; + transition: transform 0.3s ease-in-out 0s; + perspective: 500px; +} + +.card { + position: absolute; + inset: 0 0 0 0; + transform-style: preserve-3d; +} + +.card__container.active .card { + transform: rotateY(var(--flip-deg)) rotateX(var(--flip-rotate)) scale(var(--flip-scale)); + +} + +.card-front { + font-size: var(--fs-xl); font-weight: 700; display: grid; padding: 1.142857142857143em 1em; grid-template-rows: 1fr 4fr 1fr; justify-items: center; - - transition: transform 0.3s ease-in-out 0s; & div { text-align: center; @@ -421,6 +453,27 @@ ul.card__stack { } } +.card-back { + background-color: var(--clr-white); + transform: rotateY(180deg); + display: flex; + justify-content: center; + align-items: center; + + & svg { + width: 60%; + + } +} + +.card-back, .card-front { + position: absolute; + inset: 0 0 0 0; + backface-visibility: hidden; +} + + + .link { @@ -599,6 +652,10 @@ ul.card__stack { } } + footer { + margin: 2rem; + } + .icon__container img:nth-child(4) { display: block; } diff --git a/app/javascript/application.js b/app/javascript/application.js index 9a721b7..29d1ef4 100644 --- a/app/javascript/application.js +++ b/app/javascript/application.js @@ -9,7 +9,7 @@ function rand_in_range(from, to) { function shuffle_cards() { - const cards = document.querySelectorAll('.card') + const cards = document.querySelectorAll('.card__container') const card_ids = Array.from(cards).map(card => card.getAttribute('data-id')) let shown_cards = JSON.parse(localStorage.getItem('shown_cards')) || []; let cards_not_shown = card_ids.filter(id => !shown_cards.includes(id)); @@ -21,10 +21,10 @@ function shuffle_cards() { const random_id = cards_not_shown[Math.floor(Math.random() * cards_not_shown.length)]; cards.forEach((card) => { - if (card.getAttribute('data-id') == random_id) { - card.classList.add('active') + if (card.getAttribute('data-id') == random_id) { card.style.zIndex = '1' - card.style.transform = `none` + card.style.transform = '' + card.classList.add('active') } else { card.classList.remove('active') card.style.zIndex = 'auto' @@ -74,6 +74,13 @@ document.querySelectorAll('[data-share-title]').forEach((share_btn) => { }) }) +document.querySelectorAll('.card__stack a').forEach((card_link) => { + card_link.addEventListener('click', (e) => { + e.preventDefault() + }) +}) + + // Open all external links in ny tab for (const link of document.links) { if (link.hostname.replace(/^www\./i, "") != window.location.hostname.replace(/^www\./i, "") && (link.protocol == 'https:' || link.protocol == 'http:')) @@ -82,7 +89,7 @@ for (const link of document.links) { const input_range = document.getElementsByClassName('reveal')[0] -const max_value = 200 +const max_value = 180 const speed = 12 var curr_value @@ -103,7 +110,7 @@ function unlockEndHandler() { if (curr_value >= this.max) { - const card = document.querySelector('.card.active') + const card = document.querySelector('.card__container.active') window.location.href = card.parentNode.getAttribute('href') // reset @@ -118,7 +125,8 @@ function unlockEndHandler() { function animateHandler() { input_range.value = curr_value; - input_range.closest('.reveal__container').style.setProperty('--opacity', 1 - (input_range.value/input_range.max)); + input_range.closest('.reveal__container').style.setProperty('--opacity', 1 - (input_range.value/input_range.max)); + updateRotation(input_range.value) // continue? if (curr_value > -1) { @@ -135,7 +143,35 @@ if (input_range) { input_range.addEventListener('mouseup', unlockEndHandler, false) input_range.addEventListener('touchend', unlockEndHandler, false) - input_range.addEventListener("input", (e) => { + input_range.addEventListener("input", (e) => { e.currentTarget.closest('.reveal__container').style.setProperty('--opacity', 1 - (e.currentTarget.value/e.currentTarget.max)) + + updateRotation(e.currentTarget.value) }) +} + +function updateRotation(angle) { + document.documentElement.style.setProperty('--flip-deg', angle + 'deg') + + document.documentElement.style.setProperty('--flip-scale', calculateScaleFactor(angle)) + + document.documentElement.style.setProperty('--flip-rotate', calculateRotateFactor(angle) + 'deg') + +} + +const random_salt = Math.random() + +function calculateScaleFactor(angle) { + const radians = angle * (Math.PI / 180) + return 1 + (0.1 * Math.sin(radians)) + + // return 1 + (0.2 * (angle / 180)) +} + + + +function calculateRotateFactor(angle) { + const radians = angle * (Math.PI / 180) + return (4 * Math.sin(radians)) + (random_salt * 2) + } \ No newline at end of file diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb index 78d9a22..decf451 100644 --- a/app/views/layouts/application.html.erb +++ b/app/views/layouts/application.html.erb @@ -25,5 +25,7 @@
<%= yield %>
+ + diff --git a/app/views/site/tmpl_index.html.erb b/app/views/site/tmpl_index.html.erb index baa6b28..6cc36ca 100644 --- a/app/views/site/tmpl_index.html.erb +++ b/app/views/site/tmpl_index.html.erb @@ -21,10 +21,5 @@ #{rails_storage_proxy_url(asset.file.variant(resize_to_limit: [640,640]))} 3x ", loading: 'lazy' if asset&.file&.image? %> - <% end %> - - <%# image_tag 'windmill.png', width: 630, height: 963, loading: 'lazy', id: 'windmill' %> - <%# image_tag 'wase.png', width: 1024, height: 1024, id: 'wase' %> - - <%# image_tag 'ico-arrow-updown.svg', width: 124, height: 103, id: 'arrows' %> + <% end %> \ No newline at end of file diff --git a/app/views/site/tmpl_list.html.erb b/app/views/site/tmpl_list.html.erb index ed5ae73..8cbdd50 100644 --- a/app/views/site/tmpl_list.html.erb +++ b/app/views/site/tmpl_list.html.erb @@ -11,10 +11,17 @@
  • <%= link_to node.url do %> -
    - <%= tag.div node.tags[0] %> - <%= svg "ico-arrow-updown" %> - <%= tag.div node.tags[1] %> +
    +
    +
    + <%= svg "ico-arrow-updown" %> +
    +
    + <%= tag.div node.tags[0] %> + <%= svg "ico-arrow-updown" %> + <%= tag.div node.tags[1] %> +
    +
    <% end %>