Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Transformations: X and Y transformation at the same time seems to be impossible? #413

Closed
ChristianSauer opened this issue Apr 19, 2022 · 1 comment
Labels
question Further information is requested

Comments

@ChristianSauer
Copy link

I tried to reduce this as much as possible.

For context: I have map like data from a sweeping robot whose coordinate system goes from -1k to +1k in both axes. I am attempting to translate that into coordinates which I can fit and center on the mobile screen.
I am translating both axes here, but only the second transformation seems to stick, the first axis is always ignored. To see the problem, switch translateY and translateX lines in the code and watch what happens to the rect.

Code:

import { Canvas, Group, Rect } from '@shopify/react-native-skia';
import React from 'react';
import { COLORS } from '../../Constants';
import { StyleSheet, View } from 'react-native';

function convertRange(value: number, r1: number[], r2: number[]) {
  return ((value - r1[0]) * (r2[1] - r2[0])) / (r1[1] - r1[0]) + r2[0];
}

export function Map() {
  const map = {
    minX: 0,
    maxX: 10,
    minY: 10,
    maxY: 20,
  };
  const targetRange = [10, 256];

  const sourceRangeX = [map.minX, map.maxX];
  const sourceRangeY = [map.minY, map.maxY];

  const left = Math.min(map.minX, map.maxX);
  const top = Math.min(map.minY, map.maxY);

  const x = convertRange(left, sourceRangeX, targetRange);
  const width = convertRange(
    Math.max(map.minX, map.maxX),
    sourceRangeX,
    targetRange
  );

  const y = convertRange(top, sourceRangeY, targetRange);
  const height = convertRange(
    Math.max(map.minY, map.maxY),
    sourceRangeY,
    targetRange
  );

  const scale = Math.min(256 / width, 256 / height);
  return (
    <>
      <View style={styles.mapContainer}>
        <Canvas style={{ width: 256, height: 256 }}>
          <Group
            transform={[
              {
                translateY: -y * scale,
                translateX: -x * scale,
                scaleX: scale,
                scaleY: scale,
              },
            ]}>
            <Rect
              x={x}
              y={y}
              width={width}
              height={height}
              color={'green'}></Rect>
          </Group>
        </Canvas>
      </View>
    </>
  );
}

with translateY first:
image

with translateX first:
image

I would expect that both dimensions are transformed, e.g. the border padding is visible at the top AND at the left side.

@chrfalch chrfalch added the question Further information is requested label Apr 19, 2022
@chrfalch
Copy link
Contributor

chrfalch commented Apr 19, 2022

Transforms uses the same syntax as in React Native, so the way you write it is wrong:

transform={[
  {
    translateY: -y * scale,
    translateX: -x * scale,
    scaleX: scale,
    scaleY: scale,
  },
]}>

Should be:

transform={[
  {  translateY: -y * scale },
  {  translateX: -x * scale },
  {  scaleX: scale },
  {  scaleY: scale },  
]}>

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
question Further information is requested
Projects
None yet
Development

No branches or pull requests

2 participants