You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

145 lines
3.8 KiB

/**
* 图片处理工具函数
* 支持外部 URL(HTTP/HTTPS 和 Data URI)和本地路径(/images/...)
*
* 本地路径格式:/images/game/{typeName}/{color|dark|light}_{play_id}.png
* 例如:/images/game/chess/color_101.png
*
* 注意:React Native 中不支持本地文件路径的动态 require()
* 本地路径会被 Expo 的静态资源服务器处理
*/
/**
* 判断是否为有效的外部 URL
* @param source 图片源
* @returns 是否为有效的外部 URL
*/
export const isExternalUrl = (source: string | undefined): boolean => {
if (!source) return false;
return /^https?:\/\//.test(source) || /^data:image\//.test(source);
};
/**
* 判断是否为本地路径
* @param source 图片源
* @returns 是否为本地路径
*/
export const isLocalPath = (source: string | undefined): boolean => {
if (!source) return false;
return /^\/images\//.test(source);
};
/**
* 获取图片 URI
*
* 验证并返回有效的图片 URI
* 支持外部 URL(HTTP/HTTPS 和 Data URI)和本地路径(/images/...)
*
* @param source 图片源(URL 或本地路径)
* @returns 有效的图片 URI,如果无效返回 undefined
*
* @example
* ```typescript
* // 外部 URL
* const uri = getImageSource('https://example.com/image.png');
* // 返回: 'https://example.com/image.png'
*
* // Data URI
* const uri = getImageSource('data:image/png;base64,iVBORw0KGgo...');
* // 返回: 'data:image/png;base64,iVBORw0KGgo...'
*
* // 本地路径
* const uri = getImageSource('/images/game/chess/color_101.png');
* // 返回: '/images/game/chess/color_101.png'
*
* // 无效的 URL
* const uri = getImageSource('invalid-url');
* // 返回: undefined
* ```
*/
export const getImageSource = (source: string | undefined): string | undefined => {
if (!source) return undefined;
// 支持外部 URL
if (isExternalUrl(source)) {
return source;
}
// 支持本地路径
if (isLocalPath(source)) {
return source;
}
// 其他格式不支持
return undefined;
};
/**
* 将本地路径转换为可用的 require 对象
*
* 在 React Native 中,本地资源必须使用 require() 加载
* 这个函数使用预定义的图片映射表来获取资源
*
* @param localPath 本地路径,例如 /images/game/chess/color_101.png
* @returns require 对象,如果路径无效返回 undefined
*
* @example
* ```typescript
* const source = convertLocalPathToUri('/images/game/chess/color_101.png');
* // 返回: require('../assets/images/game/chess/color_101.png')
* ```
*/
export const convertLocalPathToUri = (localPath: string): any => {
if (!localPath || !isLocalPath(localPath)) {
return undefined;
}
try {
// 使用图片映射表获取本地资源
const { getGameImageFromPath } = require('@/constants/gameImages');
return getGameImageFromPath(localPath);
} catch (error) {
// 如果获取失败,返回 undefined
if (__DEV__) {
console.warn(`Failed to load image: ${localPath}`, error);
}
return undefined;
}
};
/**
* 获取图片源(带默认值)
*
* 如果主图片 URL 无效,返回默认图片 URL
*
* @param source 图片源(URL)
* @param defaultSource 默认图片源(URL)
* @returns 有效的图片 URI
*
* @example
* ```typescript
* // 如果主图片无效,使用默认图片
* const uri = getImageSourceWithDefault(
* item.imageUrl,
* 'https://via.placeholder.com/200'
* );
* ```
*/
export const getImageSourceWithDefault = (
source: string | undefined,
defaultSource: string
): string | undefined => {
const imageSource = getImageSource(source);
if (imageSource) {
return imageSource;
}
return getImageSource(defaultSource);
};
export default {
getImageSource,
getImageSourceWithDefault,
isExternalUrl,
isLocalPath,
convertLocalPathToUri,
};