Upgrade to Pro — share decks privately, control downloads, hide ads and more …

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. 3FBDUKTͱ
    ಈ͘΋ͷɺ
    ໐Δ΋ͷ

    View Slide

  2. XIPBNJ
    ϓϩϑΟʔϧ
    ંݪ ϨΦφϧυݡ
    -FPOBSEP,FO 0SJIBSB
    -*/&גࣜձࣾ 6*5ࣨ
    6TFS*OUFSGBDF5FDIOPMPHZUFBN!-*/&DPSQ

    View Slide

  3. View Slide

  4. ͜ΕΛ۷ΓԼ͛ͨ࿩͠·͢

    View Slide

  5. "HFOEB
    ͳʹΛ࿩͔͢
    ϑϩϯτΤϯυͰΦʔιυοΫεͳ
    3FBDUKT 3FEVYͷ؀ڥͰ
    8FC(- UISFFKT
    ͱ͔
    8FC"VEJP"1* Λ࢖ͬͨ
    5JQTͳΜ͔Λ঺հ
    ಈ͘΋ͷ ໐Δ΋ͷ

    View Slide

  6. ಈ͘΋ͷ

    View Slide

  7. 5JNJOHPGSFOEFSJOH
    ϨϯμϦϯάͷλΠϛϯά

    View Slide

  8. View Slide

  9. 3FBDU8FC(-SFOEFSFS
    3FBDUͱ 8FC(-SFOEFSFS
    composer.render(); Λ܁Γฦ͠ݺͿ
    ௨ৗͷ UISFFKT ͷϨϯμϦϯά
    3FBDU 3FEVYͰϧʔϓॲཧͲ͏͠Α͏ʁ

    View Slide

  10. 3FBDU8FC(-SFOEFSFS
    3FBDUͱ 8FC(-SFOEFSFS
    લఏɿ
    ΦϒδΣΫτ͕͙Δ͙Δͯ͠Δ͚ͩͷ8FCΞϓϦ͸جຊͳ͍

    View Slide

  11. #VJMEPO3FBDUMJGFDZDMF
    3FBDUͷϥΠϑαΠΫϧʹࡌͤͯΈΔ
    export class AnimationGround extends React.Component {
    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
    });
    }
    }
    ٖࣅίʔυ

    View Slide

  12. ΊͪΌͪ͘Όॏ͍
    GQTग़ͤͳ͍
    IUUQTZPVUVCF79FV9L&+6

    View Slide

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

    View Slide

  14. state
    ໰୊ͳ͘ಈ͘
    requestAnimationFrame
    IUUQTZPVUVCF79FV9L&+6 IUUQTZPVUVCF/C-3B55.

    View Slide

  15. • ࡾ֯ؔ਺ͷԋࢉ͕ϝΠϯ
    • ಉ͡ଟ߲ࣜͰɺຖϑϨʔϜಉ͡ܭࢉ
    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
    ͦ΋ͦ΋ࠓճͷॲཧͰͳʹΛ΍͍ͬͯΔ͔

    View Slide

  16. • ࡾ֯ؔ਺ͷԋࢉ͕ϝΠϯ
    • ಉ͡ଟ߲ࣜͰɺຖϑϨʔϜಉ͡ܭࢉ
    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]
    こんな四角形
    ͜ΕΛͲ͏ߴ଎Խ͢Δ͔

    View Slide

  17. 8FC"TTFNCMZΛ࢖͏
    #include
    #include
    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
    ͞ΒͳΔߴ଎Խ
    ٖࣅίʔυ

    View Slide

  18. • ͦ΋ͦ΋ඳըॲཧΛ $16Ͱܭࢉ͢ΔϝϦοτ͕ͳ͍
    • γΣʔμʔʢ(-4-ʣͰܭࢉ͢Δ
    'BTUFTUXBZ
    ͞ΒͳΔɺ͞ΒͳΔߴ଎Խ
    コード考え中
    ܽ఺
    ࠓ·ͰͷྲྀΕͰ͸ͳ͘ɺ৽ͨʹίʔυΛॻ͔ͳ͍ͱ͍͚ͳ͍

    View Slide

  19. $PNCJOBUJPOXJUI)5.-
    ϚʔΫΞοϓͱͷ૊Έ߹Θͤ

    View Slide

  20. (SPVOEHMBTTFGGFDU
    ͢ΓΨϥεޮՌ
    ϦϦʔε൛
    ͢ΓΨϥεޮՌͳ͠
    8FC(-Ͱ΅͔͠Λ͚ͭͣɺ$44ͷ GJMUFSΛ࢖༻
    :local(.container) {
    filter: blur(3px);
    }

    View Slide

  21. (SPVOEHMBTTFGGFDU
    ͢ΓΨϥεޮՌ
    ϦϦʔε൛
    ͢ΓΨϥεޮՌͳ͠
    ϝϦοτ
    • (-ଆ͕Ͱ΍Γ͍ͨࣄͱԋग़͕෼཭Ͱ͖ͯγϯϓϧʹͳΔ
    • $44΋ϞϊʹΑͬͯ͸(16ॲཧ͕Ͱ͖Δ
    • ϢʔβʔೖྗʹΑͬͯԋग़Λม͍͑ͨͱ͖ʹ$44ͷΫϥεΛ
    ม͑Δैདྷͷ΍ΓํͰ௨༻͢Δʢ8FC(-ଆʹύϥϝʔλΛૹΒͳͯ͘ྑ͍ʣ

    View Slide

  22. 5SBOTJUJPO
    τϥϯδγϣϯ
    8FCΞϓϦશମͷը໘స׵͕͞ΕͯΔΑ͏ͳԋग़

    View Slide

  23. 5SBOTJUJPO
    τϥϯδγϣϯ

    View Slide

  24. 5SBOTJUJPO
    τϥϯδγϣϯ
    ͕͜͜τϥϯδγϣϯ͍ͯ͠Δ
    ࠷લ໘ͷཁૉͳͷͰɺ
    ΫϦοΫ൑ఆ΋ୣ͍͍͑ͯײ͡

    View Slide

  25. 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 Λ౉͢͜ͱͰɺ̎ͭͷγʔϯΛ੾ସ͑Δ

    View Slide

  26. ໐Δ΋ͷ

    View Slide

  27. 8IFSFUPTUPSF"VEJPOPEFT
    "VEJPOPEFΛ֨ೲ͢Δ৔ॴ

    View Slide

  28. 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ʹ࣋ͭ

    View Slide

  29. 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Λ֨ೲ͢Δ৔ॴ

    View Slide

  30. // 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Λ֨ೲ͢Δ৔ॴ

    View Slide

  31. "QMBZFSDPNQPOFOU
    ࠶ੜ༻ͷίϯϙʔωϯτ

    View Slide

  32. #VGGFS/PEF ͸̍౓࠶ੜͨ͠Βഁغ͢Δඞཁ͕͋Δ
    "QMBZFSDPNQPOFOU
    ࠶ੜ༻ͷίϯϙʔωϯτ
    4UPSFͰ࠶ੜ͢Δ͚Ͳ
    ίϯϙʔωϯτͷৼΔ෣͍ͱಉظ͍ͨ͠

    View Slide

  33. export class SamplePlayer extends React.Component {
    componentDidMount() {
    this.props.sampleMusicPlay();
    }
    componentWillUnmount() {
    this.props.sampleMusicFadeOut();
    }
    render() {
    return ;
    }
    }
    ٖࣅίʔυ
    "QMBZFSDPNQPOFOU
    ࠶ੜ༻ͷίϯϙʔωϯτ

    View Slide

  34. 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
    ࠶ੜ༻ͷίϯϙʔωϯτ

    View Slide

  35. 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෦෼

    View Slide

  36. $PODMVTJPO
    ࠓ೔࿩ͨ͜͠ͱ

    View Slide

  37. $PODMVTJPO
    ࠓ೔࿩ͨ͜͠ͱ
    3FBDUKT 3FEVYͷ؀ڥͰ
    8FC(- UISFFKT
    ͱ͔
    8FC"VEJP"1* Λ࢖ͬͨ
    5JQT
    ಈ͘΋ͷ ໐Δ΋ͷ

    View Slide

  38. $PODMVTJPO
    ࠓ೔࿩ͨ͜͠ͱ
    • ϨϯμϦϯάͷλΠϛϯάʹ͍ͭͯ
    • ϚʔΫΞοϓͱ૊Έ߹ΘͤͯදݱͰ͖Δྫ
    • "VEJPOPEFͷ֨ೲ৔ॴʹ͍ͭͯ
    • 8FC"VEJPͱίϯϙʔωϯτ؅ཧ

    View Slide