OneFingerResponse.js 2.53 KB
Newer Older
Gaëtan Renaudeau's avatar
Gaëtan Renaudeau committed
1 2
import React from "react";
import {PanResponder, UIManager, findNodeHandle} from "react-native";
3 4
import GL from "gl-react";
import {Surface} from "gl-react-native";
5

Gaëtan Renaudeau's avatar
Gaëtan Renaudeau committed
6
const shaders = GL.Shaders.create({
Gaëtan Renaudeau's avatar
Gaëtan Renaudeau committed
7
  oneFingerResponse: {
Gaëtan Renaudeau's avatar
Gaëtan Renaudeau committed
8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
    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
25
class OneFingerResponse extends React.Component {
Gaëtan Renaudeau's avatar
Gaëtan Renaudeau committed
26 27 28 29
  constructor (props) {
    super(props);
    this.state = {
      pressed: 0,
30 31
      position: [ 0, 0 ],
      surfaceBound: [ 0, 0, 1, 1 ] // x, y, w, h
Gaëtan Renaudeau's avatar
Gaëtan Renaudeau committed
32
    };
33 34 35 36 37 38 39 40 41

    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(
Gaëtan Renaudeau's avatar
Gaëtan Renaudeau committed
42
          findNodeHandle(this.refs.surface),
43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67
          (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
68
    });
69

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

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