Skip to content

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

@liangjiazhang

Description

@liangjiazhang

环境

Xcode 16.2
[email protected]

问题描述如下:

  • 在同一个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

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions