OneFingerResponse.js 2.46 KB
Newer Older
1 2 3
import React, {PanResponder, UIManager} from "react-native";
import GL from "gl-react";
import {Surface} from "gl-react-native";
4

Gaëtan Renaudeau's avatar
Gaëtan Renaudeau committed
5
const shaders = GL.Shaders.create({
Gaëtan Renaudeau's avatar
Gaëtan Renaudeau committed
6
  oneFingerResponse: {
Gaëtan Renaudeau's avatar
Gaëtan Renaudeau committed
7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
    frag: `
precision mediump float;
varying vec2 uv;

uniform float pressed;
uniform vec2 position;

void main () {
  float dist = pow(1.0 - distance(position, uv), 4.0);
  float edgeDistX = pow(1.0 - distance(position.x, uv.x), 24.0);
  float edgeDistY = pow(1.0 - distance(position.y, uv.y), 24.0);
  gl_FragColor = pressed * vec4(0.8 * dist + edgeDistX, 0.7 * dist + edgeDistY, 0.6 * dist, 1.0);
}
    `
  }
});

Gaëtan Renaudeau's avatar
Gaëtan Renaudeau committed
24
class OneFingerResponse extends React.Component {
Gaëtan Renaudeau's avatar
Gaëtan Renaudeau committed
25 26 27 28
  constructor (props) {
    super(props);
    this.state = {
      pressed: 0,
29 30
      position: [ 0, 0 ],
      surfaceBound: [ 0, 0, 1, 1 ] // x, y, w, h
Gaëtan Renaudeau's avatar
Gaëtan Renaudeau committed
31
    };
32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66

    this._panResponder = PanResponder.create({
      onStartShouldSetPanResponder: (evt, gestureState) => true,
      onStartShouldSetPanResponderCapture: (evt, gestureState) => true,
      onMoveShouldSetPanResponder: (evt, gestureState) => true,
      onMoveShouldSetPanResponderCapture: (evt, gestureState) => true,

      onPanResponderGrant: (evt, gestureState) =>
        UIManager.measure(
          React.findNodeHandle(this.refs.surface),
          (a, b, w, h, x, y) =>
            this.setState({
              pressed: 1,
              surfaceBound: [x,y,w,h],
              position: [ gestureState.x0, gestureState.y0 ]
            })),

      onPanResponderMove: (evt, gestureState) =>
        this.setState({
          position: [ gestureState.x0 + gestureState.dx, gestureState.y0 + gestureState.dy ]
        }),

      onPanResponderTerminationRequest: (evt, gestureState) => true,

      onPanResponderRelease: (evt, gestureState) =>
        this.setState({
          pressed: 0
        }),

      onPanResponderTerminate: (evt, gestureState) =>
        this.setState({
          pressed: 0
        }),

      onShouldBlockNativeResponder: (evt, gestureState) => true
Gaëtan Renaudeau's avatar
Gaëtan Renaudeau committed
67
    });
68

Gaëtan Renaudeau's avatar
Gaëtan Renaudeau committed
69 70 71
  }
  render () {
    const { width, height } = this.props;
72 73 74 75 76
    const { pressed, position:[x,y], surfaceBound: [sx,sy,sw,sh] } = this.state;
    const position = [
      (x - sx) / sw,
      1 - (y - sy) / sh
    ];
77
    return <Surface
78 79
      ref="surface"
      {...this._panResponder.panHandlers}
Gaëtan Renaudeau's avatar
Gaëtan Renaudeau committed
80
      width={width}
81 82 83 84 85 86
      height={height}>
      <GL.Node
        shader={shaders.oneFingerResponse}
        uniforms={{ pressed, position }}
      />
    </Surface>;
Gaëtan Renaudeau's avatar
Gaëtan Renaudeau committed
87 88 89
  }
}

Gaëtan Renaudeau's avatar
Gaëtan Renaudeau committed
90
module.exports = OneFingerResponse;