项目属于二开,使用的是Fabric.js来写的。
需求:根据点击的产品类型去替换画布canvas显示的图片
产品类型有多种,若一个一个通过if去判断的话,代码过于复杂繁琐,因此就想使用动态导入图片来进行图片渲染。因为每个类型都有固定的id,便已id来命名图片,通过点击选择的类型来显示图片。
项目中使用的是以TypeScript 项目中以类型安全的方式处理图片文件(如 .png 文件)。
//declare module: 使用 declare module 关键字来定义一个模块的类型。这里的 * 表示匹配所有 .png 文件。
//const src: string: 定义了一个常量 src,它的类型为 string。这意味着导入的 .png 文件将被当作一个字符串路径。
//export default src: 将 src 作为默认导出。这意味着你可以直接从 .png 文件中导入默认值。
declare module '*.png' {
const src: string
export default src
}
在使用图片的时候可以像导入模块一样导入 .png 文件,如下所示:
import logo from '@/assets/logo.png';
console.log(logo); // 输出: src/assets/logo.png
为何使用的是@,而打印出来的是src,是因为在vite.config.ts文件中进行了转换
resolve: {
alias: [
{ find: /^@\//, replacement: resolve(__dirname, 'src') + '/' },
],
},
最初的写法如下:
async function loadImageAsync() {
const imageSplice = silkBanner.productStyle + '-' + silkBanner.productColor;
const imagePath = `/src/assets/${imageSplice}.png`;
const image = await import(imagePath);
return image.default;
}
async function handleSilkBanner() {
const imageSrc = await loadImageAsync();
// 通过点击属性替换图片
const imgFn = canvasEditor.canvas.getObjects();
const images = imgFn.filter((item) => item.type === 'image');
if (images.length > 0) {
//因为canvas返回的对象中有两层图片,而id是动态的不好进行判断,因此为区分俩层图片,便加上一个属性来区分
images[0].name = 'theBottom';
images[1].name = 'backgroundMap';
const imageStyle = imgFn.find((item) => {
if (item.isType('image') && item.name === 'backgroundMap') {
return item;
}
});
const imageBottomColor = imgFn.find((item) => {
if (item.isType('image') && item.name === 'theBottom') {
return item;
}
});
if (imageStyle) {
imageStyle.setSrc(
imageSrc,
() => {
// 重新渲染画布
canvasEditor.canvas.renderAll();
},
{
crossOrigin: 'anonymous', // 如果图片可能存在跨域问题,需要设置此选项
}
);
}
if (imageBottomColor) {
if (silkBanner.productColor === '选择id') {
// 替换底部图片
imageBottomColor.setSrc(coverRedImage, () => {
canvasEditor.canvas.renderAll();
});
} else if (silkBanner.productColor === '选择id') {
// 替换底部图片
imageBottomColor.setSrc(coverAnImage, () => {
canvasEditor.canvas.renderAll();
});
} else if (silkBanner.productColor === '选择id') {
// 替换底部图片
imageBottomColor.setSrc(blackImage, () => {
canvasEditor.canvas.renderAll();
});
}
}
}
}
在本地运行的时候一切正常,但是打包后布到服务器,去查看的时候,发现找不到图片信息,一直报图片404
经过查询发现是动态传入图片的时候,因为没有进行import引入,打包的时候没有对这些图片进行打包,因此查看了vite官网的静态资源处理的写法,将代码进行了调整。
封装了一个ts文件,用来获取静态文件的使用
// 获取assets静态资源
export const getAssetsFile = (url: string) => {
return new URL(`/src/assets/${url}.png`, import.meta.url).href;
};
export default {
getAssetsFile,
};
引入:
import { getAssetsFile } from '@/utils/pubUse';
async function handleSilkBanner() {
const imageSplice = silkBanner.productStyle + '-' + silkBanner.productColor;
const imageSrc = getAssetsFile(imageSplice);
// await loadImageAsync();
// 通过点击属性替换图片
const imgFn = canvasEditor.canvas.getObjects();
const images = imgFn.filter((item) => item.type === 'image');
if (images.length > 0) {
images[0].name = 'theBottom';
images[1].name = 'backgroundMap';
const imageStyle = imgFn.find((item) => {
if (item.isType('image') && item.name === 'backgroundMap') {
return item;
}
});
const imageBottomColor = imgFn.find((item) => {
if (item.isType('image') && item.name === 'theBottom') {
return item;
}
});
if (imageStyle) {
imageStyle.setSrc(
imageSrc,
() => {
// 重新渲染画布
canvasEditor.canvas.renderAll();
},
{
crossOrigin: 'anonymous', // 如果图片可能存在跨域问题,需要设置此选项
}
);
}
if (imageBottomColor) {
if (silkBanner.productColor === '选择id') {
// 替换底部图片
imageBottomColor.setSrc(coverRedImage, () => {
canvasEditor.canvas.renderAll();
});
} else if (silkBanner.productColor === '选择id') {
// 替换底部图片
imageBottomColor.setSrc(coverAnImage, () => {
canvasEditor.canvas.renderAll();
});
} else if (silkBanner.productColor === '选择id') {
// 替换底部图片
imageBottomColor.setSrc(blackImage, () => {
canvasEditor.canvas.renderAll();
});
}
}
}
}
最后解决了打包后找不到图片的问题