0

我目前 HTML 溢出高度:300 一盒,其中使用了 React Native HTML。(这个包:https ://www.npmjs.com/package/react-native-render-html )

这会在“溢出”时提供以下输出 - 在“阅读更多”链接之前略微锐利地截断文本。

在此处输入图像描述

我试图用这个库实现的是在盒子的最后一个元素上从透明到白色的线性渐变。一个绝对定位,底部 0:渐变,给人一种有更多可看性的错觉,并且没有那么刺耳的截断。

在我下面的代码中:<scrollfade> test </scrollfade>是我试图通过它实现的元素。

你会注意到它的自定义渲染器是在这里定义的:

scrollfade: HTMLElementModel.fromCustomModel({
      tagName: 'scrollfade',
      mixedUAStyles: {
        position: 'absolute',
        width: '100%',
        height: '220px',
        left: 0,
        bottom: 0,
        display: 'flex',
      },
      contentModel: HTMLContentModel.block,
    }),

然而,这似乎并不能促进 backgroundImages、背景渐变等能够定义可能实现这一目标的样式。我尝试使用 from 'react-native-linear-gradient' - 就在 html 渲染器下方,但它不在 dom 中的正确位置内产生任何影响。即文本粗暴地切断,然后渐变显示。我不确定是否可以混合这两种技术并在 html 模板中以某种方式使用本机组件,我怀疑不是。关于如何编写自定义渲染器的想法?对于渐变并在模板中定义它,或者欢迎其他更简单的方法。

为了澄清,我正在寻找一种视觉渐变解决方案,该解决方案允许文本预溢出略微闪耀。

import React, { FunctionComponent } from 'react';
import { StyleSheet, Text, useWindowDimensions, ViewStyle } from 'react-native';
import LinearGradient from 'react-native-linear-gradient';
import RenderHtml, {
  defaultSystemFonts,
  HTMLContentModel,
  HTMLElementModel,
  MixedStyleRecord,
} from 'react-native-render-html';
import { Theme, useTheme } from '../styles/native';

interface Props {
  html: string;
  padding: boolean;
  scrollEnabled: boolean;
  style?: ViewStyle;
  pointerEvents?: 'none' | 'auto' | 'box-none' | 'box-only';
}

// Later on in your styles..
const styles = StyleSheet.create({
  linearGradient: {
    flex: 1,
    height: 100,
  },
});

const tagsStyles: MixedStyleRecord = (theme: Theme) => {
  return {
    body: {
      color: theme.textMid,
      fontFamily: 'OpenSans-Regular',
      background: theme.background,
      overflow: 'hidden',
    },
    a: {
      color: theme.primary,
    },
    h1: {
      color: theme.textDark,
    },
    h2: {
      color: theme.textDark,
    },
    h3: {
      color: theme.textDark,
    },
    h4: {
      color: theme.textDark,
    },
    h5: {
      color: theme.textDark,
    },
    h6: {
      color: theme.textDark,
    },
  };
};

const customHTMLElementModels = (style: any, scrollEnabled: boolean, theme: Theme, padding: boolean) => {
  return {
    template: HTMLElementModel.fromCustomModel({
      tagName: 'template',
      mixedUAStyles: {
        ...style,
        position: 'relative',
        padding: padding ? '0 20px 40px 20px' : '0',
        overflow: scrollEnabled ? 'scroll' : 'hidden',
      },
      contentModel: HTMLContentModel.block,
    }),
    scrollfade: HTMLElementModel.fromCustomModel({
      tagName: 'scrollfade',
      mixedUAStyles: {
        position: 'absolute',
        width: '100%',
        height: '220px',
        left: 0,
        bottom: 0,
        display: 'flex',
      },
      contentModel: HTMLContentModel.block,
    }),
  };
};

const wrapHTMLInBody = (html: string) => {
  return `
      <body>
          <template>
            ${html}
            <scrollfade>test</scrollfade>
          </template>
          
      </body>
  `;
};

const Description: FunctionComponent<Props> = (props) => {
  const { width } = useWindowDimensions();
  const theme = useTheme();
  const systemFonts = [...defaultSystemFonts, 'OpenSans-Regular'];
  const endColor = getTheme() === 'dark' ? 'rgba(0,0,0,0)' : 'rgba(255,255,255,0)';

  return (
    <>
      <RenderHtml
        contentWidth={width}
        source={{
          html: wrapHTMLInBody(
            '<p>Miss polly had a dolly that was sick sick sick</p>Miss polly had a dolly that was sick sick sick</p>Miss polly had a dolly that was sick sick sick</p>Miss polly had a dolly that was sick sick sick</p>Miss polly had a dolly that was sick sick sick</p>Miss polly had a dolly that was sick sick sick</p>Miss polly had a dolly that was sick sick sick</p>Miss polly had a dolly that was sick sick sick</p><p>Miss polly had a dolly that was sick sick sick</p><p>Miss polly had a dolly that was sick sick sick</p><p>Miss polly had a dolly that was sick sick sick</p><p>Miss polly had a dolly that was sick sick sick</p><p>Miss polly had a dolly that was sick sick sick</p>',
          ),
        }}
        tagsStyles={tagsStyles(theme)}
        customHTMLElementModels={customHTMLElementModels(props.style, props.scrollEnabled, theme, props.padding)}
        systemFonts={systemFonts}
      />
    </>
  );
};

export default Description;
4

1 回答 1

1

我认为您需要的是一个组件自定义渲染器

您可以为一个 html 标签定义自定义模型和自定义(组件)渲染器。沿着这个:

import React, {FunctionComponent} from 'react';
import {StyleSheet, Text, useWindowDimensions, ViewStyle} from 'react-native';
import LinearGradient from 'react-native-linear-gradient';
import RenderHtml, {
  CustomRendererProps,
  defaultSystemFonts,
  HTMLContentModel,
  HTMLElementModel,
  MixedStyleRecord,
  RenderHTMLProps,
  TChildrenRenderer,
  TBlock,
  TNodeChildrenRenderer,
} from 'react-native-render-html';
import {Theme, useTheme} from '../styles/native';

interface Props {
  html: string;
  padding: boolean;
  scrollEnabled: boolean;
  style?: ViewStyle;
  pointerEvents?: 'none' | 'auto' | 'box-none' | 'box-only';
}

// Later on in your styles..
const styles = StyleSheet.create({
  linearGradient: {
    flex: 1,
    height: 100,
  },
});

const customHTMLElementModels = (
  style: any,
  scrollEnabled: boolean,
  theme: Theme,
  padding: boolean,
) => {
  return {
    template: HTMLElementModel.fromCustomModel({
      tagName: 'template',
      mixedUAStyles: {
        ...style,
        position: 'relative',
        padding: padding ? '0 20px 40px 20px' : '0',
        overflow: scrollEnabled ? 'scroll' : 'hidden',
      },
      contentModel: HTMLContentModel.block,
    }),
    scrollfade: HTMLElementModel.fromCustomModel({
      tagName: 'scrollfade',
      mixedUAStyles: {
        position: 'absolute',
        width: '100%',
        height: '220px',
        left: 0,
        bottom: 0,
        display: 'flex',
      },
      contentModel: HTMLContentModel.block,
    }),
  };
};

const renderers: RenderHTMLProps['renderers'] = {
  scrollfade: ({TDefaultRenderer, ...props}: CustomRendererProps<TBlock>) => {
    return (
      <TDefaultRenderer {...props}>
        <TNodeChildrenRenderer tnode={props.tnode} />
        <LinearGradient style={styles.linearGradient} />
      </TDefaultRenderer>
    );
  },
};

const wrapHTMLInBody = (html: string) => {
  return `
      <body>
          <template>
            ${html}
            <scrollfade>test</scrollfade>
          </template>
          
      </body>
  `;
};

const Description: FunctionComponent<Props> = (props) => {
  const {width} = useWindowDimensions();
  const theme = useTheme();
  const systemFonts = [...defaultSystemFonts, 'OpenSans-Regular'];

  return (
    <>
      <RenderHtml
        contentWidth={width}
        source={{
          html: wrapHTMLInBody(
            '<p>Miss polly had a dolly that was sick sick sick</p>Miss polly had a dolly that was sick sick sick</p>Miss polly had a dolly that was sick sick sick</p>Miss polly had a dolly that was sick sick sick</p>Miss polly had a dolly that was sick sick sick</p>Miss polly had a dolly that was sick sick sick</p>Miss polly had a dolly that was sick sick sick</p>Miss polly had a dolly that was sick sick sick</p><p>Miss polly had a dolly that was sick sick sick</p><p>Miss polly had a dolly that was sick sick sick</p><p>Miss polly had a dolly that was sick sick sick</p><p>Miss polly had a dolly that was sick sick sick</p><p>Miss polly had a dolly that was sick sick sick</p>',
          ),
        }}
        renderers={renderers}
        customHTMLElementModels={customHTMLElementModels(
          props.style,
          props.scrollEnabled,
          theme,
          props.padding,
        )}
        systemFonts={systemFonts}
      />
    </>
  );
};

export default Description;
于 2021-09-15T22:18:52.843 回答