React Native HTML - 渲染线性背景渐变
React Native HTML - rendering a linear background gradient
我目前HTML溢出高度:300一箱,这里用的是React NativeHTML。 (这个包:https://www.npmjs.com/package/react-native-render-html)
这会在 'overflown' 时提供以下输出 - 在 'Read more' Link.
之前稍微锐利地截断文本
我试图用这个库实现的是在框的最后一个元素上从透明渐变到白色的线性渐变。绝对定位的底部 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;
我想你需要的是 component custom renderer.
您可以为一个 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;
我目前HTML溢出高度:300一箱,这里用的是React NativeHTML。 (这个包:https://www.npmjs.com/package/react-native-render-html)
这会在 'overflown' 时提供以下输出 - 在 'Read more' Link.
之前稍微锐利地截断文本我试图用这个库实现的是在框的最后一个元素上从透明渐变到白色的线性渐变。绝对定位的底部 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;
我想你需要的是 component custom renderer.
您可以为一个 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;