mirror of
https://github.com/captbaritone/webamp.git
synced 2026-08-02 06:52:19 +00:00
First stab at spline line for equalizer
This commit is contained in:
parent
1f5e7503b0
commit
99e9e70ce6
4 changed files with 120 additions and 39 deletions
29
js/__tests__/EqGraph--test.js
Normal file
29
js/__tests__/EqGraph--test.js
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
jest.unmock('../components/EqGraph.jsx');
|
||||
|
||||
import {
|
||||
roundToEven,
|
||||
getY
|
||||
} from '../components/EqGraph.jsx';
|
||||
|
||||
describe('roundToEven', () => {
|
||||
it('leaves even numbers as is', () => {
|
||||
const actual = roundToEven(4);
|
||||
const expected = 4;
|
||||
expect(actual).toEqual(expected);
|
||||
});
|
||||
it('handles zero', () => {
|
||||
const actual = roundToEven(0);
|
||||
const expected = 0;
|
||||
expect(actual).toEqual(expected);
|
||||
});
|
||||
it('handles odd numbers', () => {
|
||||
const actual = roundToEven(3);
|
||||
const expected = 4;
|
||||
expect(actual).toEqual(expected);
|
||||
});
|
||||
});
|
||||
|
||||
describe('getY', () => {
|
||||
it('gives the first sprite', () => {
|
||||
});
|
||||
});
|
||||
|
|
@ -1,13 +1,21 @@
|
|||
import React from 'react';
|
||||
import {connect} from 'react-redux';
|
||||
import {getCurvePoints} from 'cardinal-spline-js';
|
||||
|
||||
import {BANDS} from '../constants';
|
||||
|
||||
export const roundToEven = (value) => (
|
||||
2 * Math.round(value / 2)
|
||||
);
|
||||
|
||||
export const getY = (value) => (
|
||||
32 - ((value / 100) * 32)
|
||||
roundToEven(32 - ((value / 100) * 32))
|
||||
);
|
||||
|
||||
class EqGraph extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {};
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
|
|
@ -15,64 +23,91 @@ class EqGraph extends React.Component {
|
|||
this.canvasCtx.imageSmoothingEnabled = false;
|
||||
this.width = this.refs.canvas.width * 1; // Cast to int
|
||||
this.height = this.refs.canvas.height * 1; // Cast to int
|
||||
this.bgImage = new Image();
|
||||
this.bgImage.onload = () => {
|
||||
this.createColorPattern();
|
||||
this.componentDidUpdate();
|
||||
};
|
||||
this.bgImage.src = 'bg.png';
|
||||
}
|
||||
|
||||
componentDidUpdate() {
|
||||
this.canvasCtx.clearRect(0, 0, this.width, this.height);
|
||||
//this.createColorPattern();
|
||||
this.drawPreampLine();
|
||||
this.drawEqLine(); // This should paint on top of the preamp line
|
||||
}
|
||||
|
||||
createColorPattern() {
|
||||
const colorsCanvas = document.createElement('canvas');
|
||||
const colorsCtx = colorsCanvas.getContext('2d');
|
||||
colorsCanvas.width = this.bgImage.width * 2;
|
||||
colorsCanvas.height = this.bgImage.height * 2;
|
||||
colorsCtx.drawImage(this.bgImage, 0, 0, colorsCanvas.width, colorsCanvas.height);
|
||||
this.colorPattern = this.canvasCtx.createPattern(colorsCanvas, 'repeat-x');
|
||||
shouldComponentUpdate(nextProps) {
|
||||
if (this.props.lineColorsImage !== nextProps.lineColorsImage) {
|
||||
this.createColorPattern(nextProps.lineColorsImage);
|
||||
}
|
||||
if (this.props.preampLineUrl !== nextProps.preampLineUrl) {
|
||||
this.createPreampLineImage(nextProps.preampLineUrl);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
createPreampLineImage(preampLineUrl) {
|
||||
const preampLineImg = new Image();
|
||||
preampLineImg.onload = () => {
|
||||
this.setState({preampLineImg});
|
||||
};
|
||||
preampLineImg.src = preampLineUrl;
|
||||
}
|
||||
|
||||
createColorPattern(lineColorsImage) {
|
||||
const bgImage = new Image();
|
||||
bgImage.onload = () => {
|
||||
const colorsCanvas = document.createElement('canvas');
|
||||
const colorsCtx = colorsCanvas.getContext('2d');
|
||||
colorsCanvas.width = bgImage.width * 2;
|
||||
colorsCanvas.height = bgImage.height * 2;
|
||||
colorsCtx.drawImage(bgImage, 0, 0, colorsCanvas.width, colorsCanvas.height);
|
||||
this.setState({
|
||||
colorPattern: this.canvasCtx.createPattern(colorsCanvas, 'repeat-x')
|
||||
});
|
||||
};
|
||||
bgImage.src = lineColorsImage;
|
||||
}
|
||||
|
||||
drawEqLine() {
|
||||
if (!this.state.colorPattern) {
|
||||
// The skin has not finished loading yet
|
||||
return;
|
||||
}
|
||||
const {props} = this;
|
||||
const values = [
|
||||
props[60],
|
||||
props[170],
|
||||
props[310],
|
||||
props[600],
|
||||
props[1000],
|
||||
props[3000],
|
||||
props[6000],
|
||||
props[12000],
|
||||
props[14000],
|
||||
props[16000]
|
||||
];
|
||||
const amplitudes = BANDS.map((band) => props[band]);
|
||||
|
||||
this.canvasCtx.strokeStyle = this.colorPattern;
|
||||
this.canvasCtx.strokeStyle = this.state.colorPattern;
|
||||
this.canvasCtx.lineWidth = 2;
|
||||
this.canvasCtx.beginPath();
|
||||
const paddingLeft = 4;
|
||||
// TODO: Curve these lines
|
||||
values.forEach((value, i) => {
|
||||
this.canvasCtx.lineTo(paddingLeft + (i * 16), getY(value));
|
||||
|
||||
let points = [];
|
||||
amplitudes.forEach((value, i) => {
|
||||
points = points.concat(paddingLeft + (i * 16), getY(value));
|
||||
});
|
||||
|
||||
// Spline between points in order to create nice curves
|
||||
const tension = 0.5;
|
||||
const resolution = 4; // Points in each segment
|
||||
const smoothPoints = getCurvePoints(points, tension, resolution);
|
||||
for (let i = 0; i < smoothPoints.length; i += 2) {
|
||||
this.canvasCtx.lineTo(smoothPoints[i], smoothPoints[i + 1]);
|
||||
}
|
||||
|
||||
this.canvasCtx.stroke();
|
||||
}
|
||||
|
||||
drawPreampLine() {
|
||||
// TODO: Use the line from the skin image
|
||||
const preampValue = getY(this.props.preamp);
|
||||
this.canvasCtx.lineWidth = 2;
|
||||
this.canvasCtx.strokeStyle = 'white';
|
||||
this.canvasCtx.beginPath();
|
||||
this.canvasCtx.moveTo(0, preampValue);
|
||||
this.canvasCtx.lineTo(this.width, preampValue);
|
||||
this.canvasCtx.stroke();
|
||||
const {preampLineImg} = this.state;
|
||||
if (!preampLineImg) {
|
||||
// The skin has not finished loading yet
|
||||
return;
|
||||
}
|
||||
const preampValue = getY(100 - this.props.preamp);
|
||||
this.canvasCtx.drawImage(
|
||||
this.state.preampLineImg,
|
||||
0,
|
||||
preampValue,
|
||||
preampLineImg.width * 2,
|
||||
preampLineImg.height * 2
|
||||
);
|
||||
}
|
||||
|
||||
render() {
|
||||
|
|
@ -85,4 +120,8 @@ class EqGraph extends React.Component {
|
|||
}
|
||||
}
|
||||
|
||||
export default connect((state) => state.equalizer.sliders)(EqGraph);
|
||||
export default connect((state) => ({
|
||||
...state.equalizer.sliders,
|
||||
lineColorsImage: state.display.skinImages.EQ_GRAPH_LINE_COLORS,
|
||||
preampLineUrl: state.display.skinImages.EQ_PREAMP_LINE
|
||||
}))(EqGraph);
|
||||
|
|
|
|||
12
js/constants.js
Normal file
12
js/constants.js
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
export const BANDS = [
|
||||
60,
|
||||
170,
|
||||
310,
|
||||
600,
|
||||
1000,
|
||||
3000,
|
||||
6000,
|
||||
12000,
|
||||
14000,
|
||||
16000
|
||||
];
|
||||
|
|
@ -50,6 +50,7 @@
|
|||
"dependencies": {
|
||||
"babel-plugin-transform-object-rest-spread": "^6.8.0",
|
||||
"babel-plugin-transform-react-jsx": "^6.8.0",
|
||||
"cardinal-spline-js": "^2.3.6",
|
||||
"classnames": "^2.2.5",
|
||||
"jszip": "^2.6.0",
|
||||
"react": "^15.2.0",
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue