`` `import React, {Component} de 'react';
import {Modal, StyleSheet, View, Dimensions} from 'react-native';
import {
PanGestureHandler,
Estado,
PinchGestureHandler,
} de 'reagir-nativo-gestor-manipulador';
import Animated, {Easing} de 'react-native-reanimated';
importar PropTypes de 'prop-types'
// setInterval (() => {
// deixe iters = 1e8,
// soma = 0;
// while (iters--> 0) sum + = iters;
//}, 300);
const {
definir,
cond,
eq,
ou,
adicionar,
sub,
Pancada,
min,
max,
depurar,
multiplicar,
dividir,
Menor que,
Primavera,
definiram,
decair,
cronometragem,
ligar,
diff,
acc,
não,
abdômen,
bloquear,
startClock,
stopClock,
clockRunning,
Valor,
Relógio,
evento,
} = Animado;
function scaleDiff (value) {
const tmp = novo valor (1);
prev prev = novo valor (1);
return [set (tmp, divide (value, prev)), set (prev, value), tmp];
}
function dragDiff (valor, atualização) {
const tmp = novo valor (0);
prev prev = novo valor (0);
return cond (
atualizando,
[definir (tmp, sub (valor, prev)), definir (prev, valor), tmp],
conjunto (anterior, 0)
);
}
// retorna o coeficiente de atrito linear. Quando value
é 0 coeficiente é 1 (sem atrito), então
// cresce linearmente até atingir MAX_FRICTION
quando value
é igual
// para MAX_VALUE
fricção de função (valor) {
const MAX_FRICTION = 5;
const MAX_VALUE = 100;
return max (
1,
min (MAX_FRICTION, some (1, multiplique (valor, (MAX_FRICTION - 1) / MAX_VALUE)))
);
}
velocidade da função (valor) {
const clock = new Clock ();
const dt = diff (relógio);
retornar cond (menosThan (dt, 1), 0, multiplicar (1000, dividir (diff (valor), dt)));
}
const MIN_SCALE = 1;
const MAX_SCALE = 2;
function scaleRest (value) {
return cond (
lessThan (valor, MIN_SCALE),
MIN_SCALE,
cond (menos que (MAX_SCALE, valor), MAX_SCALE, valor)
);
}
function scaleFriction (value, rest, delta) {
const MAX_FRICTION = 20;
const MAX_VALUE = 0,5;
const res = multiplicação (valor, delta);
const howFar = abs (sub (repouso, valor));
fricção const = max (
1,
min (MAX_FRICTION, some (1, multiplique (howFar, (MAX_FRICTION - 1) / MAX_VALUE)))
);
return cond (
lessThan (0, howFar),
multiplicar (valor, adicionar (1, dividir (adicionar (delta, -1), fricção))),
res
);
}
function runTiming (clock, value, dest, startStopClock = true) {
estado const = {
acabado: novo valor (0),
posição: novo valor (0),
frameTime: novo valor (0),
tempo: novo valor (0),
};
const config = {
toValue: novo valor (0),
duração: 300,
easing: Easing.inOut (Easing.cubic),
};
Retorna [
cond (clockRunning (clock), 0, [
definido (estado finalizado, 0),
definir (state.frameTime, 0),
set (state.time, 0),
set (state.position, value),
set (config.toValue, dest),
startStopClock && startClock (clock),
]),
tempo (relógio, estado, configuração),
cond (state.finished, startStopClock && stopClock (clock)),
state.position,
];
}
function runDecay (clock, value, velocity) {
estado const = {
acabado: novo valor (0),
velocidade: novo valor (0),
posição: novo valor (0),
tempo: novo valor (0),
};
configuração const = {desaceleração: 0,99};
Retorna [
cond (clockRunning (clock), 0, [
definido (estado finalizado, 0),
set (state.velocity, velocity),
set (state.position, value),
set (state.time, 0),
startClock (clock),
]),
set (state.position, value),
decadência (relógio, estado, configuração),
cond (state.finished, stopClock (clock)),
state.position,
];
}
function bouncyPinch (
valor,
gesto,
gesto Ativo,
focalX,
displacementX,
focalY,
deslocamento Y
) {
const clock = new Clock ();
const delta = scaleDiff (gesto);
const rest = scaleRest (valor);
const focalXRest = cond (
lessThan (valor, 1),
0,
sub (displacementX, multiplique (focalX, add (-1, divide (rest, value))))
);
const focalYRest = cond (
lessThan (valor, 1),
0,
sub (deslocamentoY, multiplicar (focalY, adicionar (-1, dividir (repouso, valor))))
);
const nextScale = new Value (1);
return cond (
[delta, gesto ativo],
[
stopClock (relógio),
set (nextScale, scaleFriction (value, rest, delta)),
definir(
displacementX,
sub (displacementX, multiplique (focalX, add (-1, divide (nextScale, value))))
),
definir(
deslocamento Y,
sub (displacementY, multiplique (focalY, add (-1, divide (nextScale, value))))
),
nextScale,
],
cond (
ou (clockRunning (clock), não (eq (resto, valor))),
[
set (displacementX, runTiming (clock, displacementX, focalXRest, false)),
set (displacementY, runTiming (clock, displacementY, focalYRest, false)),
runTiming (clock, value, rest),
],
valor
)
);
}
function bouncy (
valor,
gestoDiv,
gesto Ativo,
lowerBound,
limite superior,
atrito
) {
const timingClock = new Clock ();
const decayClock = new Clock ();
velocidade const = velocidade (valor);
// o valor ultrapassou os limites (inferior, superior)
const isOutOfBounds = ou (
lessThan (value, lowerBound),
lessThan (upperBound, value)
);
// posição para ajustar (superior ou inferior está além ou o valor atual em outro lugar)
const rest = cond (
lessThan (value, lowerBound),
lowerBound,
cond (lessThan (upperBound, value), upperBound, value)
);
// quanto o valor excede os limites, isso é usado para calcular o atrito
const outOfBounds = abs (sub (repouso, valor));
return cond (
[GestO Div, velocidade, gesto Ativo],
[
stopClock (timingClock),
stopClock (decayClock),
add (value, divide (gestureDiv, friction (outOfBounds))),
],
cond (
ou (clockRunning (timingClock), isOutOfBounds),
[stopClock (decayClock), runTiming (timingClock, value, rest)],
cond (
ou (clockRunning (decayClock), lessThan (5, abs (velocidade))),
runDecay (decayClock, valor, velocidade),
valor
)
)
);
}
const WIDTH = 300;
const HEIGHT = 300;
classe Viewer extends Component {
pinchRef = React.createRef ();
panRef = React.createRef ();
construtor (adereços) {
super (adereços);
// DECLARE TRANSX
const panTransX = new Value(0);
const panTransY = new Value(0);
// PINCH
const pinchScale = new Value(1);
const pinchFocalX = new Value(0);
const pinchFocalY = new Value(0);
const pinchState = new Value(-1);
this._onPinchEvent = event([
{
nativeEvent: {
state: pinchState,
scale: pinchScale,
focalX: pinchFocalX,
focalY: pinchFocalY,
},
},
]);
// SCALE
const scale = new Value(1);
const pinchActive = eq(pinchState, State.ACTIVE);
this._focalDisplacementX = new Value(0);
const relativeFocalX = sub(
pinchFocalX,
add(panTransX, this._focalDisplacementX)
);
this._focalDisplacementY = new Value(0);
const relativeFocalY = sub(
pinchFocalY,
add(panTransY, this._focalDisplacementY)
);
this._scale = set(
scale,
bouncyPinch(
scale,
pinchScale,
pinchActive,
relativeFocalX,
this._focalDisplacementX,
relativeFocalY,
this._focalDisplacementY
)
);
// PAN
const dragX = new Value(0);
const dragY = new Value(0);
const panState = new Value(-1);
this._onPanEvent = event([
{
nativeEvent: {
translationX: dragX,
translationY: dragY,
state: panState,
},
},
]);
const panActive = eq(panState, State.ACTIVE);
const panFriction = value => friction(value);
// X
const panUpX = cond(
lessThan(this._scale, 1),
0,
multiply(-1, this._focalDisplacementX)
);
const panLowX = add(panUpX, multiply(-WIDTH, add(max(1, this._scale), -1)));
this._panTransX = set(
panTransX,
bouncy(
panTransX,
dragDiff(dragX, panActive),
or(panActive, pinchActive),
panLowX,
panUpX,
panFriction
)
);
// Y
const panUpY = cond(
lessThan(this._scale, 1),
0,
multiply(-1, this._focalDisplacementY)
);
const panLowY = add(
panUpY,
multiply(-HEIGHT, add(max(1, this._scale), -1))
);
this._panTransY = set(
panTransY,
bouncy(
panTransY,
dragDiff(dragY, panActive),
or(panActive, pinchActive),
panLowY,
panUpY,
panFriction
)
);
}
render () {
// Os dois valores animados abaixo fazem com que a escala pareça estar concluída
// a partir do canto superior esquerdo da visualização da imagem em vez de seu centro. Esse
// é necessário para que a matemática do "ponto focal da escala" funcione corretamente
const scaleTopLeftFixX = divide (multiply (WIDTH, add (this._scale, -1)), 2);
const scaleTopLeftFixY = divide (multiply (HEIGHT, add (this._scale, -1)), 2);
Retorna (
simultaneousHandlers = {this.panRef}
onGestureEvent = {this._onPinchEvent}
onHandlerStateChange = {this._onPinchEvent}>
avgTouches
simultaneousHandlers = {this.pinchRef}
onGestureEvent = {this._onPanEvent}
onHandlerStateChange = {this._onPanEvent}>
styles.image,
{
transformar: [
{translateX: this._panTransX},
{traduzirY: this._panTransY},
{translateX: this._focalDisplacementX},
{translateY: this._focalDisplacementY},
{translateX: scaleTopLeftFixX},
{translateY: scaleTopLeftFixY},
{escala: this._scale},
],
},
]}
resizeMode = "esticar"
source = {this.props.source}
/>
);
}
}
exportar a classe padrão ImageView extends Component {
render () {
Retorna (
);
}
}
ImageView.propTypes = {
im ageSource: PropTypes.any
};
estilos const = StyleSheet.create ({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '# F5FCFF',
},
embrulho: {
estouro: 'escondido',
},
imagem: {
largura: Dimensions.get ('janela'). largura,
altura: Dimensions.get ('janela'). altura,
backgroundColor: 'black',
},
}); `` `
Duplicado de # 139
use View em vez de Modal!
@yasahmed , em algum lugar como o meu projeto você deve usar o Modal porque algumas áreas absolutas estão na tela e o Pan deve aparecer no topo delas.
No meu caso devo usar o Modal, mas ainda não encontrei uma solução.