$30 off During Our Annual Pro Sale. View Details »

React.js と動くもの、鳴るもの

React.js と動くもの、鳴るもの

UIT meetup vol.7 で発表した内容です!
https://uit.connpass.com/event/138084/

↓の記事の内容が大筋になっています!
Webでどこまで遊べるか試してみた
https://qiita.com/Leonardo-mbc/items/3c365836acfd71a55185

React ライフサイクルの demo
https://youtu.be/VXeuXkEJ76U

requestAnimationFrame の demo
https://youtu.be/40NbLRaTT6M

LeonardoKen Orihara

July 24, 2019
Tweet

More Decks by LeonardoKen Orihara

Other Decks in Technology

Transcript

  1.  #VJMEPO3FBDUMJGFDZDMF 3FBDUͷϥΠϑαΠΫϧʹࡌͤͯΈΔ export class AnimationGround extends React.Component<Props, State> {

    constructor(props: Props, state: State) { super(props); this.state = { position: { x: 0, y: 0, z: 0 } } } componentDidUpdate() { composer.render(); const newPosition = ... this.setState({ position: newPosition }); } } ٖࣅίʔυ
  2.  #VJMEPO3FBDUDPNQPOFOU 3FBDUͷίϯϙʔωϯτͰಈ͔ͯ͠ΈΔ export class AnimationGround extends React.Component<Props, State> {

    constructor(props: Props, state: State) { super(props); this.position = { x: 0, y: 0, z: 0 }; } componentDidMount() { requestAnimationFrame(this.renderAnim); } renderAnim = () => { this.position = ... composer.render(); } } ٖࣅίʔυ
  3. • ࡾ֯ؔ਺ͷԋࢉ͕ϝΠϯ • ಉ͡ଟ߲ࣜͰɺຖϑϨʔϜಉ͡ܭࢉ for (let i = 0; i

    < freqsLength; i++) { const thetaMuli = theta * i; const thetaPlusPI = thetaMuli + Math.PI / 2; const thetaSubPI = thetaMuli - Math.PI / 2; spectrumVertices[2].x = value * Math.cos(thetaMuli) + halfWidth * Math.cos(thetaPlusPI); spectrumVertices[2].y = value * Math.sin(thetaMuli) + halfWidth * Math.sin(thetaPlusPI); spectrumVertices[3].x = value * Math.cos(thetaMuli) + halfWidth * Math.cos(thetaSubPI); spectrumVertices[3].y = value * Math.sin(thetaMuli) + halfWidth * Math.sin(thetaSubPI); spectrumGeometry.verticesNeedUpdate = true; } ٖࣅίʔυ  )PXUPDBMDVMBUFUIFTQFDUSVN ͦ΋ͦ΋ࠓճͷॲཧͰͳʹΛ΍͍ͬͯΔ͔
  4. • ࡾ֯ؔ਺ͷԋࢉ͕ϝΠϯ • ಉ͡ଟ߲ࣜͰɺຖϑϨʔϜಉ͡ܭࢉ for (let i = 0; i

    < freqsLength; i++) { const thetaMuli = theta * i; const thetaPlusPI = thetaMuli + Math.PI / 2; const thetaSubPI = thetaMuli - Math.PI / 2; spectrumVertices[2].x = value * Math.cos(thetaMuli) + halfWidth * Math.cos(thetaPlusPI); spectrumVertices[2].y = value * Math.sin(thetaMuli) + halfWidth * Math.sin(thetaPlusPI); spectrumVertices[3].x = value * Math.cos(thetaMuli) + halfWidth * Math.cos(thetaSubPI); spectrumVertices[3].y = value * Math.sin(thetaMuli) + halfWidth * Math.sin(thetaSubPI); spectrumGeometry.verticesNeedUpdate = true; } ٖࣅίʔυ  )PXUPDBMDVMBUFUIFTQFDUSVN ͦ΋ͦ΋ࠓճͷॲཧͰͳʹΛ΍͍ͬͯΔ͔ [2].x = 振幅 * cos(角度) + 幅/2 * cos(角度+Δ); [2].y = 振幅 * sin(角度) + 幅/2 * sin(角度+Δ); [3].x = 振幅 * cos(角度) + 幅/2 * cos(角度-Δ); [3].y = 振幅 * sin(角度) + 幅/2 * sin(角度-Δ); [0] === [1] こんな四角形 ͜ΕΛͲ͏ߴ଎Խ͢Δ͔
  5. 8FC"TTFNCMZΛ࢖͏ #include <cmath> #include <iostream> using namespace std; int calcSpectrum(int

    freqsLength) { static const double PI = 3.141592653589793; for (int i = 0; i < freqsLength; i++) { double thetaMuli = theta * i; double thetaPlusPI = thetaMuli + PI / 2.0; double thetaSubPI = thetaMuli - PI / 2.0; double v2x = value * cos(thetaMuli) + halfWidth * cos(thetaPlusPI); double v2y = value * sin(thetaMuli) + halfWidth * sin(thetaPlusPI); double v3x = value * cos(thetaMuli) + halfWidth * cos(thetaSubPI); double v3y = value * sin(thetaMuli) + halfWidth * sin(thetaSubPI); } }  'VSUIFSGBTUFS ͞ΒͳΔߴ଎Խ ٖࣅίʔυ
  6.  (SPVOEHMBTTFGGFDU ͢ΓΨϥεޮՌ ϦϦʔε൛ ͢ΓΨϥεޮՌͳ͠ ϝϦοτ • (-ଆ͕Ͱ΍Γ͍ͨࣄͱԋग़͕෼཭Ͱ͖ͯγϯϓϧʹͳΔ • $44΋ϞϊʹΑͬͯ͸(16ॲཧ͕Ͱ͖Δ

    • ϢʔβʔೖྗʹΑͬͯԋग़Λม͍͑ͨͱ͖ʹ$44ͷΫϥεΛ ม͑Δैདྷͷ΍ΓํͰ௨༻͢Δʢ8FC(-ଆʹύϥϝʔλΛૹΒͳͯ͘ྑ͍ʣ
  7.  5SBOTJUJPO τϥϯδγϣϯ uniform float mixRatio; uniform sampler2D tDiffuse1; uniform

    sampler2D tDiffuse2; varying vec2 vUv; void main() { vec4 tex1 = texture2D(tDiffuse1, vUv); vec4 tex2 = texture2D(tDiffuse2, vUv); gl_FragColor = mix(tex2, tex1, mixRatio); } ٖࣅίʔυ +4ଆ͔Β mixRatio Λ౉͢͜ͱͰɺ̎ͭͷγʔϯΛ੾ସ͑Δ
  8.  8IFSFUPTUPSF"VEJPOPEFT "VEJPOPEFΛ֨ೲ͢Δ৔ॴ export const initialState: State = { system:

    { sound: { sources: { titleMusic: null, unlockedSound: null, musicSamples: {}, }, context: null, systemGainNode: null, cueAGainNode: null, cueBGainNode: null, analyzerNode: null, filterNode: null, analyzerParams: null, } }, ... } ٖࣅίʔυ ݁ہશ෦ 4UPSFʹ࣋ͭ
  9. export function reducer(state: SystemState = initialState.system, action: ActionTypes): SystemState {

    switch (action.type) { case CREATE_SOUNDS_LINE: const context = new AudioContext(); const cueAGainNode = context.createGain(); const cueBGainNode = context.createGain(); const analyzerNode = context.createAnalyser(); cueAGainNode.connect(analyzerNode); cueBGainNode.connect(analyzerNode); analyzerNode.connect(context.destination); return { ...state, sound: { ...state.sound, context, cueAGainNode, cueBGainNode, analyzerNode } }; } } ٖࣅίʔυ 3FEVDFSͰ૊Έཱͯ  8IFSFUPTUPSF"VEJPOPEFT "VEJPOPEFΛ֨ೲ͢Δ৔ॴ
  10. // Action export const sampleMusicPlay = ({ musicId }: SampleMusicPlayPayload):

    SampleMusicPlay => ({ type: SAMPLE_MUSIC_PLAY, payload: { musicId }, }); // redux-saga takeEvery(SAMPLE_MUSIC_PLAY, function*(action: SampleMusicPlay) { const { musicId } = action.payload; const store = yield select(); const sound = store.system.sound as Sound; const { samples } = sound.sources; samples[musicId].start(0, 0); }) ٖࣅίʔυ "DUJPOˠ 4BHBܦ༝Ͱ࠶ੜ  8IFSFUPTUPSF"VEJPOPEFT "VEJPOPEFΛ֨ೲ͢Δ৔ॴ
  11. export class SamplePlayer extends React.Component<SamplePlayerProps, SamplePlayerState> { componentDidMount() { this.props.sampleMusicPlay();

    } componentWillUnmount() { this.props.sampleMusicFadeOut(); } render() { return <div />; } } ٖࣅίʔυ  "QMBZFSDPNQPOFOU ࠶ੜ༻ͷίϯϙʔωϯτ
  12. takeEvery(SAMPLE_MUSIC_FADE_OUT, function*(action: SampleMusicFadeOut) { const fadeTime = action.payload.duration || 250;

    new TWEEN.Tween(gainNode.gain) .to({ value: 0.0 }, fadeTime) .onComplete(() => { try { bufferNode.buffer.stop(); } catch (e) {} }).start(); yield put(remakeSampleSounds({ bufferNode, gainNode }); }) ٖࣅίʔυ  "QMBZFSDPNQPOFOU ࠶ੜ༻ͷίϯϙʔωϯτ
  13. takeEvery(SAMPLE_MUSIC_FADE_OUT, function*(action: SampleMusicFadeOut) { const fadeTime = action.payload.duration || 250;

    new TWEEN.Tween(gainNode.gain) .to({ value: 0.0 }, fadeTime) .onComplete(() => { try { bufferNode.buffer.stop(); } catch (e) {} }).start(); yield put(remakeSampleSounds({ bufferNode, gainNode }); }) ٖࣅίʔυ  "QMBZFSDPNQPOFOU ࠶ੜ༻ͷίϯϙʔωϯτ const buffer = bufferNode.buffer; const bufferNode = context.createBufferSource(); bufferNode.buffer = buffer; bufferNode.loop = true; bufferNode.connect(gainNode); ٖࣅίʔυ 3FNBLF෦෼