Typescript + Vuejs

This commit is contained in:
Brandon Thomas committed 2016-10-24 23:52:53 -04:00
1 parent adabd2b588
commit 0bebea4a0e
14 files changed
+324 -28

No files matched your search

+5
View File
@@ -44,6 +44,11 @@ Scaling
4. Prevent others from calling it
5. Caching strategy
Hardening
1. Reduce API surface
2. Limit length of input sentences
3. Rate limiting
Presentation
- Better frontend UI
- Testing page (current frontend)
+1
View File
@@ -11,6 +11,7 @@ rsync -utrv dictionary bt@jungle.horse:/home/bt/dev/trumpet
rsync -utrv config.toml bt@jungle.horse:/home/bt/dev/trumpet
# Frontend
rsync -utrv web/images bt@jungle.horse:/home/bt/dev/trumpet/web
rsync -utrv web/*css bt@jungle.horse:/home/bt/dev/trumpet/web
rsync -utrv web/*html bt@jungle.horse:/home/bt/dev/trumpet/web
pushd frontend
+1
View File
@@ -6,6 +6,7 @@ banjo-tooie
batshit
charizard
crafted
derping
dipshit
fam
fearmongers
+199
View File
@@ -0,0 +1,199 @@
// Copyright (c) 2016 Brandon Thomas <bt@brand.io, echelon@gmail.com>
import PIXI = require('pixi.js');
// TODO: Clean up this abysmal garbage.
export function setup_animation() {
//let renderer = new PIXI.WebGLRenderer(800, 470);
let renderer = PIXI.autoDetectRenderer(800, 470);
renderer.backgroundColor = 0xffffff;
document.getElementById('animation').appendChild(renderer.view);
let stage = new PIXI.Container();
let asset: any = null;
let logo: any = null;
(<any>window).animationState = null;
let blinkingStart = null;
let talkingStart = null;
let start = null;
let curFrame = 0;
function animate() {
// start the timer for the next animation loop
requestAnimationFrame(animate);
if ((<any>window).animationState === 'blinking') {
if (blinkingStart == null) {
blinkingStart = window.performance.now();
curFrame = 0;
} else {
let delta = window.performance.now() - blinkingStart;
if (delta > 200) {
curFrame = 0;
blinkingStart = null;
(<any>window).animationState = null;
} else if (delta > 150) {
curFrame = 4;
} else if (delta > 60) {
curFrame = 3;
} else if (delta > 20) {
curFrame = 2;
} else if (delta > 10) {
curFrame = 1;
}
}
} else if ((<any>window).animationState === 'talking') {
if (talkingStart == null) {
talkingStart = window.performance.now();
curFrame = 5;
} else {
let delta = window.performance.now() - talkingStart;
if (delta > 550) {
curFrame = 5;
talkingStart = null;
//(<any>window).animationState = null;
} else if (delta > 580) {
curFrame = 6;
} else if (delta > 540) {
curFrame = 7;
} else if (delta > 500) {
curFrame = 8;
} else if (delta > 460) {
curFrame = 9;
} else if (delta > 420) {
curFrame = 10;
} else if (delta > 400) {
curFrame = 11;
} else if (delta > 360) {
curFrame = 12;
} else if (delta > 320) {
curFrame = 13;
} else if (delta > 280) {
curFrame = 12;
} else if (delta > 240) {
curFrame = 11;
} else if (delta > 200) {
curFrame = 10;
} else if (delta > 160) {
curFrame = 9;
} else if (delta > 120) {
curFrame = 8;
} else if (delta > 80) {
curFrame = 7;
} else if (delta > 40) {
curFrame = 6;
}
}
} else if ((<any>window).animationState === 'stop_talking') {
if (curFrame > 13 || curFrame < 5) {
(<any>window).animationState = null;
curFrame = 0;
} else {
if (start == null) {
start = window.performance.now();
}
let delta = window.performance.now() - start;
if (delta > 40) {
curFrame -= 1;
start = window.performance.now();
}
}
}
asset.gotoAndStop(curFrame);
// this is the main render call that makes pixi draw your container and its children.
renderer.render(stage);
}
let idleImages = [
'/assets/images/trumpette/idle_0.png', // 0
'/assets/images/trumpette/idle_1.png', // 1
'/assets/images/trumpette/idle_2.png', // 2
'/assets/images/trumpette/idle_3.png', // 3
'/assets/images/trumpette/idle_4.png', // 4
];
let talkImages = [
'/assets/images/trumpette/talk_0.png', // 5
'/assets/images/trumpette/talk_1.png', // 6
'/assets/images/trumpette/talk_2.png', // 7
'/assets/images/trumpette/talk_3.png', // 8
'/assets/images/trumpette/talk_4.png', // 9
'/assets/images/trumpette/talk_5.png', // 10
'/assets/images/trumpette/talk_6.png', // 11
'/assets/images/trumpette/talk_7.png', // 12
'/assets/images/trumpette/talk_8.png', // 13
];
let idleTextures = [];
for (let image of idleImages) {
let texture = PIXI.Texture.fromImage(image);
idleTextures.push(texture);
}
for (let image of talkImages) {
let texture = PIXI.Texture.fromImage(image);
idleTextures.push(texture);
}
logo = new PIXI.Text('Jungle Horse',
{font: '150px Impact Bold', fill: 0x000000, align: 'center'});
PIXI.loader.add('asset', '/assets/images/trumpette/idle_0.png')
.load(function (loader, resources) {
// This creates a texture from a 'asset.png' image.
//asset = new PIXI.Sprite(resources.asset.texture);
asset = new PIXI.extras.MovieClip(idleTextures);
// Setup the position and scale of the asset
asset.position.x = 200;
asset.position.y = 0;
asset.scale.x = 0.5;
asset.scale.y = 0.5;
logo.position.y = 260;
// Add the asset to the scene we are building.
stage.addChild(logo);
stage.addChild(asset);
asset.play();
// kick off the animation loop (defined below)
animate();
});
blinkAnimation();
}
export function talk() {
(<any>window).animationState = 'talking';
}
export function stopTalking() {
(<any>window).animationState = 'stop_talking';
}
function blink() {
(<any>window).animationState = 'blinking';
}
function blinkAnimation() {
if ((<any>window).animationState == null) {
(<any>window).animationState = 'blinking';
}
let nextBlink = getRandomInt(1000, 4000);
setTimeout(blinkAnimation, nextBlink);
}
function getRandomInt(min: number, max: number) : number {
min = Math.ceil(min);
max = Math.floor(max);
return Math.floor(Math.random() * (max - min)) + min;
}
+11
View File
@@ -2,6 +2,8 @@
declare var buzz: any; // TODO: static types.
import { talk, stopTalking } from "./animation";
export default class Audio {
sound: any;
@@ -13,6 +15,15 @@ export default class Audio {
this.stop();
this.sound = new buzz.sound(url);
this.sound.play();
this.sound.bind('play playing', function() {
talk(); // UI
});
this.sound.bind('ended pause', function() {
stopTalking(); // UI
});
}
stop() {
+22 -5
View File
@@ -1,19 +1,36 @@
// Copyright (c) 2016 Brandon Thomas <bt@brand.io, echelon@gmail.com>
/// <reference path='./typings/tsd.d.ts' />
import Vue = require('vue');
declare var $: any;
import { setup_animation } from "./animation";
import Audio from "./audio";
import { decode_url_hash, get_audio_api_url, set_url_hash } from "./url";
import { RawSentence, FilteredSentence } from "./sentence";
const INPUT = 'input#jungle';
/*(<any>window).V = new Vue({
el: '#image-box',
data: {
content: 'foo',
},
});*/
$(function() {
console.log('installing...');
window.audio = new Audio();
(<any>window).audio = new Audio();
install_events();
initialize_from_url();
focus();
if ($('#animation').length > 0) {
// Only install animation if the page supports it.
setup_animation();
}
});
function install_events() {
@@ -25,7 +42,7 @@ function install_events() {
set_url_hash(filtered);
let url = get_audio_api_url(filtered);
window.audio.playUrl(url);
(<any>window).audio.playUrl(url);
ev.preventDefault();
return false;
@@ -36,7 +53,7 @@ function install_events() {
// ESC key.
focus();
$(INPUT).val('');
window.audio.stop();
(<any>window).audio.stop();
}
});
@@ -45,7 +62,7 @@ function install_events() {
if (ev.keyCode === 27) {
$(INPUT).val(''); // ESC key.
window.audio.stop();
(<any>window).audio.stop();
}
});
@@ -57,7 +74,7 @@ function install_events() {
$('button#clear').on('click', function(ev: any): any {
$(INPUT).val(''); // ESC key.
window.audio.stop();
(<any>window).audio.stop();
ev.preventDefault();
return false;
});
+2
View File
@@ -2,8 +2,10 @@
"dependencies": {
"bower": "^1.7.9",
"jquery": "^3.0.0",
"pixi.js": "^4.1.0",
"ts-loader": "^0.8.2",
"typescript": "^1.8.10",
"vue": "^1.0.28",
"wavesurfer.js": "^1.1.12"
}
}
+12
View File
@@ -0,0 +1,12 @@
{
"filesGlob": [
"./**/*.ts",
"!./node_modules/**/*.ts"
],
"files": [
"./main.ts",
"./typings/pixi.js/pixi.js.d.ts",
"./typings/tsd.d.ts",
"./typings/vue/vue.d.ts"
]
}
+6
View File
@@ -7,6 +7,12 @@
"installed": {
"jquery/jquery.d.ts": {
"commit": "73110d92bdab2367e326f297bef3574285cba329"
},
"vue/vue.d.ts": {
"commit": "3cc599268d2dabe3c3ee194e92965ee87440e9c3"
},
"pixi.js/pixi.js.d.ts": {
"commit": "3cc599268d2dabe3c3ee194e92965ee87440e9c3"
}
}
}
+5
View File
@@ -0,0 +1,5 @@
{
"globalDependencies": {
"vue": "registry:dt/vue#1.0.21+20160929090511"
}
}
+2 -2
View File
@@ -22,10 +22,10 @@ export function set_url_hash(sentence: FilteredSentence) {
urlHash = '';
if (!json) {
urlHash = new URI('/').hash('').toString();
urlHash = new URI('').hash('').toString();
} else {
let uriEncoded = encodeURIComponent(json);
urlHash = new URI('/').hash(uriEncoded).toString();
urlHash = new URI('').hash(uriEncoded).toString();
}
window.history.replaceState(null, null, urlHash);
+13
View File
@@ -23,6 +23,19 @@ h1 {
text-align: center;
}
#animation canvas {
display: block;
margin: auto;
}
#logo {
display: none;
z-index: 100;
position: absolute;
top: 0;
width: 100%;
}
#image-box {
width: 100%;
}
+36 -16
View File
@@ -1,28 +1,48 @@
img#trump {
height: 300px;
}
@media screen and (min-height: 600px) {
img#trump {
height: 400px;
@media screen and (min-width: 1px) {
#animation canvas {
width: 200px;
}
}
@media screen and (min-height: 800px) {
img#trump {
height: 500px;
@media screen and (min-width: 300px) {
#animation canvas {
width: 300px;
}
}
@media screen and (min-height: 1000px) {
img#trump {
height: 700px;
@media screen and (min-width: 400px) {
#animation canvas {
width: 400px;
}
}
@media screen and (min-height: 1500px) {
img#trump {
height: 1000px;
@media screen and (min-width: 450px) {
#animation canvas {
width: 450px;
}
}
@media screen and (min-width: 500px) {
#animation canvas {
width: 500px;
}
}
@media screen and (min-width: 600px) {
#animation canvas {
width: 600px;
}
}
@media screen and (min-width: 800px) {
#animation canvas {
width: 800px;
}
}
@media screen and (min-width: 1000px) {
#animation canvas {
width: 800px;
}
}
+9 -5
View File
@@ -10,12 +10,15 @@
<link href="https://fonts.googleapis.com/css?family=Fira+Sans|Open+Sans" rel="stylesheet">
</head>
<body>
<div id="animation"></div>
<div id="logo">
<h1>Text to Trump</h1>
</div>
<div id="main">
<h1>Jungle Horse</h1>
<div id="image-box">
<img id="trump" src="/assets/images/trump_jon.png">
</div>
<!--<div id="image-box">
{{ content }}
</div>-->
<form>
<div id="input-box">
@@ -32,7 +35,8 @@
<div class="clear"></div>
</div>
</form>
</div>
<script src="/assets/output/libraries.js"/></script>
<script src="/assets/output/main.built.js"/></script>
</body>
</html>