Skip to content

Commit

Permalink
initial react example code
Browse files Browse the repository at this point in the history
  • Loading branch information
yofreke committed Sep 15, 2016
1 parent c37985e commit f1d2ee9
Show file tree
Hide file tree
Showing 14 changed files with 375 additions and 5 deletions.
22 changes: 22 additions & 0 deletions examples/components/App.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import React from 'react';

import MenuDrawer from './MenuDrawer';
import SimpleExample from './simple';

import './App.styl'


export default class App extends React.Component {
render () {
const example = <SimpleExample />;

return (
<div className='app-cmpt'>
<MenuDrawer />
<div className='example-wrapper'>
{example}
</div>
</div>
);
}
}
26 changes: 26 additions & 0 deletions examples/components/App.styl
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
@import 'nib'


body
font-family Roboto, sans-serif


.app-cmpt
display flex

*
flex-shrink 0

.example-wrapper
padding 20px
max-width 750px
min-width 400px
flex 1

display flex
justify-content center
align-items center

.menu-drawer-cmpt
width 256px
height 100%
55 changes: 55 additions & 0 deletions examples/components/MenuDrawer.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import React, { PropTypes } from 'react';
import { connect } from 'react-redux';
import classNames from 'classnames';

import Drawer from 'material-ui/Drawer';
import MenuItem from 'material-ui/MenuItem';

import { EXAMPLES, setExample } from 'clmtrackr/examples/reducers/examples';

import './MenuDrawer.styl';


class MenuDrawer extends React.Component {
render () {
const menuItems = EXAMPLES.map((example, i) =>
<MenuItem
className={classNames({
selected: example.id === this.props.selectedExample
})}
onClick={() => this.props.setExample(example)}
key={i}
>
{example.name}
</MenuItem>
);

return (
<div className='menu-drawer-cmpt'>
<Drawer open={true}>
<div className='section-header'>Examples</div>
{menuItems}
</Drawer>
</div>
);
}
}

MenuDrawer.propTypes = {
selectedExample: PropTypes.string,
setExample: PropTypes.func.isRequired
};

const mapStateToProps = state => {
return {
selectedExample: state.examples.activeExample
};
};

const mapDispatchToProps = dispatch => {
return {
setExample: example => dispatch(setExample(example))
};
};

export default connect(mapStateToProps, mapDispatchToProps)(MenuDrawer);
9 changes: 9 additions & 0 deletions examples/components/MenuDrawer.styl
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
@require '~material-design-color/material-color'

.menu-drawer-cmpt
.section-header
padding 0 1em
margin 1em 0
font-weight 500
.selected
background clr-blue-100 !important
81 changes: 81 additions & 0 deletions examples/components/simple/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
// import './App.styl';
// import 'font-awesome-webpack';

import React from 'react';

import Tracker from 'clmtrackr/js/Tracker';

import VideoContainer from 'clmtrackr/ui/container/VideoContainer';

const VIDEO_SRC = 'media/franck.ogv';
const VIDEO_SIZE = { width: 368, height: 288 };


export default class SimpleExample extends React.Component {
constructor () {
super();
this.state = {
tracker: null
};
}

componentDidMount () {
const tracker = new Tracker();
this.setState({ tracker });
tracker.init();

const videoContainer = this.refs.videoContainer;
tracker.start(videoContainer.refs.video);

requestAnimationFrame(this._onFrame.bind(this));
}

_onFrame () {
// Update overlay
const cc = this.refs.videoContainer.refs.canvas.getContext('2d');
cc.clearRect(0, 0, VIDEO_SIZE.width, VIDEO_SIZE.height);
this.state.tracker.draw(cc.canvas);

// Update the rendered points
this.forceUpdate();
requestAnimationFrame(this._onFrame.bind(this));
}

render () {
const positionChildren = [];

const tracker = this.state.tracker;
const positions = tracker && tracker.getCurrentPosition();
if (positions) {
for (let p = 0; p < 10; p++) {
const positionString = (
'featurepoint ' + p + ' : ' +
'[' +
positions[p][0].toFixed(2) +
', ' +
positions[p][1].toFixed(2) +
']'
);
positionChildren.push(<div key={p}>{positionString}</div>);
}
}

return (
<div className='simple-example-cmpt'>
<h1>Tracking a video tag</h1>

<VideoContainer
ref='videoContainer'
videoSrc={VIDEO_SRC}
videoSize={VIDEO_SIZE}
/>

<p>Printing coordinates of the first 10 points in facial features:</p>

<div className='positions'>
{positionChildren}
</div>
</div>
);
}
}
15 changes: 15 additions & 0 deletions examples/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<!DOCTYPE html>
<html>
<head>
<meta
name="viewport"
content="user-scalable=no,initial-scale=1, maximum-scale=1"
/>
<!-- <link rel="stylesheet" href="./dist/faceDecoratorUi.css"> -->
</head>
<body>
<div id="main"></div>
<script src="../dist/examples.js"></script>
<!-- <script src="./dist/faceDecoratorUi.js"></script> -->
</body>
</html>
37 changes: 37 additions & 0 deletions examples/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// See: http://stackoverflow.com/questions/33541949/react-material-ui-dropdown-menu-not-working
import injectTapEventPlugin from 'react-tap-event-plugin';
injectTapEventPlugin();
// ----

import React from 'react';
import ReactDOM from 'react-dom';

import App from './components/App';

import { createStore, applyMiddleware } from 'redux';
import { Provider } from 'react-redux';
import createLogger from 'redux-logger';
import reducers from './reducers';

import MuiThemeProvider from 'material-ui/styles/MuiThemeProvider';


const DEV_MODE = location.host.indexOf('localhost') === 0;


let store;
if (DEV_MODE) {
store = createStore(reducers, applyMiddleware(createLogger()));
} else {
store = createStore(reducers);
}


ReactDOM.render(
<Provider store={store}>
<MuiThemeProvider>
<App />
</MuiThemeProvider>
</Provider>,
document.getElementById('main')
);
40 changes: 40 additions & 0 deletions examples/reducers/examples.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
// Action types
export const SET_EXAMPLE = 'examples/SET_EXAMPLE';

export const EXAMPLES = [
{
id: 'simple',
name: 'Simple'
}
];


export const getExample = (id) => {
return _.find(EXAMPLES, { id });
};


// Action generators
export const setExample = (example) => {
if (typeof example === 'object') {
example = example.id;
}
return { type: SET_EXAMPLE, value: example };
};


// The reducers
const DEFAULT_STATE = {
activeExample: EXAMPLES[0].id
};

export default function (state = DEFAULT_STATE, action) {
switch (action.type) {
case SET_EXAMPLE:
return Object.assign({}, state, {
activeExmaple: action.value
});
default:
return state
}
};
10 changes: 10 additions & 0 deletions examples/reducers/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { combineReducers } from 'redux';
import examples from './examples';


const reducers = combineReducers({
examples
});


export default reducers;
7 changes: 6 additions & 1 deletion js/Tracker.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import leftEyeFilter from './filters/left_eye_filter.json';
import rightEyeFilter from './filters/right_eye_filter.json';
import noseFilter from './filters/nose_filter.json';

import modelPca20Svm from '!json!clmtrackr/models/model_pca_20_svm.json';

import {
requestAnimFrame,
Expand All @@ -26,10 +27,14 @@ import procrustes from './utils/procrustes';


const halfPI = Math.PI / 2;

const DEFAULT_MODEL = modelPca20Svm;

const HAS_MOSSE_FILTERS = MosseFilter && leftEyeFilter && rightEyeFilter && noseFilter;
const VALID_RESPONSEMODE_LIST = ['raw', 'sobel', 'lbp'];
const VALID_RESPONSEMODES = ['single', 'blend', 'cycle'];


export default class Tracker extends EventEmitter {
constructor (params) {
super();
Expand Down Expand Up @@ -165,7 +170,7 @@ export default class Tracker extends EventEmitter {
*
* @param <Object> pdm model object
*/
init (pdmmodel) {
init (pdmmodel = DEFAULT_MODEL) {
this.model = pdmmodel;

// load from model
Expand Down
13 changes: 12 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,25 @@
"json-loader": "^0.5.4",
"raf": "^3.1.0",
"stats.js": "0.0.14-master",
"stylus": "^0.54.5",
"stylus-loader": "^2.3.1",
"twgl.js": "^1.9.0",
"uglify": "^0.1.5",
"webpack": "^1.13.2",
"webpack-dev-server": "^1.15.1",
"worker-loader": "^0.7.1"
},
"dependencies": {
"classnames": "^2.2.5",
"jsfeat": "git+https://github.com/inspirit/jsfeat#f584f93c78b5085ef141eb1dc66d9d06a7123ec3",
"numeric": "^1.2.6"
"material-design-color": "^2.3.1",
"material-ui": "^0.15.4",
"numeric": "^1.2.6",
"react": "^15.3.1",
"react-dom": "^15.3.1",
"react-redux": "^4.4.5",
"react-tap-event-plugin": "^1.0.0",
"redux": "^3.6.0",
"redux-logger": "^2.6.1"
}
}
31 changes: 31 additions & 0 deletions ui/container/VideoContainer.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import React, { PropTypes } from 'react';

import './VideoContainer.styl';


export default class VideoContainer extends React.Component {
render () {
return (
<div className='video-container-cmpt'>
<video
ref='video'
autoPlay
loop
{...this.props.videoSize}
>
<source src={this.props.videoSrc} type='video/ogg'/>
</video>

<canvas
ref='canvas'
{...this.props.videoSize}
/>
</div>
);
}
}

VideoContainer.propTypes = {
videoSrc: PropTypes.string,
videoSize: PropTypes.object.isRequired
};
Loading

0 comments on commit f1d2ee9

Please sign in to comment.