diff --git a/static/images/play_button.svg b/static/images/play_button.svg
new file mode 100644
index 0000000..541085c
--- /dev/null
+++ b/static/images/play_button.svg
@@ -0,0 +1,17 @@
+
+
+
diff --git a/static/src/interface/About.js b/static/src/interface/About.js
new file mode 100644
index 0000000..ac6042e
--- /dev/null
+++ b/static/src/interface/About.js
@@ -0,0 +1,118 @@
+/**
+ * Copyright 2016 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import 'style/about.css'
+import YouTubeIframeLoader from 'youtube-iframe'
+import events from 'events'
+
+const magentaLink = 'https://github.com/tensorflow/magenta'
+const sourceCode = 'https://github.com/googlecreativelab/aiexperiments-ai-duet'
+const toneLink = 'https://github.com/Tonejs/Tone.js'
+
+const blurbCopy = `Built by Yotam Mann with friends on the Magenta and Creative Lab teams at Google.
+ It uses Tone.js and tools
+ from the Magenta project.
+ The open-source code is available here.`
+
+export class About extends events.EventEmitter{
+ constructor(container){
+
+ super()
+
+ this._container = document.createElement('div')
+ this._container.id = 'about'
+ container.appendChild(this._container)
+
+ this._toggleButton = document.createElement('div')
+ this._toggleButton.id = 'aboutButton'
+ this._toggleButton.classList.add('open')
+ container.appendChild(this._toggleButton)
+ this._toggleButton.addEventListener('click', (e) => {
+ e.preventDefault()
+ if (this.isOpen()){
+ this.close()
+ } else {
+ this.open()
+ }
+ })
+
+ const content = document.createElement('div')
+ content.id = 'content'
+ this._container.appendChild(content)
+
+ const title = document.createElement('div')
+ title.id = 'title'
+ title.textContent = 'A.I. Duet'
+ content.appendChild(title)
+
+ const video = document.createElement('div')
+ video.id = 'video'
+ //vid YT0k99hCY5I
+ video.innerHTML = ``
+ content.appendChild(video)
+
+ this._ytplayer = null
+
+ this._playButton = document.createElement('div')
+ this._playButton.id = 'playButton'
+ this._playButton.classList.add('visible')
+ video.appendChild(this._playButton)
+
+ YouTubeIframeLoader.load((YT) => {
+ this._ytplayer = new YT.Player('youtube-iframe', {
+ events : {
+ onStateChange : (state) => {
+ this._playButton.classList.remove('visible')
+ }
+ }
+ })
+ })
+
+ const blurb = document.createElement('div')
+ blurb.id = 'blurb'
+ content.appendChild(blurb)
+ blurb.innerHTML = blurbCopy
+
+ }
+ close(){
+ this._toggleButton.classList.remove('close')
+ this._toggleButton.classList.add('open')
+
+ this._container.classList.remove('visible')
+
+ if (this._ytplayer){
+ this._ytplayer.stopVideo()
+ }
+ this.emit('close')
+ if (window.ga){
+ ga('send', 'event', 'AI-Duet', 'Click', 'About - Close')
+ }
+ }
+ open(){
+ this._toggleButton.classList.add('close')
+ this._toggleButton.classList.remove('open')
+
+ this._playButton.classList.add('visible')
+ this._container.classList.add('visible')
+ this.emit('open')
+ if (window.ga){
+ ga('send', 'event', 'AI-Duet', 'Click', 'About - Open')
+ }
+ }
+ isOpen(){
+ return this._container.classList.contains('visible')
+ }
+}
\ No newline at end of file
diff --git a/static/app/interface/Splash.js b/static/src/interface/Splash.js
similarity index 71%
rename from static/app/interface/Splash.js
rename to static/src/interface/Splash.js
index 8649099..6ed7123 100644
--- a/static/app/interface/Splash.js
+++ b/static/src/interface/Splash.js
@@ -23,7 +23,7 @@ class Splash extends events.EventEmitter{
constructor(container){
super()
- const splash = document.createElement('div')
+ const splash = this._splash = document.createElement('div')
splash.id = 'splash'
container.appendChild(splash)
@@ -42,26 +42,39 @@ class Splash extends events.EventEmitter{
titleContainer.appendChild(subTitle)
subTitle.textContent = 'Trade melodies with a neural network.'
- const loader = new Loader(titleContainer)
+ this._clicked = false
+ const loader = this._loader = new Loader(titleContainer)
loader.on('click', () => {
splash.classList.add('disappear')
+ this._clicked = true
this.emit('click')
})
+ const magenta = document.createElement('div')
+ magenta.id = 'magentaLink'
+ titleContainer.appendChild(magenta)
+ magenta.innerHTML = 'Built using Magenta'
+
+ const badges = document.createElement('div')
+ badges.id = 'badges'
+ splash.appendChild(badges)
+
const aiExperiments = document.createElement('a')
aiExperiments.id = 'aiExperiments'
aiExperiments.href = 'https://aiexperiments.withgoogle.com'
aiExperiments.target = '_blank'
- splash.appendChild(aiExperiments)
+ aiExperiments.classList.add('badge')
+ badges.appendChild(aiExperiments)
// break
const badgeBreak = document.createElement('div')
badgeBreak.id = 'badgeBreak'
- splash.appendChild(badgeBreak)
+ badges.appendChild(badgeBreak)
const googleFriends = document.createElement('a')
googleFriends.id = 'googleFriends'
- splash.appendChild(googleFriends)
+ googleFriends.classList.add('badge')
+ badges.appendChild(googleFriends)
const privacyAndTerms = document.createElement('div')
privacyAndTerms.id = 'privacyAndTerms'
@@ -69,6 +82,22 @@ class Splash extends events.EventEmitter{
splash.appendChild(privacyAndTerms)
}
+
+ get loaded(){
+ return this._loader.loaded
+ }
+
+ isOpen(){
+ return !this._clicked
+ }
+
+ show(){
+ this._splash.classList.remove('disappear')
+ }
+
+ hide(){
+ this._splash.classList.add('disappear')
+ }
}
export {Splash}
\ No newline at end of file
diff --git a/static/style/about.css b/static/style/about.css
new file mode 100644
index 0000000..72b3af3
--- /dev/null
+++ b/static/style/about.css
@@ -0,0 +1,155 @@
+/**
+ * Copyright 2016 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+@import 'common.scss';
+
+#aboutButton {
+ $closeSize : 30px;
+ position: absolute;
+ top: 15px;
+ right: 15px;
+ width: $closeSize;
+ height: $closeSize;
+ cursor: pointer;
+ z-index: 1000;
+ transition: transform 0.1s;
+ text-align: center;
+
+ &:hover {
+ transform: scale(1.1);
+ }
+
+ &:before{
+ font-family: $font-family;
+ font-weight: bold;
+ width: 100%;
+ height: 100%;
+ position: absolute;
+ top: 0px;
+ right: 0px;
+ line-height: $closeSize;
+ }
+
+ &.close:before{
+ content: "✕";
+ font-size: 25px;
+ color: white;
+ background-color: transparent;
+
+ }
+ &.open:before{
+ content: "?";
+ background-color: white;
+ border-radius: 50%;
+
+ }
+}
+
+#about {
+ width: 100%;
+ height: 100%;
+ z-index: 10;
+ top: 0px;
+ left: 0px;
+ position: absolute;
+ overflow-y: auto;
+ display: none;
+
+ &.visible {
+ display: initial;
+ }
+
+ #content {
+ width: 90%;
+ margin: 50px auto 30px auto;
+ min-width: 300px;
+ max-width: 800px;
+ height: auto;
+ position: relative;
+ color: white;
+ font-family: $font-family;
+ position: relative;
+
+ #title {
+ font-family: $font-family;
+ font-size: 40px;
+ line-height: 30px;
+ margin: 20px 0px 30px 0px;
+ position: relative;
+ }
+
+ $smallScreen : 450px;
+ $mediumScreen : 700px;
+
+ #video {
+ width: 100%;
+ cursor: pointer;
+ position: relative;
+
+ @media (max-width: $smallScreen) {
+ height: 200px;
+ }
+
+ @media (min-width: $smallScreen) and (max-width: $mediumScreen) {
+ height: 380px;
+ }
+
+ @media (min-width: $mediumScreen){
+ height: 450px;
+ }
+
+ iframe {
+ width: 100%;
+ height: 100%;
+ }
+
+ #playButton {
+ pointer-events: none;
+ position: absolute;
+ top: 50%;
+ left: 50%;
+ transform: translate(-50%, -50%);
+ width: 100px;
+ height: 100px;
+ background-image: url(../images/play_button.svg);
+ background-size: 100% 100%;
+ display: none;
+
+ &.visible {
+ display: initial;
+ }
+ }
+
+ &:hover #playButton svg{
+ fill: blue;
+ }
+ }
+
+ #blurb {
+
+ position: relative;
+ text-transform: none;
+ margin-top: 30px;
+ font-size: 16px;
+ line-height: 25px;
+
+ a {
+ color: $orange;
+ }
+ }
+
+ }
+}
\ No newline at end of file
diff --git a/static/style/splash.css b/static/style/splash.css
index ffe10d9..e145519 100644
--- a/static/style/splash.css
+++ b/static/style/splash.css
@@ -1,6 +1,6 @@
@import 'common.scss';
-$topMargin: 50px;
+$topMargin: 40px;
#splash {
position: absolute;
@@ -9,7 +9,7 @@ $topMargin: 50px;
top: 0px;
left: 0px;
z-index: 100;
- font-family: 'Quicksand', sans-serif;
+ font-family: $font-family;
font-weight: bold;
color: white;
transition: opacity 0.2s;
@@ -54,6 +54,30 @@ $topMargin: 50px;
font-weight: normal;
}
+ #magentaLink {
+ margin-top: $topMargin * 0.8;
+ letter-spacing: 0.8px;
+ line-height: 30px;
+ font-size: 20px;
+ width: 100%;
+ margin-left: auto;
+ margin-right: auto;
+ text-align: center;
+ font-weight: normal;
+ color: #aaa;
+ font-size: 14px;
+
+ a {
+ color: $orange;
+ text-decoration: underline;
+ cursor: pointer;
+ &:hover:active {
+ color: white;
+ }
+ }
+
+ }
+
$loaderWidth: 200px;
$loaderHeight: 60px;
@@ -144,50 +168,78 @@ $topMargin: 50px;
margin-top: $topMargin;
}
- $badgeWidth : 80px;
- $badgeHeight: 50px;
+ $badgeWidth : 110px;
+ $badgeHeight: 60px;
$badgeMargin : 20px;
$badegOpacity: 0.7;
- #aiExperiments, #googleFriends {
- width: $badgeWidth;
- height: $badgeHeight;
+ $smallScreen : 500px;
+ $smallBadgeWidth : 70px;
+ $smallBadgeHeight: 40px;
+
+ #badges {
+
position: absolute;
+ display: inline-block;
bottom: $badgeMargin;
- opacity: $badegOpacity;
- background-repeat: no-repeat;
- background-size: 100% 100%;
- }
-
- #aiExperiments {
left: $badgeMargin;
- background-image: url(../images/badgeAI_master.svg);
- &:hover {
- opacity: 1;
+ @media (max-width: $smallScreen) {
+ // bottom: $badgeMargin * 0.5;
+ }
- &:active {
- opacity: 0.3;
+ .badge {
+ display: inline-block;
+ position: relative;
+ margin-right: $badgeMargin;
+ width: $badgeWidth;
+ height: $badgeHeight;
+ background-repeat: no-repeat;
+ background-size: 100% 100%;
+ opacity: $badegOpacity;
+
+ @media (max-width: $smallScreen) {
+ width: $smallBadgeWidth;
+ height: $smallBadgeHeight;
+ }
+ }
+
+ #aiExperiments {
+ background-image: url(../images/badgeAI_master.svg);
+ &:hover {
+ opacity: 1;
+ &:active {
+ opacity: 0.3;
+ }
+ }
+ }
+
+ #googleFriends {
+ cursor: initial;
+ background-image: url(../images/badgeFriends_master.svg);
+ }
+
+ #badgeBreak{
+ display: inline-block;
+ position: relative;
+ margin-right: $badgeMargin;
+
+ $breakScale : 0.95;
+
+ $breakHeight: $badgeHeight * $breakScale;
+ height: $breakHeight;
+ background-color: white;
+ opacity: $badegOpacity / 2;
+ width: 1px;
+
+ @media (max-width: $smallScreen) {
+ $smallBreakHeight: $smallBadgeHeight * $breakScale;
+ height: $smallBreakHeight;
}
}
}
- #googleFriends {
- cursor: initial;
- left: $badgeWidth + $badgeMargin * 3;
- background-image: url(../images/badgeFriends_master.svg);
- }
- #badgeBreak{
- $breakHeight: $badgeHeight * 0.8;
- height: $breakHeight;
- left: $badgeWidth + $badgeMargin * 1.8;
- background-color: white;
- opacity: $badegOpacity / 2;
- position: absolute;
- width: 1px;
- bottom: $badgeMargin + ($badgeHeight - $breakHeight) / 2;
- }
#privacyAndTerms {
position: absolute;
@@ -199,7 +251,7 @@ $topMargin: 50px;
* {
height: 14px;
line-height: 14px;
- font-size: 14px;
+ font-size: 10px;
color: white;
display: inline;
opacity: $badegOpacity;