17 Commits

Author SHA1 Message Date
Josh Creek a8af91a104 fix#25): Ensure wheel is not too small 2022-10-26 23:06:29 +01:00
Josh Creek daf9e01dfa Merge pull request #29 from jcreek/25-improve-max-wheel-size-on-wider-viewports
feat(#25): Improve max wheel size on smaller viewports
2022-10-25 18:12:08 +01:00
Josh Creek 5117591567 feat(#25): Improve max wheel size on smaller viewports 2022-10-25 18:11:19 +01:00
Josh Creek b8fd761e2f Merge pull request #27 from jcreek/26-display-selected-name-in-a-modal
feat(#26): Display selection in modal
2022-10-25 10:09:23 +01:00
Josh Creek 4b94d42271 feat(#26): Display selection in modal 2022-10-25 10:08:32 +01:00
Josh Creek f20995a879 chore(*): Update version number 2022-10-24 13:48:12 +01:00
Josh Creek 84e1e39f9c Merge pull request #24 from jcreek/3-add-nicer-styling-to-selection-reveal
feat(#3): Add fireworks and sound to selection reveal
2022-10-24 13:44:18 +01:00
Josh Creek 7783162127 feat(#3): Add fireworks and sound to selection reveal 2022-10-24 13:42:44 +01:00
Josh Creek f1efac7c7f Merge pull request #23 from jcreek/11-add-optional-spinner-audio-with-a-mute-toggle-button
feat(#11): Add spinner audio and mute button
2022-10-24 12:32:13 +01:00
Josh Creek d8fe76f62c fix(#11): Fix styling 2022-10-24 12:31:30 +01:00
Josh Creek b9a40bb8a5 feat(#11): Add spinner audio and mute button 2022-10-24 12:27:32 +01:00
Josh Creek ff58967c8c Merge pull request #21 from jcreek/19-add-touchclick-to-spin-help-text-depending-on-device
doc(#19): Add click to spin help text
2022-10-09 19:47:12 +01:00
Josh Creek d15f55b94b doc(#19): Add click to spin help text 2022-10-09 19:40:39 +01:00
Josh Creek d411a76c49 Merge pull request #20 from jcreek/17-when-highlightedgreyed-out-invert-the-name-text-to-white
feat(#17): Change colour of selected names
2022-10-09 19:37:30 +01:00
Josh Creek 546c647234 feat(#17): Change colour of selected names 2022-10-09 19:36:42 +01:00
Josh Creek e7f80e1885 Merge branch 'master' of https://github.com/jcreek/SelectionWheel 2022-10-09 19:28:45 +01:00
Josh Creek 5dc201eac7 chore(*): Remove navigation preload
This is unnecessary as there are only two pages.
2022-10-09 15:34:57 +01:00
13 changed files with 560 additions and 628 deletions
+2 -1
View File
@@ -27,6 +27,7 @@
"ts": "never", "ts": "never",
"tsx": "never" "tsx": "never"
} }
] ],
"quotes": [2, "single", { "avoidEscape": true }]
} }
} }
+212 -460
View File
File diff suppressed because it is too large Load Diff
+3 -1
View File
@@ -1,6 +1,6 @@
{ {
"name": "SelectionWheel", "name": "SelectionWheel",
"version": "1.4.1", "version": "1.5.0",
"description": "A fun and simple selection wheel.", "description": "A fun and simple selection wheel.",
"main": "index.js", "main": "index.js",
"scripts": { "scripts": {
@@ -38,8 +38,10 @@
"workbox-cli": "^6.5.4" "workbox-cli": "^6.5.4"
}, },
"dependencies": { "dependencies": {
"@fireworks-js/web": "^2.5.1",
"@types/d3": "^7.4.0", "@types/d3": "^7.4.0",
"d3": "^7.6.1", "d3": "^7.6.1",
"fireworks-js": "^2.5.1",
"html-webpack-plugin": "^5.5.0", "html-webpack-plugin": "^5.5.0",
"react-dev-utils": "^12.0.1", "react-dev-utils": "^12.0.1",
"webpack-manifest-plugin": "^5.0.0", "webpack-manifest-plugin": "^5.0.0",
Binary file not shown.
Binary file not shown.
+17
View File
@@ -0,0 +1,17 @@
export default {
pauseAudio(audio: HTMLAudioElement) {
audio.pause();
},
playAudio(audio: HTMLAudioElement) {
audio.play();
},
stopAudio(audio: HTMLAudioElement) {
audio.pause();
// eslint-disable-next-line no-param-reassign
audio.currentTime = 0;
},
toggleMute(audio: HTMLAudioElement) {
// eslint-disable-next-line no-param-reassign
audio.muted = !audio.muted;
},
};
+73 -10
View File
@@ -1,5 +1,9 @@
import * as d3 from 'd3'; import * as d3 from 'd3';
import { Fireworks } from 'fireworks-js';
import loadServiceWorker from './loadServiceWorker'; import loadServiceWorker from './loadServiceWorker';
import audioControls from './audioControls';
import spinnerMp3 from './assets/spinner-sound.mp3';
import tadaMp3 from './assets/tada-fanfare.mp3';
require('./assets/favicon.ico'); require('./assets/favicon.ico');
require('./assets/android-chrome-192x192.png'); require('./assets/android-chrome-192x192.png');
@@ -8,6 +12,39 @@ require('./assets/apple-touch-icon.png');
require('./assets/favicon-16x16.png'); require('./assets/favicon-16x16.png');
require('./assets/favicon-32x32.png'); require('./assets/favicon-32x32.png');
require('./styles/main.scss'); require('./styles/main.scss');
require('./styles/buttons.scss');
require('./styles/modal.scss');
require('./styles/spinner.scss');
const wheelSpinningSound = new Audio(spinnerMp3);
const tadaSound = new Audio(tadaMp3);
if (window.localStorage.audioMuteSetting) {
wheelSpinningSound.muted = window.localStorage.audioMuteSetting;
tadaSound.muted = window.localStorage.audioMuteSetting;
}
const modal = document.getElementById('myModal');
const fireworksContainer = document.getElementById('fireworks-container');
function fireworksContainerOnClick() {
fireworksContainer.style.display = 'none';
modal.style.display = 'none';
document.getElementById('chart').click();
document.getElementsByClassName('chartholder')[0].dispatchEvent(new Event('click'));
}
fireworksContainer.onclick = fireworksContainerOnClick;
const fireworks = new Fireworks(fireworksContainer, {
// sound: {
// enabled: !wheelSpinningSound.muted,
// },
});
// When the user clicks anywhere outside of the modal, close it
window.onclick = (event) => {
if (event.target === modal) {
modal.style.display = 'none';
}
};
const padding = { const padding = {
top: 20, top: 20,
@@ -41,8 +78,6 @@ function stopSpinning() {
// console.log('done'); // console.log('done');
const chartElement = document.getElementById('chart'); const chartElement = document.getElementById('chart');
chartElement.remove(); chartElement.remove();
const questionElement = document.getElementById('question');
questionElement.remove();
document.getElementById('input-lines').style.display = 'block'; document.getElementById('input-lines').style.display = 'block';
document.getElementById('startSpinning').style.display = 'block'; document.getElementById('startSpinning').style.display = 'block';
} }
@@ -156,9 +191,16 @@ function drawWheel() {
// all slices have been seen, all done // all slices have been seen, all done
// console.log(`OldPick: ${oldpick.length}`, `Data length: ${data.length}`); // console.log(`OldPick: ${oldpick.length}`, `Data length: ${data.length}`);
if (oldpick.length === data.length) { if (oldpick.length === data.length) {
fireworksContainer.style.display = 'none';
fireworks.clear();
stopSpinning(); stopSpinning();
return; return;
} }
audioControls.stopAudio(tadaSound);
audioControls.playAudio(wheelSpinningSound);
fireworksContainer.style.display = 'none';
fireworks.stop();
const ps = 360 / data.length; const ps = 360 / data.length;
const rng = Math.floor(Math.random() * 1440 + 360); const rng = Math.floor(Math.random() * 1440 + 360);
@@ -180,10 +222,22 @@ function drawWheel() {
.on('end', () => { .on('end', () => {
// mark question as seen // mark question as seen
d3.select(`.slice:nth-child(${picked + 1}) path`).attr('fill', '#111'); d3.select(`.slice:nth-child(${picked + 1}) path`).attr('fill', '#111');
d3.select(`.slice:nth-child(${picked + 1}) text`).attr('fill', '#ffffff');
// populate question // populate question
d3.select('#question h1').text(data[picked].label.trim()); modal.style.display = 'block';
d3.select('#selection').text(data[picked].label.trim());
oldrotation = rotation; oldrotation = rotation;
audioControls.stopAudio(wheelSpinningSound);
audioControls.playAudio(tadaSound);
fireworksContainer.style.display = 'block';
const sizes = {
width: window.innerWidth,
height: window.innerHeight,
};
fireworks.updateSize(sizes);
fireworks.start();
/* Get the result value from object "data" */ /* Get the result value from object "data" */
// console.log(data[picked].value); // console.log(data[picked].value);
@@ -199,6 +253,15 @@ function drawWheel() {
function startOver() { function startOver() {
stopSpinning(); stopSpinning();
audioControls.stopAudio(wheelSpinningSound);
}
function toggleMute() {
audioControls.toggleMute(wheelSpinningSound);
audioControls.toggleMute(tadaSound);
this.textContent = wheelSpinningSound.muted ? 'Unmute' : 'Mute';
window.localStorage.audioMuteSetting = wheelSpinningSound.muted;
// TODO - toggle muting the fireworks from here
} }
function startSpinning() { function startSpinning() {
@@ -230,19 +293,19 @@ function startSpinning() {
startOverElement.setAttribute('role', 'button'); startOverElement.setAttribute('role', 'button');
startOverElement.onclick = startOver; startOverElement.onclick = startOver;
startOverElement.textContent = 'Start over'; startOverElement.textContent = 'Start over';
const muteElement = document.createElement('button');
muteElement.setAttribute('id', 'mute');
muteElement.setAttribute('class', 'button button-black');
muteElement.setAttribute('role', 'button');
muteElement.onclick = toggleMute;
muteElement.textContent = wheelSpinningSound.muted ? 'Unmute' : 'Mute';
chartElement.appendChild(startOverElement); chartElement.appendChild(startOverElement);
chartElement.appendChild(muteElement);
document.getElementById('spinner-container').appendChild(chartElement); document.getElementById('spinner-container').appendChild(chartElement);
const questionElement = document.createElement('div');
questionElement.setAttribute('id', 'question');
questionElement.setAttribute('class', 'spinner-items');
const h1Element = document.createElement('h1');
questionElement.appendChild(h1Element);
document.getElementById('spinner-container').appendChild(questionElement);
drawWheel(); drawWheel();
document.getElementById('chart').style.display = 'block'; document.getElementById('chart').style.display = 'block';
document.getElementById('question').style.display = 'block';
document.getElementById('input-lines').style.display = 'none'; document.getElementById('input-lines').style.display = 'none';
document.getElementById('startSpinning').style.display = 'none'; document.getElementById('startSpinning').style.display = 'none';
} }
-3
View File
@@ -7,9 +7,6 @@ import { registerRoute, NavigationRoute, Route } from 'workbox-routing';
// eslint-disable-next-line no-underscore-dangle, no-restricted-globals // eslint-disable-next-line no-underscore-dangle, no-restricted-globals
precacheAndRoute(self.__WB_MANIFEST); precacheAndRoute(self.__WB_MANIFEST);
// Enable navigation preload - this should reduce navigation latency
navigationPreload.enable();
const navigationRoute = new NavigationRoute(new NetworkFirst({ const navigationRoute = new NavigationRoute(new NetworkFirst({
cacheName: 'navigations', cacheName: 'navigations',
})); }));
+82
View File
@@ -0,0 +1,82 @@
.button {
appearance: none;
border: 1px solid rgba(27, 31, 35, 0.15);
border-radius: 6px;
box-shadow: rgba(27, 31, 35, 0.1) 0 1px 0;
box-sizing: border-box;
color: #fff;
cursor: pointer;
display: inline-block;
font-family: -apple-system, system-ui, "Segoe UI", Helvetica, Arial,
sans-serif, "Apple Color Emoji", "Segoe UI Emoji";
font-size: 14px;
font-weight: 600;
line-height: 20px;
padding: 6px 16px;
position: relative;
text-align: center;
text-decoration: none;
user-select: none;
-webkit-user-select: none;
touch-action: manipulation;
vertical-align: middle;
white-space: nowrap;
}
.button:focus:not(:focus-visible):not(.focus-visible) {
box-shadow: none;
outline: none;
}
.button:disabled {
border-color: rgba(27, 31, 35, 0.1);
color: rgba(255, 255, 255, 0.8);
cursor: default;
}
.button:focus {
outline: none;
}
.button-green {
background-color: #2ea44f;
}
.button-green:hover {
background-color: #2c974b;
}
.button-green:focus {
box-shadow: rgba(46, 164, 79, 0.4) 0 0 0 3px;
outline: none;
}
.button-green:disabled {
background-color: #94d3a2;
}
.button-green:active {
background-color: #298e46;
box-shadow: rgba(20, 70, 32, 0.2) 0 1px 0 inset;
}
.button-black {
background-color: #423e37;
}
.button-black:hover {
background-color: #2e2b26;
}
.button-blue {
background-color: #388697;
}
.button-blue:hover {
background-color: #275d69;
}
.button-white {
background-color: #ffffff;
color: black;
}
+9 -153
View File
@@ -1,4 +1,4 @@
body { body {
margin: 0; margin: 0;
font-family: Arial, sans-serif; font-family: Arial, sans-serif;
} }
@@ -17,7 +17,7 @@ body {
.topbar-container h1 { .topbar-container h1 {
color: white; color: white;
font-family: 'Fuzzy Bubbles', cursive; font-family: "Fuzzy Bubbles", cursive;
font-weight: 700; font-weight: 700;
margin-block-start: 0.2em; margin-block-start: 0.2em;
margin-block-end: 0.2em; margin-block-end: 0.2em;
@@ -81,64 +81,6 @@ body {
order: 0; order: 0;
} }
#input-lines {
max-width: 100%;
}
#start-over {
position: absolute;
top: 100px;
left: auto;
}
#spinner-container {
display: flex;
flex-direction: row;
flex-wrap: wrap;
justify-content: center;
align-items: flex-start;
align-content: center;
}
.spinner-items:nth-child(1) {
display: block;
flex-grow: 0;
flex-shrink: 1;
flex-basis: 800px;
align-self: auto;
order: 0;
}
.spinner-items:nth-child(2) {
display: block;
flex-grow: 0;
flex-shrink: 1;
flex-basis: auto;
align-self: auto;
order: 0;
width: 100%;
}
text{
font-family: Arial, sans-serif;
font-size:35px;
pointer-events:none;
}
#chart{
max-width:800px;
margin-left: auto;
margin-right: auto;
}
#question h1{
font-size: 50px;
font-weight: bold;
font-family: Arial, sans-serif;
-webkit-transform:translate(0,-50%);
transform:translate(0,-50%);
text-align: center;
}
#install-app-btn-container { #install-app-btn-container {
display: none; display: none;
} }
@@ -149,23 +91,25 @@ text{
bottom: 0; bottom: 0;
width: 100%; width: 100%;
text-align: center; text-align: center;
color: #423E37; color: #423e37;
padding-bottom: 10px; padding-bottom: 10px;
background-color: white; background-color: white;
} }
.footer-container hr { .footer-container hr {
max-width: 500px; max-width: 500px;
border-top: 0.5px solid #423E37; border-top: 0.5px solid #423e37;
margin-left: auto; margin-left: auto;
margin-right: auto; margin-right: auto;
} }
.footer-container a, #privacy-container a { .footer-container a,
color: #423E37; #privacy-container a {
color: #423e37;
} }
.footer-container a:hover, #privacy-container a:hover { .footer-container a:hover,
#privacy-container a:hover {
color: #81796c; color: #81796c;
} }
@@ -175,91 +119,3 @@ text{
max-width: 800px; max-width: 800px;
margin-bottom: 50px; margin-bottom: 50px;
} }
#image{
width: 100%;
}
/* Buttons */
.button {
appearance: none;
border: 1px solid rgba(27, 31, 35, .15);
border-radius: 6px;
box-shadow: rgba(27, 31, 35, .1) 0 1px 0;
box-sizing: border-box;
color: #fff;
cursor: pointer;
display: inline-block;
font-family: -apple-system,system-ui,"Segoe UI",Helvetica,Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji";
font-size: 14px;
font-weight: 600;
line-height: 20px;
padding: 6px 16px;
position: relative;
text-align: center;
text-decoration: none;
user-select: none;
-webkit-user-select: none;
touch-action: manipulation;
vertical-align: middle;
white-space: nowrap;
}
.button:focus:not(:focus-visible):not(.focus-visible) {
box-shadow: none;
outline: none;
}
.button:disabled {
border-color: rgba(27, 31, 35, .1);
color: rgba(255, 255, 255, .8);
cursor: default;
}
.button:focus {
outline: none;
}
.button-green {
background-color: #2ea44f;
}
.button-green:hover {
background-color: #2c974b;
}
.button-green:focus {
box-shadow: rgba(46, 164, 79, .4) 0 0 0 3px;
outline: none;
}
.button-green:disabled {
background-color: #94d3a2;
}
.button-green:active {
background-color: #298e46;
box-shadow: rgba(20, 70, 32, .2) 0 1px 0 inset;
}
.button-black {
background-color: #423E37;
}
.button-black:hover {
background-color: #2e2b26;
}
.button-blue {
background-color: #388697;
}
.button-blue:hover {
background-color: #275d69;
}
.button-white {
background-color: #FFFFFF;
color: black;
}
+55
View File
@@ -0,0 +1,55 @@
/* The Modal (background) */
.modal {
display: none; /* Hidden by default */
position: fixed; /* Stay in place */
z-index: 1; /* Sit on top */
// padding-top: 100px; /* Location of the box */
left: 0;
top: 0;
width: 100%; /* Full width */
height: 100%; /* Full height */
overflow: auto; /* Enable scroll if needed */
background-color: rgb(0, 0, 0); /* Fallback color */
background-color: rgba(0, 0, 0, 0.4); /* Black w/ opacity */
}
/* Modal Content/Box */
#modal-content {
position: relative;
background-color: #fefefe;
margin: auto;
padding: 0;
border: 1px solid #888;
width: 80%;
box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19);
-webkit-animation-name: animatetop;
-webkit-animation-duration: 0.8s;
animation-name: animatetop;
animation-duration: 0.4s;
top: 30%;
transform: translateY(-30%);
text-align: center;
border-radius: 10px;
}
@-webkit-keyframes animatetop {
from {
top: -300px;
opacity: 0;
}
to {
top: 30%;
opacity: 1;
}
}
@keyframes animatetop {
from {
top: -300px;
opacity: 0;
}
to {
top: 30%;
opacity: 1;
}
}
+92
View File
@@ -0,0 +1,92 @@
#input-lines {
max-width: 100%;
}
#start-over {
position: absolute;
top: 100px;
left: auto;
}
#mute {
position: absolute;
top: 140px;
left: auto;
}
#spinner-container {
display: flex;
flex-direction: row;
flex-wrap: wrap;
justify-content: center;
align-items: flex-start;
align-content: center;
}
.spinner-items:nth-child(1) {
display: block;
flex-grow: 0;
flex-shrink: 1;
flex-basis: 800px;
align-self: auto;
order: 0;
}
@media screen and ( max-height: 920px )
{
.spinner-items:nth-child(1){
flex-basis: 650px;
flex-grow: 0;
}
}
.spinner-items:nth-child(2) {
display: block;
flex-grow: 0;
flex-shrink: 1;
flex-basis: auto;
align-self: auto;
order: 0;
width: 100%;
}
text {
font-family: Arial, sans-serif;
font-size: 35px;
pointer-events: none;
}
#chart {
max-width: calc(90%);
margin-left: auto;
margin-right: auto;
}
@media screen and ( min-width: 800px ) and ( max-height: 800px )
{
#chart{
max-width: 650px;
}
}
#selection h1 {
font-size: 50px;
font-weight: bold;
font-family: Arial, sans-serif;
-webkit-transform: translate(0, -50%);
transform: translate(0, -50%);
text-align: center;
}
#fireworks-container {
display: none;
position: fixed;
left: 0;
top: 0;
width: 100%;
height: 100%;
}
#image {
width: 100%;
}
+15
View File
@@ -42,6 +42,8 @@
<textarea id="input-lines" class="input-items" rows="15" cols="60" name="text" <textarea id="input-lines" class="input-items" rows="15" cols="60" name="text"
placeholder="Enter names to be shuffled, one per line. Leave this area empty in order to use a default set of generated names. placeholder="Enter names to be shuffled, one per line. Leave this area empty in order to use a default set of generated names.
Click or tap on the wheel to spin it.
You can also customise the centre of the spinner with an image. Just put ?imgUrl= at the end of the web address and the URL of the image you want to use. You can also customise the centre of the spinner with an image. Just put ?imgUrl= at the end of the web address and the URL of the image you want to use.
For example, https://wheel.jcreek.co.uk/?imgUrl=https://www.mammal.org.uk/wp-content/uploads/2021/09/red-fox-300x300.jpg"></textarea> For example, https://wheel.jcreek.co.uk/?imgUrl=https://www.mammal.org.uk/wp-content/uploads/2021/09/red-fox-300x300.jpg"></textarea>
@@ -54,5 +56,18 @@ For example, https://wheel.jcreek.co.uk/?imgUrl=https://www.mammal.org.uk/wp-con
<span> | </span> <span> | </span>
<span class="footer-items"><a href="/privacy-policy.html">Privacy Policy</a></span> <span class="footer-items"><a href="/privacy-policy.html">Privacy Policy</a></span>
</footer> </footer>
<div id="myModal" class="modal">
<!-- Modal content -->
<div id="modal-content">
<h1 id="selection"></h1>
</div>
<div id="fireworks-container"></div>
</div>
</body> </body>
</html> </html>