Skip to content

Instantly share code, notes, and snippets.

@wchargin
Created December 10, 2015 07:15
  • Star 13 You must be signed in to star a gist
  • Fork 4 You must be signed in to fork a gist
Star You must be signed in to star a gist
Save wchargin/96f2550531b67c379b3e to your computer and use it in GitHub Desktop.
proof-of-concept: rendering musical notes in React
<!-- in dist/ folder -->
<!DOCTYPE html>
<html>
<body>
<div id="app"></div>
</body>
<script src="bundle.js"></script>
</html>
import ReactDOM from 'react-dom';
import React from 'react';
import Notes from './Vex';
import Vex from 'vexflow';
const {Accidental, StaveNote} = Vex.Flow;
const chord1 = [new StaveNote({
keys: ["c/0", "e/4", "g#/8"],
duration: "w",
}).addAccidental(0, new Accidental("bb")).addAccidental(2, new Accidental("#"))];
const chord2 = [new StaveNote({
keys: ["d/4", "f#/4", "a#/4"],
duration: "w",
}).addAccidental(1, new Accidental("#")).addAccidental(2, new Accidental("#"))];
ReactDOM.render(
<div>
<Notes chord={chord1} />
<Notes chord={chord2} />
</div>, document.getElementById("app"));
{
"name": "vexnpm",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC",
"dependencies": {
"babel-preset-react": "^6.3.13",
"react": "^0.14.3",
"react-dom": "^0.14.3",
"vexflow": "^1.2.36"
},
"devDependencies": {
"babel-core": "^6.3.15",
"babel-loader": "^6.2.0",
"babel-preset-es2015": "^6.3.13",
"webpack": "^1.12.9",
"webpack-dev-server": "^1.14.0"
}
}
import Vex from 'vexflow';
import React, {Component} from 'react';
const {
Accidental,
Formatter,
Stave,
StaveNote,
Renderer,
} = Vex.Flow;
export default class Notes extends Component {
render() {
return <div ref="outer" style={{
border: "2px blue solid",
padding: 10,
borderRadius: 10,
display: "inline-block",
}}>
</div>;
}
componentDidMount() {
const {chord} = this.props;
const svgContainer = document.createElement('div');
const renderer = new Renderer(svgContainer, Renderer.Backends.SVG);
const ctx = renderer.getContext();
const stave = new Stave(0, 0, 100); // x, y, width
stave.addClef("treble").setContext(ctx).draw();
const bb = Formatter.FormatAndDraw(ctx, stave, chord);
const svg = svgContainer.childNodes[0];
const padding = 10;
const half = padding / 2;
svg.style.top = -bb.y + half + Math.max(0, (100 - bb.h) * 2/3) + "px";
svg.style.height = Math.max(100, bb.h);
svg.style.left = "0px";
svg.style.width = 100 + "px";
svg.style.position = "absolute";
svg.style.overflow = "visible";
svgContainer.style.height = Math.max(100, bb.h + padding) + "px";
svgContainer.style.width = 100 + "px";
svgContainer.style.position = "relative";
svgContainer.style.display = "inlineBlock";
this.refs.outer.appendChild(svgContainer);
}
}
var webpack = require('webpack');
var prod = process.env.NODE_ENV === 'production';
function entry() {
var mainEntry = './index.jsx';
if (prod) {
return [mainEntry];
} else {
return [
'webpack-dev-server/client?http://localhost:8080',
//'webpack/hot/only-dev-server',
mainEntry,
];
}
}
module.exports = {
devtool: prod ? "source-map" : "eval",
entry: entry(),
module: {
loaders: [
{
test: /\.jsx?$/,
exclude: /node_modules/,
loader: 'babel?presets[]=react&presets[]=es2015&cacheDirectory',
},
{ test: /\.css$/, loader: 'style-loader!css-loader' },
{ test: /\.eot(\?v=\d+\.\d+\.\d+)?$/, loader: "file" },
{ test: /\.(woff|woff2)$/, loader:"url?prefix=font/&limit=5000" },
{ test: /\.ttf(\?v=\d+\.\d+\.\d+)?$/, loader: "url?limit=10000&mimetype=application/octet-stream" },
{ test: /\.svg(\?v=\d+\.\d+\.\d+)?$/, loader: "url?limit=10000&mimetype=image/svg+xml" },
],
},
resolve: {
extensions: ['', '.js', '.jsx'],
},
output: {
path: __dirname + '/dist',
publicPath: '/',
filename: 'bundle.js',
},
devServer: {
contentBase: './dist',
hot: !prod,
},
plugins: prod ?
[new webpack.optimize.UglifyJsPlugin({
compress: {
warnings: false,
},
})] :
[new webpack.HotModuleReplacementPlugin()],
};
@wchargin
Copy link
Author

output

@fmquaglia
Copy link

beautiful, @wchargin 👏 🎶 ❤️

Copy link

ghost commented Feb 1, 2019

nice try 👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment