diff --git a/example/app/bar-chart.tsx b/example/app/bar-chart.tsx index be9dbde2..1dea4de8 100644 --- a/example/app/bar-chart.tsx +++ b/example/app/bar-chart.tsx @@ -7,8 +7,20 @@ import { } from "@shopify/react-native-skia"; import React, { useState } from "react"; import { SafeAreaView, ScrollView, StyleSheet, View } from "react-native"; -import { Bar, CartesianChart } from "victory-native"; +import { + Bar, + CartesianChart, + getTransformComponents, + setScale, + setTranslate, + useChartTransformState, +} from "victory-native"; import { useDarkMode } from "react-native-dark"; +import { + useAnimatedReaction, + useSharedValue, + withTiming, +} from "react-native-reanimated"; import inter from "../assets/inter-medium.ttf"; import { appColors } from "./consts/colors"; import { InputSwitch } from "../components/InputSwitch"; @@ -37,12 +49,46 @@ export default function BarChartPage(props: { segment: string }) { const [labelPosition, setLabelPosition] = useState< "top" | "bottom" | "left" | "right" >("top"); + const { state } = useChartTransformState(); + + const k = useSharedValue(1); + const tx = useSharedValue(0); + const ty = useSharedValue(0); + + useAnimatedReaction( + () => { + return state.panActive.value || state.zoomActive.value; + }, + (cv, pv) => { + if (!cv && pv) { + const vals = getTransformComponents(state.matrix.value); + k.value = vals.scaleX; + tx.value = vals.translateX; + ty.value = vals.translateY; + + k.value = withTiming(1); + tx.value = withTiming(0); + ty.value = withTiming(0); + } + }, + ); + + useAnimatedReaction( + () => { + return { k: k.value, tx: tx.value, ty: ty.value }; + }, + ({ k, tx, ty }) => { + const m = setTranslate(state.matrix.value, tx, ty); + state.matrix.value = setScale(m, k); + }, + ); return ( <> Math.floor(Math.random() * (50 - 25 + 1)) + 25; const randomNumber2 = () => Math.floor(Math.random() * (50 - 25 + 1)) + 10000; @@ -40,6 +55,7 @@ export default function MultipleYAxesPage() { const [priceYDomain, setPriceYDomain] = useState<[number, number]>([ 100, 200, ]); + const { state } = useChartTransformState(); const red = "#a04d4d"; const blue = "#1e1e59"; @@ -47,15 +63,54 @@ export default function MultipleYAxesPage() { const green = "#74b567"; const gray = "#232323"; + const k = useSharedValue(1); + const tx = useSharedValue(0); + const ty = useSharedValue(0); + + useAnimatedReaction( + () => { + return state.panActive.value || state.zoomActive.value; + }, + (cv, pv) => { + if (!cv && pv) { + const vals = getTransformComponents(state.matrix.value); + k.value = vals.scaleX; + tx.value = vals.translateX; + ty.value = vals.translateY; + + k.value = withTiming(1); + tx.value = withTiming(0); + ty.value = withTiming(0); + } + }, + ); + + useAnimatedReaction( + () => { + return { k: k.value, tx: tx.value, ty: ty.value }; + }, + ({ k, tx, ty }) => { + const m = setTranslate(state.matrix.value, tx, ty); + state.matrix.value = setScale(m, k); + }, + ); + return ( { @@ -76,6 +131,7 @@ export default function MultipleYAxesPage() { return value.toFixed(0); }, lineColor: "pink", + enableRescaling: true, }, { yKeys: ["profit"], @@ -107,6 +163,9 @@ export default function MultipleYAxesPage() { )} + + This chart supports pan/zoom + {/* Multi bar, with negative values */} diff --git a/example/app/pan-zoom.tsx b/example/app/pan-zoom.tsx new file mode 100644 index 00000000..b00825c9 --- /dev/null +++ b/example/app/pan-zoom.tsx @@ -0,0 +1,191 @@ +import { + useAnimatedReaction, + useSharedValue, + withTiming, +} from "react-native-reanimated"; + +export const PanZoom = () => {}; +import * as React from "react"; +import { StyleSheet, View, SafeAreaView, ScrollView } from "react-native"; +import { + CartesianChart, + getTransformComponents, + Line, + setScale, + setTranslate, + useChartTransformState, +} from "victory-native"; +import { + multiply4, + scale, + translate, + useFont, +} from "@shopify/react-native-skia"; +import { useState } from "react"; +import { appColors } from "./consts/colors"; +import inter from "../assets/inter-medium.ttf"; + +import { Button } from "../components/Button"; + +export default function PanZoomPage() { + const font = useFont(inter, 12); + const [width, setWidth] = useState(0); + const [height, setHeight] = useState(0); + const { state } = useChartTransformState(); + + const k = useSharedValue(1); + const tx = useSharedValue(0); + const ty = useSharedValue(0); + + useAnimatedReaction( + () => { + return state.panActive.value || state.zoomActive.value; + }, + (cv, pv) => { + if (!cv && pv) { + const vals = getTransformComponents(state.matrix.value); + k.value = vals.scaleX; + tx.value = vals.translateX; + ty.value = vals.translateY; + + k.value = withTiming(1); + tx.value = withTiming(0); + ty.value = withTiming(0); + } + }, + ); + + useAnimatedReaction( + () => { + return { k: k.value, tx: tx.value, ty: ty.value }; + }, + ({ k, tx, ty }) => { + const m = setTranslate(state.matrix.value, tx, ty); + state.matrix.value = setScale(m, k); + }, + ); + + return ( + + + { + setWidth(right - left); + setHeight(bottom - top); + }} + > + {({ points }) => { + return ( + <> + + + ); + }} + + + + + +