diff --git a/404.md b/404.md index 65c076d..e21e09f 100644 --- a/404.md +++ b/404.md @@ -4,8 +4,12 @@ - - + + + + + + - - - - - - + @@ -47,7 +46,7 @@ }) (window, document, "script", "https://mc.yandex.ru/metrika/tag.js", "ym"); - ym(79722217, "init", { + ym(89252711, "init", { clickmap: true, trackLinks: true, accurateTrackBounce: true, @@ -60,12 +59,12 @@ - + diff --git a/CNAME b/CNAME new file mode 100644 index 0000000..db815ff --- /dev/null +++ b/CNAME @@ -0,0 +1 @@ +wavelovers.ru \ No newline at end of file diff --git a/README.md b/README.md index 702f523..d950d2f 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # Wavelovers -Wavelovers in ***Javascript***, ***HTML*** and ***CSS*** **[[rep](https://github.com/eugene-serb/wavelovers/), [site](https://eugene-serb.github.io/wavelovers/)]**. +Wavelovers in ***Javascript***, ***HTML*** and ***CSS*** **[[rep](https://github.com/eugene-serb/wavelovers/), [site](https://wavelovers.ru/)]**. -This is a Wavelovers that can make a vibration massager from your gamepad. +This is Wavelovers, which can make a vibrating massager out of a gamepad. It has 16 free vibration patterns to play with. If you are interested in this or my other projects, or would like to suggest and share ideas with me, or just talk to me, contact me: *[@eugene_serb](https://t.me/eugene_serb)* diff --git a/about.html b/about.html new file mode 100644 index 0000000..029846c --- /dev/null +++ b/about.html @@ -0,0 +1,150 @@ + + + + Wavelovers – About + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+ +
+ +
+
+ +
+

Wavelovers – Feedback

+
+
+

Feedback

+

Hi! I am the author and developer of Wavelovers app and I want to thank you for using this app. If you have any ideas or wishes, you can write to me.

+
+ Write me: + eugene.serb@gmail.com +
+ Visit my homepage: + eugene-serb.github.io +
+ Follow me on Twitter: + @eugene_serb +
+
+

Advertising and collaboration

+ If you have advertising suggestions, please mail me: + eugene.serb@gmail.com +
+ +
+
+ + + + + + + + diff --git a/assets/patterns.json b/assets/patterns.json new file mode 100644 index 0000000..1d4dca8 --- /dev/null +++ b/assets/patterns.json @@ -0,0 +1,234 @@ +[ + { + "name": "Dotted Weak", + "type": "Simple", + "icon": "😌", + "pattern": [ + { + "startDelay": 100, + "duration": 100, + "weakMagnitude": 1.0, + "strongMagnitude": 0.0 + } + ] + }, + { + "name": "Dotted Strong", + "type": "Simple", + "icon": "😉", + "pattern": [ + { + "startDelay": 100, + "duration": 100, + "weakMagnitude": 0.0, + "strongMagnitude": 1.0 + } + ] + }, + { + "name": "Dotted AC", + "type": "Simple", + "icon": "🤨", + "pattern": [ + { + "startDelay": 100, + "duration": 100, + "weakMagnitude": 1.0, + "strongMagnitude": 0.0 + }, + { + "startDelay": 100, + "duration": 100, + "weakMagnitude": 0.0, + "strongMagnitude": 1.0 + } + ] + }, + { + "name": "Dotted Max", + "type": "Simple", + "icon": "🙃", + "pattern": [ + { + "startDelay": 100, + "duration": 100, + "weakMagnitude": 1.0, + "strongMagnitude": 1.0 + } + ] + }, + { + "name": "Short Dashed Weak", + "type": "Simple", + "icon": "🙂", + "pattern": [ + { + "startDelay": 100, + "duration": 250, + "weakMagnitude": 1.0, + "strongMagnitude": 0.0 + } + ] + }, + { + "name": "Short Dashed Strong", + "type": "Simple", + "icon": "😇", + "pattern": [ + { + "startDelay": 100, + "duration": 250, + "weakMagnitude": 0.0, + "strongMagnitude": 1.0 + } + ] + }, + { + "name": "Short Dashed AC", + "type": "Simple", + "icon": "🤤", + "pattern": [ + { + "startDelay": 100, + "duration": 250, + "weakMagnitude": 1.0, + "strongMagnitude": 0.0 + }, + { + "startDelay": 100, + "duration": 250, + "weakMagnitude": 0.0, + "strongMagnitude": 1.0 + } + ] + }, + { + "name": "Short Dashed Max", + "type": "Simple", + "icon": "😊", + "pattern": [ + { + "startDelay": 100, + "duration": 250, + "weakMagnitude": 1.0, + "strongMagnitude": 1.0 + } + ] + }, + { + "name": "Long Dashed Weak", + "type": "Simple", + "icon": "😋", + "pattern": [ + { + "startDelay": 100, + "duration": 500, + "weakMagnitude": 1.0, + "strongMagnitude": 0.0 + } + ] + }, + { + "name": "Long Dashed Strong", + "type": "Simple", + "icon": "😜", + "pattern": [ + { + "startDelay": 100, + "duration": 500, + "weakMagnitude": 0.0, + "strongMagnitude": 1.0 + } + ] + }, + { + "name": "Long Dashed AC", + "type": "Simple", + "icon": "😝", + "pattern": [ + { + "startDelay": 100, + "duration": 500, + "weakMagnitude": 1.0, + "strongMagnitude": 0.0 + }, + { + "startDelay": 100, + "duration": 500, + "weakMagnitude": 0.0, + "strongMagnitude": 1.0 + } + ] + }, + { + "name": "Long Dashed Max", + "type": "Simple", + "icon": "🤪", + "pattern": [ + { + "startDelay": 100, + "duration": 500, + "weakMagnitude": 1.0, + "strongMagnitude": 1.0 + } + ] + }, + { + "name": "Constant Weak", + "type": "Simple", + "icon": "😏", + "pattern": [ + { + "startDelay": 0, + "duration": 1000, + "weakMagnitude": 1.0, + "strongMagnitude": 0.0 + } + ] + }, + { + "name": "Constant Strong", + "type": "Simple", + "icon": "🤩", + "pattern": [ + { + "startDelay": 0, + "duration": 1000, + "weakMagnitude": 0.0, + "strongMagnitude": 1.0 + } + ] + }, + { + "name": "Constant AC", + "type": "Simple", + "icon": "😵", + "pattern": [ + { + "startDelay": 0, + "duration": 1000, + "weakMagnitude": 1.0, + "strongMagnitude": 0.0 + }, + { + "startDelay": 0, + "duration": 1000, + "weakMagnitude": 0.0, + "strongMagnitude": 1.0 + } + ] + }, + { + "name": "Constant Max", + "type": "Simple", + "icon": "😍", + "pattern": [ + { + "startDelay": 0, + "duration": 1000, + "weakMagnitude": 1.0, + "strongMagnitude": 1.0 + } + ] + } +] \ No newline at end of file diff --git a/css/styles.css b/css/styles.css index 8a1b61f..a5dc864 100644 --- a/css/styles.css +++ b/css/styles.css @@ -26,21 +26,36 @@ --color-e: #B3DEE2; } +:root { + /* Base numbers */ + --number-border-radius: 8px; + --number-border-size: 2px; +} + @media (prefers-color-scheme: light) { :root { + /* Base colors */ + --color-border: var(--color-a); --color-background: var(--color-white); - --color-content-background: var(--color-milk); - --color-logo: var(--color-white); - --color-header: var(--color-coal); --color-text: var(--color-coal); + --color-text-header: var(--color-coal); --color-link: var(--color-b); --color-link-hover: var(--color-a); - --color-border: var(--color-a); --color-selection: var(--color-b); - --color-table-header-background: transparent; - --color-table-header-text: transparent; - --color-table-item: transparent; - --color-anotation: var(--color-coal); + --color-fieldset-border: var(--color-c); + --color-table-header-background: var(--color-b); + --color-table-header-text: var(--color-white); + --color-table-item: var(--color-c); + /* Components colors */ + --color-header-background: var(--color-b); + --color-header-borderline: var(--color-a); + --color-header-selection: var(--color-a); + --color-header-logo: var(--color-white); + --color-header-navigation-link: var(--color-white); + --color-header-navigation-link-hover: var(--color-white); + --color-footer-borderline: var(--color-a); + --color-footer-text: var(--color-coal); + --color-content-item-background: var(--color-milk); --color-pattern-button: var(--color-c); --color-pattern-text: var(--color-white); } @@ -48,19 +63,28 @@ @media (prefers-color-scheme: dark) { :root { + /* Base colors */ + --color-border: var(--color-a); --color-background: var(--color-coal); - --color-content-background: var(--color-c); - --color-logo: var(--color-white); - --color-header: var(--color-coal); --color-text: var(--color-coal); + --color-text-header: var(--color-coal); --color-link: var(--color-b); --color-link-hover: var(--color-a); - --color-border: var(--color-a); --color-selection: var(--color-b); - --color-table-header-background: transparent; - --color-table-header-text: transparent; - --color-table-item: transparent; - --color-anotation: var(--color-milk); + --color-fieldset-border: var(--color-c); + --color-table-header-background: var(--color-b); + --color-table-header-text: var(--color-white); + --color-table-item: var(--color-c); + /* Components colors */ + --color-header-background: var(--color-b); + --color-header-borderline: var(--color-a); + --color-header-selection: var(--color-b); + --color-header-logo: var(--color-white); + --color-header-navigation-link: var(--color-white); + --color-header-navigation-link-hover: var(--color-white); + --color-footer-borderline: var(--color-a); + --color-footer-text: var(--color-milk); + --color-content-item-background: var(--color-c); --color-pattern-button: var(--color-milk); --color-pattern-text: var(--color-black); } @@ -85,12 +109,17 @@ body { background: var(--color-selection); } +:focus { + border-bottom: 2px solid var(--color-selection); +} + :focus-visible { outline: 2px solid var(--color-selection); + border-color: transparent; } h1, h2, h3, h4, h5, h6 { - color: var(--color-header); + color: var(--color-text-header); font-weight: 500; margin-block-start: 0.382em; margin-block-end: 0.618em; @@ -140,9 +169,21 @@ hr { margin-block-end: 0.5em; } +legend { + padding: 2px 4px; + text-align: left; +} + +fieldset { + border: 2px solid var(--color-border-alpha); + border-radius: 4px; + padding: 8px; +} + button, input, textarea, select { padding: 4px 8px; border: 2px solid var(--color-link); + border-radius: var(--number-border-radius); background: var(--color-milk); color: var(--color-text); font-size: 16px; @@ -168,15 +209,38 @@ option { color: var(--color-white); } -fieldset { - border: 2px solid var(--color-border-alpha); - border-radius: 4px; +/* ------ */ +/* TABLES */ +/* ------ */ + +table, th, td { + width: 100%; padding: 8px; + border-collapse: collapse; + table-layout: fixed; + font-weight: 400; } -legend { - padding: 2px 4px; - text-align: left; +.table_pink thead { + border-bottom: 4px solid var(--color-table-item); +} + + .table_pink thead > tr { + background-color: var(--color-table-header-background); + color: var(--color-table-header-text); + } + + .table_pink thead > tr > th { + font-weight: 500; + } + +.table_pink tbody > tr:nth-child(even) { + background-color: var(--color-table-item); + color: var(--color-white); +} + +.table_pink tfoot { + border-top: 4px solid var(--color-table-header-background); } /* ------------- */ @@ -208,33 +272,32 @@ legend { padding-right: 16px; } -/* ------ */ -/* BANNER */ -/* ------ */ - -.banner-container { - min-height: 100vh; - display: flex; -} - -.banner { - margin: auto; - padding: 16px; -} - -/* ------------ */ -/* ITEMS STYLES */ -/* ------------ */ +/* ----------------- */ +/* COMPONENTS STYLES */ +/* ----------------- */ /* ------ */ /* HEADER */ /* ------ */ .header { - border-bottom: 32px solid var(--color-border); - background: var(--color-b); + border-bottom: 32px solid var(--color-header-borderline); + background: var(--color-header-background); } + .header ::selection { + background: var(--color-header-selection); + } + + .header :focus { + border-bottom: 2px solid var(--color-header-navigation-link-hover); + } + + .header :focus-visible { + outline: 2px solid var(--color-header-navigation-link-hover); + border-color: transparent; + } + .header-wrapper { padding-top: 64px; padding-bottom: 16px; @@ -247,19 +310,8 @@ legend { .logo-wrapper__logo { font-size: 48px; font-weight: 500; - color: var(--color-logo); -} - - .logo-wrapper__logo::selection { - background-color: var(--color-a); - } - -@media only screen and (min-width: 540px) { - .logo-wrapper__logo { - font-size: 64px; - font-weight: 500; - color: var(--color-logo); - } + color: var(--color-header-logo); + cursor: default; } .menu-wrapper { @@ -271,7 +323,10 @@ legend { padding: 0; list-style-type: none; display: flex; + flex-direction: row; + flex-wrap: wrap; justify-content: space-between; + gap: 8px; } .navigation__item { @@ -280,58 +335,40 @@ legend { } .navigation__item a { - color: var(--color-logo); + border-color: transparent; + color: var(--color-header-navigation-link); } .navigation__item a:hover { - color: var(--color-logo); - border-color: var(--color-logo); - } - - .navigation__item a::selection { - background: var(--color-a); + border-color: var(--color-header-navigation-link-hover); + color: var(--color-header-navigation-link-hover); } @media only screen and (min-width: 720px) { .header-wrapper { - display: grid; - grid-template-columns: 1fr 1fr; - gap: 32px; + display: flex; + flex-direction: row; + flex-wrap: nowrap; + justify-content: space-between; + gap: 64px; } .logo-wrapper { - grid-column: 1 / 2; - grid-row: 1 / 2; + width: 50%; text-align: left; } .menu-wrapper { + width: 50%; margin-top: 0px; - grid-column: 2 / 3; - grid-row: 1 / 2; align-self: flex-end; } } -/* ----------------------------------- */ -/* MAIN, PAGE FLOW AND CONTENT SECTION */ -/* ----------------------------------- */ - -.page { - flex-grow: 1; - margin-top: 64px; - margin-bottom: 64px; -} - -.content { - margin-bottom: 16px; - padding: 32px; - border-radius: 8px; - background: var(--color-content-background); -} - -.content__header { - text-align: center; +@media only screen and (min-width: 1024px) { + .logo-wrapper__logo { + font-size: 64px; + } } /* ------ */ @@ -339,56 +376,121 @@ legend { /* ------ */ .footer { - border-top: 4px solid var(--color-a); - background: var(--color-background); + border-top: 4px solid var(--color-footer-borderline); } + .footer span { + color: var(--color-footer-text); + } + .footer-wrapper { padding-top: 32px; padding-bottom: 32px; display: flex; flex-direction: row; - justify-content: space-between; flex-wrap: wrap; + justify-content: space-between; gap: 32px; } - .annotation__text { - color: var(--color-anotation); +.created-by { + align-self: flex-end; +} + + .created-by > span { + padding-right: 8px; } - .created-by { - align-self: end; + .created-by > a { + font-size: 32px; } - .created-by > span { - padding-right: 8px; - } +/* ---- */ +/* PAGE */ +/* ---- */ - .created-by > a { - font-size: 32px; - } +.page { + flex-grow: 1; + margin-top: 64px; + margin-bottom: 64px; +} - .created-by > a:hover { - border: none; - } +/* ---- */ +/* POST */ +/* ---- */ + +.post { + margin: 0 auto; +} + +.post__header { + text-align: center; + margin-block-end: 32px; +} + +/* ------- */ +/* CONTENT */ +/* ------- */ + + +.content { + margin-bottom: 64px; +} + +.content__header { + margin-top: 0; + margin-bottom: 32px; + padding-left: 16px; + border: 2px solid var(--color-content-borderline); + border-radius: var(--number-border-radius); + color: var(--color-text-header); + font-size: 1.8em; +} + +.content-item { + margin-bottom: 16px; + padding: 32px; + border-radius: var(--number-border-radius); + background: var(--color-content-item-background); +} + + .content-item__header { + margin-bottom: 16px; + text-align: center; + } /* ----------- */ -/* WAVE MASTER */ +/* WAVELOVERS */ /* ----------- */ .wavelovers { display: flex; - flex-direction: column; + flex-direction: column-reverse; justify-content: flex-start; gap: 16px; } + @media only screen and (min-width: 540px) { + .wavelovers { + flex-direction: column; + } + } + .message { + width: 100%; + display: flex; + flex-direction: column; + justify-content: center; text-align: center; - font-size: 24px; + font-size: 16px; } + @media only screen and (min-width: 540px) { + .message { + font-size: 24px; + } + } + .pattern-box { display: flex; flex-direction: column; @@ -398,37 +500,43 @@ legend { .pattern-list { display: flex; flex-direction: row; - justify-content: space-between; + justify-content: space-around; flex-wrap: wrap; gap: 32px; } .pattern-item { - width: 300px; - height: 64px; - padding: 16px; - border-radius: 8px; + width: 100%; + height: 48px; + padding: 8px; + border-radius: var(--number-border-radius); background: var(--color-pattern-button); display: flex; flex-direction: row; justify-content: flex-start; - gap: 32px; + gap: 16px; align-items: center; text-align: center; overflow: hidden; cursor: default; } + @media only screen and (min-width: 540px) { + .pattern-item { + width: 200px; + } + } + .pattern-item__selected { background: var(--color-b); } .pattern-item__icon{ - font-size: 32px; + font-size: 24px; } .pattern-item__name { - font-size: 18px; + font-size: 14px; white-space: nowrap; overflow: hidden; color: var(--color-pattern-text); @@ -469,50 +577,34 @@ legend { color: var(--color-white); } -.controls-box { - display: flex; - flex-direction: row; - justify-content: space-around; - flex-wrap: wrap; - gap: 32px; +.link_hash { + word-break: break-all; } - .controls-box__item { - display: flex; - flex-direction: column; - text-align: center; - gap: 8px; - } - - .controls-box__item > span { - font-size: 24px; - } - -.gamepad-button-container { - display: flex; - flex-direction: row; - justify-content: center; - align-items: center; - gap: 8px; +.faq__ask { + font-size: 18px; + font-weight: 500; } - .gamepad-button { - width: 4ch; - height: 4ch; - border: 1px solid black; - border-radius: 100%; - display: flex; - justify-content: center; - align-items: center; - background: grey; - color: white; - text-align: center; - } +.faq__reply { + padding-left: 16px; +} - .gamepad-button > span { color: var(--color-white); } +/* ----- */ +/* PAGES */ +/* ----- */ - .gamepad-button_a { background: green; } - .gamepad-button_b { background: red; } - .gamepad-button_x { background: blue; } - .gamepad-button_y { background: orange; } +/* ------ */ +/* BANNER */ +/* ------ */ + +.banner-container { + min-height: 100vh; + display: flex; +} + +.banner { + margin: auto; + padding: 16px; +} diff --git a/faq.html b/faq.html new file mode 100644 index 0000000..46c8f8e --- /dev/null +++ b/faq.html @@ -0,0 +1,150 @@ + + + + Wavelovers – FAQ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+ +
+ +
+
+ +
+

Wavelovers – FAQ

+
+
+

FAQ

+ What is the purpose of this software?
+ Everyone decides for himself, but can be used as a gamepad vibration tester, or as a hand massager.

+ + Can I use this software as a hand massager?
+ Yes of course. If you use this as a massager, then before the session I recommend consulting with a doctor.

+ + I have a gamepad with vibration, what should I do before using it as a hand massager?
+ I recommend checking the device for correct operation, mechanical damage, and be sure to use an antiseptic.

+ + I'm having problems with the app or connecting my device to the app?
+ Go to Troubleshooting. +
+
+

Troubleshooting

+ If you are having difficulty detecting a gamepad by the browser, you can use the utility + Gamepad Master

+ + The app does not see my device.
+ Make sure you have a chromium-based browser, then update the app and reconnect your device.

+ + The application sees the gamepad, but writes that the vibration actuator is missing.
+ This problem is specific to mozilla firefox browser and d-input mode. Check the system requirements before using the software.

+ + My question is not here.
+ Write me eugene.serb@gmail.com +
+
+

System Requirements

+ Gamepad: X-Input and vibration actuator required.
+ Browser: Google Chrome or any other Chromium-based browser is recommended.
+ OS: Windows 7 or higher recommended.
+
+
+
+ + + + + + + + diff --git a/index.html b/index.html index f4ec557..bb45b0f 100644 --- a/index.html +++ b/index.html @@ -9,19 +9,19 @@ - - - - - - - + + + + + + + - + @@ -29,40 +29,35 @@ - - - + + + - - - - - - + - + - + - + diff --git a/js/scripts.js b/js/scripts.js index 9c50b98..3e142cd 100644 --- a/js/scripts.js +++ b/js/scripts.js @@ -4,193 +4,54 @@ 'use strict'; -const __PATTERNS = [ - /* Dotted, 0.1s, 0.1s */ - { - name: 'Dotted Weak', - type: 'Simple', - icon: '😌', - pattern: [ - { - startDelay: 100, - duration: 100, - weakMagnitude: 1.0, - strongMagnitude: 0.0, - }, - ], - }, - { - name: 'Dotted Strong', - type: 'Simple', - icon: '😉', - pattern: [ - { - startDelay: 100, - duration: 100, - weakMagnitude: 0.0, - strongMagnitude: 1.0, - }, - ], - }, - { - name: 'Dotted Max', - type: 'Simple', - icon: '🙃', - pattern: [ - { - startDelay: 0, - duration: 100, - weakMagnitude: 1.0, - strongMagnitude: 1.0, - }, - ], - }, - /* Short Dashed, 0.1s, 0.25s */ - { - name: 'Short Dashed Weak', - type: 'Simple', - icon: '🙂', - pattern: [ - { - startDelay: 100, - duration: 250, - weakMagnitude: 1.0, - strongMagnitude: 0.0, - }, - ], - }, - { - name: 'Short Dashed Strong', - type: 'Simple', - icon: '😇', - pattern: [ - { - startDelay: 100, - duration: 250, - weakMagnitude: 0.0, - strongMagnitude: 1.0, - }, - ], - }, - { - name: 'Short Dashed Max', - type: 'Simple', - icon: '😊', - pattern: [ - { - startDelay: 0, - duration: 250, - weakMagnitude: 1.0, - strongMagnitude: 1.0, - }, - ], - }, - /* Long Dashed, 0.1s, 0.5s */ - { - name: 'Long Dashed Weak', - type: 'Simple', - icon: '😋', - pattern: [ - { - startDelay: 100, - duration: 500, - weakMagnitude: 1.0, - strongMagnitude: 0.0, - }, - ], - }, - { - name: 'Long Dashed Strong', - type: 'Simple', - icon: '😜', - pattern: [ - { - startDelay: 100, - duration: 500, - weakMagnitude: 0.0, - strongMagnitude: 1.0, - }, - ], - }, - { - name: 'Long Dashed Max', - type: 'Simple', - icon: '🤪', - pattern: [ - { - startDelay: 0, - duration: 500, - weakMagnitude: 1.0, - strongMagnitude: 1.0, - }, - ], - }, - /* Constant, 0s, 1s */ - { - name: 'Constant Weak', - type: 'Simple', - icon: '😏', - pattern: [ - { - startDelay: 0, - duration: 1000, - weakMagnitude: 1.0, - strongMagnitude: 0.0, - }, - ], - }, - { - name: 'Constant Strong', - type: 'Simple', - icon: '🤩', - pattern: [ - { - startDelay: 0, - duration: 1000, - weakMagnitude: 0.0, - strongMagnitude: 1.0, - }, - ], - }, - { - name: 'Constant Max', - type: 'Simple', - icon: '😍', - pattern: [ - { - startDelay: 0, - duration: 1000, - weakMagnitude: 1.0, - strongMagnitude: 1.0, - }, - ], - }, -]; +class Library { + constructor() { + if (typeof Library.instance === 'object') { + return Library.instance; + }; + this.init(); + Library.instance = this; + return this; + }; + init = () => { + this.state = 'load'; + this.patterns = this.update(); + }; + update = async () => { + const url = 'https://wavelovers.ru/assets/patterns.json'; + try { + const response = await fetch(url); + if (response.ok) { + let json = await response.json(); + this.patterns = json; + this.state = 'draw'; + } else { + console.log('Connect to the Internet for download more patterns...'); + this.state = 'fail'; + }; + } catch (error) { + console.log('[error]', error); + }; + }; +}; class Gamepad { - constructor(gamepad, $container, library) { + constructor(gamepad, $container) { this.unit = gamepad; this.$container = $container; - this.library = library; this.init(); }; init = () => { this.id = Date.now(); this.canVibrate = (this.unit.vibrationActuator) ? true : false; - this.isSelected = false; this.isVibrating = false; - this.isLocked = false; - this.cooldown = 0; + + this.library = new Library; + this.index = 0; - this.pattern = [ - { - startDelay: 0, - duration: 1000, - weakMagnitude: 1.0, - strongMagnitude: 1.0, - } - ]; + this.pattern = this.library.patterns[this.index].pattern; + this.generateBox(); }; @@ -232,7 +93,7 @@ class Gamepad { }; vibrate = async () => { this.isVibrating = true; - this.pattern = this.library[this.index].pattern; + this.pattern = this.library.patterns[this.index].pattern; while (this.isVibrating) { for (let i = 0; i < this.pattern.length; i++) { @@ -248,49 +109,19 @@ class Gamepad { sleep = (ms) => { return new Promise(resolve => setTimeout(resolve, ms)); }; - previous = () => { - if (Date.now() >= this.cooldown) { - if (this.index === 0) { - this.index = this.library.length - 1; - } else { - this.index--; - }; - this.pattern = this.library[this.index].pattern; - this.cooldown = Date.now() + 500; - }; - }; - next = () => { - if (Date.now() >= this.cooldown) { - if (this.index === this.library.length - 1) { - this.index = 0; - } else { - this.index++; - }; - this.pattern = this.library[this.index].pattern; - this.cooldown = Date.now() + 500; - }; - }; - lock = () => { - if (Date.now() >= this.cooldown) { - this.isLocked = !this.isLocked; - this.cooldown = Date.now() + 500; - }; - }; - change = (index) => { this.index = index; - this.pattern = this.library[this.index].pattern; + this.pattern = this.library.patterns[this.index].pattern; }; }; -class VibrationMaster { +class Wavelovers { constructor() { this.init(); }; init = () => { this.#DOMs(); - this.patterns = __PATTERNS; - this.print(this.patterns); + this.library = new Library(); if (!this.checkGamepadSupport()) { console.log(`This browser does not support of gamepads.`); @@ -328,33 +159,15 @@ class VibrationMaster { gamepad.draw(); }); }; - }; - eventHandler = () => { - if (this.gamepads.length > 0) { - this.gamepads.forEach(gamepad => { - if (gamepad.canVibrate === true) { - if (gamepad.unit.buttons[2].pressed === true && - gamepad.unit.buttons[3].pressed === true) { - gamepad.lock(); - }; - if (gamepad.isLocked === false) { - if (gamepad.unit.buttons[0].pressed === true) { - if (gamepad.isVibrating === false) { - gamepad.vibrate(); - }; - }; - if (gamepad.unit.buttons[1].pressed === true) { - gamepad.reset(); - }; - if (gamepad.unit.buttons[4].pressed === true) { - gamepad.previous(); - }; - if (gamepad.unit.buttons[5].pressed === true) { - gamepad.next(); - }; - }; - }; - }); + if (this.library.state === 'draw') { + this.print(this.library.patterns); + this.library.state = 'ready'; + }; + if (this.library.state === 'fail') { + this.$PATTERN_LIST.innerHTML = ` +
+ Loading error... +
`; }; }; @@ -384,15 +197,17 @@ class VibrationMaster { change = (index) => { if (this.gamepads.length > 0) { this.gamepads.forEach(gamepad => { - this.unselect(); - if (gamepad.index === index && - gamepad.isVibrating === true) { - gamepad.isVibrating = false; - gamepad.reset(); - } else { - gamepad.change(index); - gamepad.vibrate(); - this.select(index); + if (gamepad.canVibrate === true) { + this.unselect(this.library.patterns); + if (gamepad.index === index && + gamepad.isVibrating === true) { + gamepad.reset(); + } else { + gamepad.reset() + gamepad.change(index); + gamepad.vibrate(); + this.select(this.library.patterns, index); + }; }; }); } else { @@ -401,13 +216,13 @@ class VibrationMaster { }; }; - unselect = () => { - this.patterns.forEach(pattern => { + unselect = (patterns) => { + patterns.forEach(pattern => { pattern['container'].classList.remove('pattern-item__selected'); }); }; - select = (index) => { - this.patterns[index]['container'].classList.add('pattern-item__selected'); + select = (patterns, index) => { + patterns[index]['container'].classList.add('pattern-item__selected'); }; checkGamepadSupport = () => { @@ -426,7 +241,7 @@ class VibrationMaster { if (this.gamepads.length > 1) { return; } else { - this.gamepads.push(new Gamepad(event.gamepad, this.$DEVICE_LIST, this.patterns)); + this.gamepads.push(new Gamepad(event.gamepad, this.$DEVICE_LIST)); }; }); window.addEventListener('gamepaddisconnected', (event) => { @@ -436,6 +251,7 @@ class VibrationMaster { this.gamepads.splice(index, 1); }; }); + this.unselect(); }); }; }; @@ -444,5 +260,5 @@ class VibrationMaster { /* INITIALIZATION */ /* -------------- */ -const VIBRATION_MASTER = new VibrationMaster(); +const WAVELOVERS = new Wavelovers(); diff --git a/robots.txt b/robots.txt new file mode 100644 index 0000000..f559157 --- /dev/null +++ b/robots.txt @@ -0,0 +1,13 @@ +# +# robots.txt at https://wavelovers.ru/ +# +# Follow me on Twitter: @eugene_serb +# Author: https://eugene-serb.github.io/ +# + +# All Bots +User-agent: * +Allow: / + +Sitemap: https://wavelovers.ru/sitemap.xml + diff --git a/site.webmanifest b/site.webmanifest index 899dac7..7418fbd 100644 --- a/site.webmanifest +++ b/site.webmanifest @@ -1,6 +1,6 @@ { - "name": "", - "short_name": "", + "name": "Wavelovers", + "short_name": "Wavelovers", "icons": [ { "src": "https://eugene-serb.github.io/wavelovers/img/android-chrome-192x192.png", @@ -13,8 +13,8 @@ "type": "image/png" } ], - "theme_color": "#ffffff", - "background_color": "#ffffff", + "theme_color": "#EFCFE3", + "background_color": "#EFCFE3", "display": "standalone" } diff --git a/sitemap-internal.xml b/sitemap-internal.xml new file mode 100644 index 0000000..202c214 --- /dev/null +++ b/sitemap-internal.xml @@ -0,0 +1,22 @@ + + + + https://wavelovers.ru/ + 2022-06-24 + weekly + 1.0 + + + https://wavelovers.ru/about.html + 2022-06-24 + weekly + 1.0 + + + https://wavelovers.ru/faq.html + 2022-06-24 + weekly + 1.0 + + + diff --git a/sitemap.xml b/sitemap.xml new file mode 100644 index 0000000..3a7934f --- /dev/null +++ b/sitemap.xml @@ -0,0 +1,8 @@ + + + + https://wavelovers.ru/sitemap-internal.xml + 2022-06-24 + + +