Преглед на файлове

Add props, fix fret widths

Add various props for fretboard display, also made fret widths realistic.
master
TheoryOfNekomata преди 3 години
родител
ревизия
4b10aeafc4
променени са 2 файла, в които са добавени 205 реда и са изтрити 51 реда
  1. +18
    -0
      src/components/Fretboard/Fretboard.stories.tsx
  2. +187
    -51
      src/components/Fretboard/Fretboard.tsx

+ 18
- 0
src/components/Fretboard/Fretboard.stories.tsx Целия файл

@@ -8,3 +8,21 @@ export default {
// By passing optional props to this story, you can control the props of the component when // By passing optional props to this story, you can control the props of the component when
// you consume the story in a test. // you consume the story in a test.
export const Default = (props?: Partial<Props>) => <Fretboard {...props} /> export const Default = (props?: Partial<Props>) => <Fretboard {...props} />

export const ReducedFrets = (props?: Partial<Props>) => <Fretboard {...props} frets={18} />

export const FixedTunings = (props?: Partial<Props>) => <Fretboard {...props} fixedTunings displayTunings />

export const Fretted = (props?: Partial<Props>) => <Fretboard {...props} fretted={[0, 0, 1, 2, 2, 0]} />

export const Tunable = (props?: Partial<Props>) => <Fretboard {...props} displayTunings />

export const LeftHanded = (props?: Partial<Props>) => <Fretboard {...props} leftHanded />

export const Bass = (props?: Partial<Props>) => <Fretboard {...props} tunings={[43, 38, 33, 28]} />

export const ExtendedGuitar = (props?: Partial<Props>) => <Fretboard {...props} tunings={[64, 59, 55, 50, 45, 40, 35, 30]} />

// export const ExtendedBass = (props?: Partial<Props>) => <Fretboard {...props} tunings={[48, 43, 38, 33, 28, 23]} />

export const WithCapo = (props?: Partial<Props>) => <Fretboard {...props} capoFret={8} />

+ 187
- 51
src/components/Fretboard/Fretboard.tsx Целия файл

@@ -1,17 +1,55 @@
import React, { FC } from 'react'
import React, {ChangeEventHandler, FC} from 'react'
import * as PropTypes from 'prop-types' import * as PropTypes from 'prop-types'


const propTypes = { const propTypes = {
tunings: PropTypes.arrayOf(PropTypes.number), tunings: PropTypes.arrayOf(PropTypes.number),
frets: PropTypes.number, frets: PropTypes.number,
leftHanded: PropTypes.bool, leftHanded: PropTypes.bool,
fixedTunings: PropTypes.bool,
displayTunings: PropTypes.bool,
capoFret: PropTypes.number,
fretted: PropTypes.arrayOf(PropTypes.number),
} }


export type Props = PropTypes.InferProps<typeof propTypes> export type Props = PropTypes.InferProps<typeof propTypes>


const PITCHES = 'C C# D D# E F F# G G# A A# B'.split(' ') const PITCHES = 'C C# D D# E F F# G G# A A# B'.split(' ')


const Fretboard: FC<Props> = ({ tunings = [64, 59, 55, 50, 45, 40], frets = 24, leftHanded = false }) => {
const getPitchName = (n: number) => PITCHES[n % 12] + Math.floor(n / 12)

const Fretboard: FC<Props> = ({
tunings = [64, 59, 55, 50, 45, 40],
frets = 24,
leftHanded = false,
fixedTunings = false,
displayTunings = false,
capoFret = 0,
fretted = [],
}) => {
const [clientSide, setClientSide, ] = React.useState(false)
const [pitches, setPitches, ] = React.useState<string[]>(tunings!.map(t => getPitchName(t!)))

const updateStringPitch = (currentStringNumber: number): ChangeEventHandler<HTMLInputElement> => e => {
const { value } = e.target
setPitches(oldPitches => [
...oldPitches.slice(0, currentStringNumber),
getPitchName(Number(value)),
...oldPitches.slice(currentStringNumber + 1),
])
}

React.useEffect(() => {
setClientSide(true)
}, [])

// React.useEffect(() => {
// if (!Array.isArray(tunings!)) {
// return
// }
//
// setPitches(() => tunings.map(t => getPitchName(t!)))
// }, [tunings])

if (!Array.isArray(tunings!)) { if (!Array.isArray(tunings!)) {
return null return null
} }
@@ -23,59 +61,80 @@ const Fretboard: FC<Props> = ({ tunings = [64, 59, 55, 50, 45, 40], frets = 24,
style={{ style={{
border: '0.0625rem solid', border: '0.0625rem solid',
boxSizing: 'border-box', boxSizing: 'border-box',
transform: leftHanded
? 'perspective(6rem) rotateY(2deg) scaleX(1.375)'
: 'perspective(6rem) rotateY(-2deg) scaleX(1.375)',
transformOrigin: leftHanded ? 'left' : 'right',
}} }}
> >
{strings!.map((pitches, stringNumber) => (
{strings!.map((stringPitches, stringNumber) => (
<div <div
style={{ style={{
display: 'flex', display: 'flex',
flexDirection: leftHanded ? 'row-reverse' : 'row', flexDirection: leftHanded ? 'row-reverse' : 'row',
}} }}
> >
<div
style={{
display: 'flex',
flexDirection: leftHanded ? 'row-reverse' : 'row',
width: '5rem',
height: '1rem',
padding: 0,
boxSizing: 'border-box',
}}
>
<input
type="number"
style={{
display: 'block',
width: '3rem',
height: '1rem',
padding: 0,
boxSizing: 'border-box',
}}
defaultValue={tunings[stringNumber]!}
min={0}
max={127}
/>
<span
style={{
display: 'block',
width: '2rem',
height: '1rem',
textAlign: leftHanded ? 'left' : 'right',
}}
>
{PITCHES[tunings[stringNumber]! % 12]}
{Math.floor(tunings[stringNumber]! / 12)}
</span>
</div>
{
displayTunings
&& (
<div
style={{
display: 'block',
width: '5rem',
height: '1rem',
padding: '0 0 0 1rem',
boxSizing: 'border-box',
position: 'relative',
flexShrink: 0,
}}
>
<div
style={{
display: 'block',
width: '100%',
height: '100%',
padding: 0,
boxSizing: 'border-box',
position: 'relative',
}}
>
<span
style={{
display: 'block',
width: '2rem',
height: '100%',
position: 'absolute',
top: 0,
left: 0,
pointerEvents: 'none',
}}
>
{pitches[stringNumber]}
</span>
<input
type="number"
style={{
display: 'block',
width: '100%',
height: '100%',
padding: 0,
boxSizing: 'border-box',
border: 0,
backgroundColor: 'transparent',
font: 'inherit',
textAlign: 'right',
}}
readOnly={!clientSide || Boolean(fixedTunings)}
onChange={updateStringPitch(stringNumber)}
defaultValue={tunings[stringNumber]!}
min={0}
max={127}
/>
</div>
</div>
)
}
<div <div
style={{ style={{
display: 'block', display: 'block',
position: 'relative', position: 'relative',
width: '1rem',
width: '0.5rem',
height: '1rem', height: '1rem',
flexShrink: 0, flexShrink: 0,
padding: 0, padding: 0,
@@ -88,8 +147,8 @@ const Fretboard: FC<Props> = ({ tunings = [64, 59, 55, 50, 45, 40], frets = 24,
style={{ style={{
position: 'relative', position: 'relative',
display: 'block', display: 'block',
width: '1rem',
height: '1rem',
width: '100%',
height: '100%',
flexShrink: 0, flexShrink: 0,
padding: 0, padding: 0,
border: 0, border: 0,
@@ -104,12 +163,40 @@ const Fretboard: FC<Props> = ({ tunings = [64, 59, 55, 50, 45, 40], frets = 24,
backgroundColor: 'currentColor', backgroundColor: 'currentColor',
}} }}
/> />
{
fretted![stringNumber] === 0
&& (
<span
style={{
position: 'absolute',
top: 0,
left: 0,
height: '100%',
width: '100%',
display: 'flex',
alignItems: 'center',
justifyContent: 'space-around',
flexDirection: 'column',
color: 'red',
}}
>
<span
style={{
width: '0.75rem',
height: '0.75rem',
backgroundColor: 'currentColor',
borderRadius: '50%',
}}
/>
</span>
)
}
</button> </button>
</div> </div>
{pitches.map((_, i) => (
{stringPitches.map((_, i) => (
<div <div
style={{ style={{
width: `${(frets! - i + frets! / 2) * 100}%`,
width: `${(frets! - i - 1) / 12 * 100 + 100}%`,
height: '1rem', height: '1rem',
position: 'relative', position: 'relative',
}} }}
@@ -129,8 +216,8 @@ const Fretboard: FC<Props> = ({ tunings = [64, 59, 55, 50, 45, 40], frets = 24,
> >
<div <div
style={{ style={{
width: `${0.75 - i * (1 / 80)}rem`,
height: `${0.75 - i * (1 / 256)}rem`,
width: '0.75rem',
height: '0.75rem',
backgroundColor: 'currentColor', backgroundColor: 'currentColor',
opacity: 0.5, opacity: 0.5,
borderRadius: '50%', borderRadius: '50%',
@@ -139,8 +226,8 @@ const Fretboard: FC<Props> = ({ tunings = [64, 59, 55, 50, 45, 40], frets = 24,
{i % 12 === 11 && ( {i % 12 === 11 && (
<div <div
style={{ style={{
width: `${0.75 - i * (1 / 80)}rem`,
height: `${0.75 - i * (1 / 256)}rem`,
width: '0.75rem',
height: '0.75rem',
backgroundColor: 'currentColor', backgroundColor: 'currentColor',
opacity: 0.5, opacity: 0.5,
borderRadius: '50%', borderRadius: '50%',
@@ -171,7 +258,56 @@ const Fretboard: FC<Props> = ({ tunings = [64, 59, 55, 50, 45, 40], frets = 24,
backgroundColor: 'currentColor', backgroundColor: 'currentColor',
}} }}
/> />
{
fretted![stringNumber] === i + 1
&& (
<span
style={{
position: 'absolute',
top: 0,
left: 0,
height: '100%',
width: '100%',
display: 'flex',
alignItems: 'center',
justifyContent: 'space-around',
flexDirection: 'column',
color: 'red',
}}
>
<span
style={{
width: '0.75rem',
height: '0.75rem',
backgroundColor: 'currentColor',
borderRadius: '50%',
}}
/>
</span>
)
}
</button> </button>
{
capoFret === (i + 1) && stringNumber === 0 && (
<div
style={{
position: 'absolute',
top: 0,
height: `${tunings.length * 100}%`,
width: '100%',
}}
>
<div
style={{
width: '0.75rem',
height: '100%',
backgroundColor: 'currentColor',
borderRadius: '0.375rem',
}}
/>
</div>
)
}
</div> </div>
))} ))}
</div> </div>


Зареждане…
Отказ
Запис