Fabric.js动态更改canvas渲染图片

项目属于二开,使用的是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();
        });
      }
    }
  }
}

最后解决了打包后找不到图片的问题

  • 9
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值