UNPKG

6.91 kBJavaScriptView Raw
1'use strict';
2
3var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
4
5Object.defineProperty(exports, "__esModule", {
6 value: true
7});
8
9var _react = require('react');
10
11var _react2 = _interopRequireDefault(_react);
12
13var _rx = require('rx');
14
15var _rx2 = _interopRequireDefault(_rx);
16
17var _lodash = require('lodash.throttle');
18
19var _lodash2 = _interopRequireDefault(_lodash);
20
21function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
22
23function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
24
25function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
26
27function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
28
29function eventPreventDefault(event) {
30 event.preventDefault();
31}
32
33function isTouch() {
34 return 'ontouchstart' in window || navigator.MaxTouchPoints > 0 || navigator.msMaxTouchPoints > 0;
35}
36
37function hasTwoTouchPoints(event) {
38 if (isTouch()) return event.touches && event.touches.length === 2;else return event.altKey;
39}
40
41function logger(subject) {
42 console.log(subject);
43}
44
45function between(min, max, val) {
46 return Math.min(max, Math.max(min, val));
47}
48function inverse(val) {
49 return val * -1;
50}
51
52function normalizeTouch(e) {
53 var p = isTouch() ? e.touches[0] : e;
54 return { x: p.clientX, y: p.clientY };
55}
56
57var ReactPinchZoomPan = function (_Component) {
58 _inherits(ReactPinchZoomPan, _Component);
59
60 function ReactPinchZoomPan(props) {
61 _classCallCheck(this, ReactPinchZoomPan);
62
63 var _this = _possibleConstructorReturn(this, Object.getPrototypeOf(ReactPinchZoomPan).call(this, props));
64
65 _this.state = { obj: {
66 scale: 1,
67 x: 0,
68 y: 0
69 } };
70 return _this;
71 }
72
73 _createClass(ReactPinchZoomPan, [{
74 key: 'resize',
75 value: function resize() {
76 if (this.refs.root) {
77 var domNode = this.refs.root;
78 this.setState({
79 size: { width: domNode.offsetWidth, height: domNode.offsetHeight }
80 });
81 }
82 }
83 }, {
84 key: 'componentWillMount',
85 value: function componentWillMount() {
86 this.handlePinch();
87 }
88 }, {
89 key: 'componentWillUnmount',
90 value: function componentWillUnmount() {
91 if (this.pinchSubscription) {
92 this.pinchSubscription.dispose();
93 }
94 window.removeEventListener('resize', this.resize);
95 }
96 }, {
97 key: 'componentDidMount',
98 value: function componentDidMount() {
99 var _this2 = this;
100
101 this.resize();
102 window.addEventListener('resize', (0, _lodash2.default)(function () {
103 return _this2.resize();
104 }, 500));
105 }
106 }, {
107 key: 'handlePinch',
108 value: function handlePinch() {
109 var _this3 = this;
110
111 var touchStart = _rx2.default.Observable.fromEvent(window, isTouch() ? 'touchstart' : 'mousedown');
112 var touchMove = _rx2.default.Observable.fromEvent(window, isTouch() ? 'touchmove' : 'mousemove');
113 var touchEnd = _rx2.default.Observable.fromEvent(window, isTouch() ? 'touchend' : 'mouseup');
114
115 function translatePos(point, size) {
116 return {
117 x: point.x - size.width / 2,
118 y: point.y - size.height / 2
119 };
120 }
121
122 function momentum(newValue, oldValue) {
123 return oldValue / newValue * newValue * 1.01;
124 }
125
126 var pinch = touchStart.tap(eventPreventDefault).flatMap(function (md) {
127 var startPoint = normalizeTouch(md);
128 var size = _this3.state.size;
129
130 return touchMove.map(function (mm) {
131 var _state$obj = _this3.state.obj;
132 var scale = _state$obj.scale;
133 var x = _state$obj.x;
134 var y = _state$obj.y;
135 var maxScale = _this3.props.maxScale;
136
137 var movePoint = normalizeTouch(mm);
138
139 if (hasTwoTouchPoints(mm)) {
140 var scaleFactor = undefined;
141 if (isTouch()) {
142 scaleFactor = mm.scale;
143 } else {
144 scaleFactor = movePoint.x < size.width / 2 ? scale + (translatePos(startPoint, size).x - translatePos(movePoint, size).x) / size.width : scale + (translatePos(movePoint, size).x - translatePos(startPoint, size).x) / size.width;
145 }
146 scaleFactor = between(1, maxScale, scaleFactor);
147 return {
148 scale: scaleFactor,
149 x: scaleFactor < 1.01 ? 0 : x,
150 y: scaleFactor < 1.01 ? 0 : y
151 };
152 } else {
153 var scaleFactorX = (size.width * scale - size.width) / 4;
154 var scaleFactorY = (size.height * scale - size.height) / 4;
155 return {
156 x: between(inverse(scaleFactorX), scaleFactorX, movePoint.x - startPoint.x),
157 y: between(inverse(scaleFactorY), scaleFactorY, movePoint.y - startPoint.y)
158 };
159 }
160 }).takeUntil(touchEnd);
161 });
162 //.tap(logger)
163
164 this.pinchSubscription = pinch.subscribe(function (newObject) {
165 requestAnimationFrame(function () {
166 _this3.setState({
167 obj: Object.assign({}, _this3.state.obj, newObject)
168 });
169 });
170 });
171 }
172 }, {
173 key: 'render',
174 value: function render() {
175 var _state$obj2 = this.state.obj;
176 var scale = _state$obj2.scale;
177 var x = _state$obj2.x;
178 var y = _state$obj2.y;
179
180 return _react2.default.createElement(
181 'div',
182 { ref: 'root' },
183 this.props.render({
184 x: x.toFixed(2),
185 y: y.toFixed(2),
186 scale: scale.toFixed(2)
187 })
188 );
189 }
190 }]);
191
192 return ReactPinchZoomPan;
193}(_react.Component);
194
195ReactPinchZoomPan.defaultProps = {
196 maxScale: 2
197};
198
199ReactPinchZoomPan.propTypes = {
200 render: _react.PropTypes.func,
201 maxScale: _react.PropTypes.number
202};
203
204exports.default = ReactPinchZoomPan;
\No newline at end of file