微信小程序渲染图片,实现动态颜色变换

原由:小程序支持image使用svg格式图片,但是不支持上色

现有几种解决方案,归类为占小程序包体积大小和不太占小程序包体积大小

分类一:占小程序包体积大小

  • 方案一:小程序使用字体图标实现
uniapp开发的小程序使用字体图标:
步骤一:App.vue的css加上:
@font-face {
        font-family: 'iconfont';
        src: url('https://at.alicdn.com/t/font_865816_17gjspmmrkti.ttf') format('truetype');
    }
@font-face {
        font-family: 'iconfont1';
        src: url('//at.alicdn.com/t/c/font_4746321_9p80oinolbu.ttf?t=1732699493736') format('truetype');
    }

步骤二:要用字体图标的页面css加上:
.test {
        font-family: iconfont;
        margin-left: 20rpx;
    }
.test1 {
        font-family: iconfont1;
        margin-left: 20rpx;
    }

步骤三:要用字体图标的页面html加上:
<text class="test">&#xe600;</text>
<text class="test1">&#xe628;</text>  
  • 方案二:小程序获取svg图片文本后将颜色值使用正则表达式替换后转成base64图片显示
    本人做的-uniapp插件

分类二:不太占小程序包体积大小

  • 方案一:小程序图片不需要管理后台维护的,直接叫后端把svg格式图片转成png的返回到接口中
    具体做法如下
在Java中处理完SVG格式图片的颜色后,如果你需要将其保存为PNG格式并返回到前端,你可以使用Java的图形处理库,如java.awt和javax.imageio,以及可能的第三方库如Apache Batik(它提供了将SVG转换为图像的功能)。

以下是一个简化的步骤指南和示例代码,展示了如何将处理后的SVG转换为PNG格式并返回给前端:

处理SVG文件:首先,使用你之前编写的代码或库来处理SVG文件,修改其颜色等属性。
将SVG转换为图像:使用Apache Batik或类似的库将处理后的SVG内容转换为BufferedImage对象。
将图像保存为PNG:使用ImageIO.write方法将BufferedImage对象保存为PNG格式的文件或字节数组。
将PNG返回给前端:将PNG文件的字节数组作为HTTP响应的主体返回给前端,通常设置响应的内容类型为image/png。
以下是一个使用Apache Batik库将SVG转换为PNG并返回给前端的示例代码:
java
import org.apache.batik.transcoder.TranscoderInput;
import org.apache.batik.transcoder.TranscoderOutput;
import org.apache.batik.transcoder.image.PNGTranscoder;
import org.w3c.dom.Document;
 
import javax.imageio.ImageIO;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.StringReader;
 
// ... 省略其他必要的导入和代码 ...
 
public class SvgToPngConverter {
 
    // 假设你已经有了一个处理后的SVG字符串
    private String processedSvgContent;
 
    public byte[] convertSvgToPng(String svgContent) throws Exception {
        // 解析SVG字符串为DOM文档
        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
        DocumentBuilder builder = factory.newDocumentBuilder();
        Document document = builder.parse(new StringReader(svgContent));
 
        // 使用Apache Batik的PNGTranscoder将SVG转换为PNG
        PNGTranscoder transcoder = new PNGTranscoder();
        TranscoderInput input = new TranscoderInput(document);
        ByteArrayOutputStream pngOutputStream = new ByteArrayOutputStream();
        TranscoderOutput output = new TranscoderOutput(pngOutputStream);
 
        transcoder.transcode(input, output);
 
        // 获取PNG字节数组
        return pngOutputStream.toByteArray();
    }
 
    public void sendPngToFrontend(HttpServletResponse response, String svgContent) throws IOException {
        try {
            byte[] pngBytes = convertSvgToPng(svgContent);
 
            // 设置响应内容类型
            response.setContentType("image/png");
 
            // 将PNG字节数组写入响应输出流
            try (ServletOutputStream outputStream = response.getOutputStream()) {
                outputStream.write(pngBytes);
            }
        } catch (Exception e) {
            // 处理异常,可能记录日志或返回错误响应
            e.printStackTrace();
            response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "Failed to convert SVG to PNG");
        }
    }
 
    // ... 省略其他方法,如处理前端请求和返回结果等 ...
}
在这个示例中,convertSvgToPng方法接收一个SVG字符串,使用Apache Batik的PNGTranscoder将其转换为PNG格式的字节数组。sendPngToFrontend方法则接收一个HttpServletResponse对象和SVG内容,调用convertSvgToPng方法获取PNG字节数组,并将其写入响应输出流中,同时设置正确的内容类型。

请注意,你需要将Apache Batik库添加到你的项目依赖中。如果你使用的是Maven,可以在pom.xml文件中添加相应的依赖。

此外,这个示例假设你已经有了处理后的SVG字符串。在实际应用中,你可能需要从文件、数据库或其他来源获取SVG内容,并在处理之前对其进行适当的解析和修改。
  • 方案二:小程序图片需要管理后台维护的,可以在管理后台系统中上传svg格式图片,然后将svg格式图片上色后,转成canvas保存成png格式图片传给后端接口
<template>
  <div>
    <h1>SVG颜色修改和下载功能</h1>
    <!-- 下拉框,选择颜色 -->
    <select v-model="selectedColor">
      <option value="red">红色</option>
      <option value="blue">蓝色</option>
      <option value="green">绿色</option>
    </select>
    <div ref="svgContainer" :style="{fill:selectedColor}" v-html="sidebarSvg" />
    <button @click="saveAsPNG">保存为PNG</button>
  </div>
</template>

<script>
  export default {
    data() {
      return {
        selectedColor: 'red',  // 默认选择颜色为红色
        svgUrl: 'svg图片网络地址',
        sidebarSvg: ''
      }
    },
    mounted() {
      this.loadSvg()
    },
    methods: {
      // 请求加载svg
      async loadSvg() {
        const response = await fetch(this.svgUrl)
        const svgText = await response.text()
        this.sidebarSvg = svgText
      },
      // 保存SVG为PNG
      saveAsPNG() {
        const svgElement = this.$refs.svgContainer.querySelector('svg') // 获取SVG元素
        const canvas = document.createElement('canvas') // 创建一个canvas元素
        const ctx = canvas.getContext('2d') // 获取2d上下文

        // 设置canvas的宽高为SVG的viewBox大小
        const viewBox = svgElement.getAttribute('viewBox').split(' ')
        const width = parseFloat(viewBox[2])
        const height = parseFloat(viewBox[3])

        // 设置canvas的宽高为SVG的viewBox大小
        canvas.width = width
        canvas.height = height

        // 将SVG转换为图片URL
        const svgData = new XMLSerializer().serializeToString(svgElement)
        const svgBlob = new Blob([svgData], { type: 'image/svg+xml' })
        const svgURL = URL.createObjectURL(svgBlob)
        // 创建图片并加载SVG数据
        const img = new Image()
        img.onload = () => {
          // 将SVG图像绘制到Canvas上
          ctx.drawImage(img, 0, 0, width, height)
          // 将Canvas转换为PNG
          const pngDataUrl = canvas.toDataURL('image/png')
          // console.log('base64图片路径:', pngDataUrl)
          // 如果是将图片上传到服务器,需要将图片格式转换成二进制
          // // 将Base64图片转换为Blob
          // const blob = this.dataUrlToBlob(pngDataUrl)
          // console.log('blob', blob)
          // // 创建FormData并添加Blob
          // const formData = new FormData()
          // formData.append('file', blob, 'image.png') // 使用图片的Blob对象
          // 创建下载链接并触发下载
          const link = document.createElement('a')
          link.download = 'modified-image.png'  // 设置下载文件名
          link.href = pngDataUrl  // 设置PNG图片链接
          link.click()  // 模拟点击下载
        }
        img.src = svgURL // 设置图片源为SVG URL
      },
      // 将Base64数据转换为Blob对象
      dataUrlToBlob(dataUrl) {
        const [header, base64Data] = dataUrl.split(',')
        const byteString = atob(base64Data)
        const arrayBuffer = new ArrayBuffer(byteString.length)
          const uint8Array = new Uint8Array(arrayBuffer)
            for (let i = 0; i < byteString.length; i++) {
                uint8Array[i] = byteString.charCodeAt(i)
            }
            return new Blob([uint8Array], { type: 'image/png' })
        }
    }
}
</script>

浪迹天涯小king
15 声望1 粉丝