微信小程序渲染图片,实现动态颜色变换
原由:小程序支持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"></text>
<text class="test1"></text>
分类二:不太占小程序包体积大小
- 方案一:小程序图片不需要管理后台维护的,直接叫后端把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>
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。