Skip to content

iOS 加载RN页面的交互错误 #976

@liangjiazhang

Description

@liangjiazhang

环境

Xcode 16.2
react-native@0.78.0

问题描述如下:

  • 在同一个iOS 的App中,
    1、加载 RN 页面 A 时出现错误,加载页面 B 正常
    2、相同的 RN 页面 A 从远端拉取时出现错误,放在本地运行正常。
    3、加载的A页面能显示出来,但随后弹出红屏错误,错误提示内容如下
    Error: Unsupported top level event type "topSvgLayout" dispatched, js engine: hermes

其中package.json 中svg的相关引入如下
"react-native-svg": "^15.11.2",
在项目下,终端执行cat node_modules/react-native-svg/package.json | grep version
执行后输出是"version": "15.13.0"

其中A页面的部分RN/svg相关代码如下:

import React, { useRef, useState, useEffect } from 'react';
import {
  View,
  Image,
  PanResponder,
  StyleSheet,
  Dimensions,
  ImageEditor,
} from 'react-native';
import Svg, { Circle } from 'react-native-svg';
import { scaleWidth, scaleHeight, scaleFont } from '../../utils/ScreenAdapter';
const WHEEL_SIZE = scaleWidth(280); 
const SAMLL_WHEEL = scaleWidth(190);
const RADIUS = WHEEL_SIZE / 2; 
const SAMLL_RADIUS = SAMLL_WHEEL / 2;
const SAMLL_CIRCLE = scaleWidth(16);
const SAMLL_CIRCLE_RADIUS = SAMLL_CIRCLE / 2;
const ColorWheelWith = (WHEEL_SIZE - SAMLL_WHEEL) / 2;
const ColorWheelWithRadius = ColorWheelWith / 2;

const ColorWheel = ({ imageSource,onColorChange, hue ,sliderSatVal , sliderLightVal }) => {
  console.log('ColorWheel....',hue);
  const [handlePos, setHandlePos] = useState({ x: RADIUS, y: SAMLL_CIRCLE });
  const [layout, setLayout] = useState(null);
  const [color, setCenterColor] = useState(180);
  const [satVal, setsatVal] = useState(sliderSatVal);
  const [lightVal, setlightVal] = useState(sliderLightVal);


  useEffect(() => {
    if (hue == null) return;
    const center = { x: RADIUS, y: RADIUS };
    const { x, y } = getHandlePositionFromHue(360-hue, SAMLL_RADIUS+ColorWheelWithRadius, center);
    console.log('xy....',x+"..."+y);
    setHandlePos({ x, y });
  }, [hue, layout]);
  useEffect(() => {
    setsatVal(sliderSatVal==0?1:sliderSatVal)
  }, [sliderSatVal]);

  useEffect(() => {
    setlightVal(sliderLightVal==0?0.1:sliderLightVal/100)
}, [sliderLightVal]);

  const imageRef = useRef();

  const panResponder = useRef(
    PanResponder.create({
      onStartShouldSetPanResponder: () => true,
      onPanResponderGrant: evt => {
        handleTouch(evt.nativeEvent);
      },
      onPanResponderMove: evt => {
        handleTouch(evt.nativeEvent);
      },
      onPanResponderRelease:evt => {
        handleTouch(evt.nativeEvent,true);
      },
    })
  ).current;

  const handleTouch = async (nativeEvent,flag=false) => {
    const { locationX, locationY } = nativeEvent;
    const dx = locationX - RADIUS;
    const dy = locationY - RADIUS;
    const distance = Math.sqrt(dx * dx + dy * dy);
        const angle = (Math.atan2(dy, dx) * 180) / Math.PI;
        let hue = (angle + 360) % 360;
        const center = { x: RADIUS, y: RADIUS };
        const { x, y } = getHandlePositionFromHue(hue, SAMLL_RADIUS + ColorWheelWithRadius, center);
        setHandlePos({ x, y });
        onColorChange?.(hue,flag);
  };

  const getHandlePositionFromHue = (hue, radius, center)=>{    
    setCenterColor(360-hue)
    const rad = hue * (Math.PI / 180);
    const x = center.x + radius * Math.cos(rad);
    const y = center.y + radius * Math.sin(rad);
    return { x, y };
  }

  return (
    <View style={styles.container}  {...panResponder.panHandlers}   >
        <Image
        ref={imageRef}
        source={imageSource}
        style={styles.wheelImage}
        onLayout={(e) => {
            const { width, height } = e.nativeEvent.layout;
            setLayout({ width, height });
        }}
        resizeMode="contain"
        />
        <Svg style={StyleSheet.absoluteFill}>
        <Circle
            cx={handlePos.x}
            cy={handlePos.y}
            r={SAMLL_CIRCLE}
            fill="none" //#fff
            stroke="#fff"
            strokeWidth={4}
        />
        </Svg>
        <View style={[styles.colorSmallRound,{backgroundColor:`hsla(${color}, ${satVal}%, 50%,${lightVal})`}]}>
            <Image resizeMode='contain' style={styles.colorSmallRoundImg} source={require('../../assets/light/images/lightIcon.png')} />
        </View>
    </View>
  );
};

function hsvToRgb(h, s, v) {
  let f = (n, k = (n + h / 60) % 6) =>
    v - v * s * Math.max(Math.min(k, 4 - k, 1), 0);
  return {
    r: Math.round(f(5) * 255),
    g: Math.round(f(3) * 255),
    b: Math.round(f(1) * 255),
  };
}

function rgbToHsv(r, g, b) {
  r /= 255; g /= 255; b /= 255;
  const max = Math.max(r, g, b), min = Math.min(r, g, b);
  const d = max - min;
  let h = 0, s = max === 0 ? 0 : d / max, v = max;
  if (d !== 0) {
    switch (max) {
      case r: h = (g - b) / d + (g < b ? 6 : 0); break;
      case g: h = (b - r) / d + 2; break;
      case b: h = (r - g) / d + 4; break;
    }
    h *= 60;
  }
  return { h, s, v };
}

function rgbToHex(r, g, b) {
  return "#" + [r, g, b].map(x => x.toString(16).padStart(2, '0')).join('');
}

function hexToRgb(hex) {
  const bigint = parseInt(hex.replace('#', ''), 16);
  return {
    r: (bigint >> 16) & 255,
    g: (bigint >> 8) & 255,
    b: bigint & 255,
  };
}

const styles = StyleSheet.create({
  container: {
    width: WHEEL_SIZE,
    height: WHEEL_SIZE,
    alignItems: 'center',
    justifyContent: 'center',
    position: 'relative',
  },
  wheelImage: {
    width: WHEEL_SIZE,
    height: WHEEL_SIZE,
    borderRadius: WHEEL_SIZE / 2,
  },
  colorSmallRound:{
    width: 100,
    height: 100,
    borderRadius: 50,
    position: 'absolute',
    justifyContent: 'center',
    alignItems: 'center',
  },
  colorSmallRoundImg:{
    width: 40,
  },

});

export default ColorWheel;


  • 根据以上描述,作为iOS OC端,该怎么解决这个问题(Error: Unsupported top level event type "topSvgLayout" dispatched, js engine: hermes),还请详细解答,非常感谢

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions