uniapp使用svg标签转换base64格式渲染页面并预览
啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊,这个项目真是,各种小程序不支持,需求却还要做!!!!!!!!
我这边收到后端一个2M的svg标签,需要呈现页面。
使用uniapp呈现很简单,转换base64格式,然后给它放image标签或者 用view的背景图都可以直接渲染出来
//svg转base64格式
svgToBase64(svgString) {
const str = wx.arrayBufferToBase64(
new Uint8Array(
Array.from(svgString).map(c => c.charCodeAt(0))
)
)
return `data:image/svg+xml;base64,${str}`;
// return str
},
//直接html部分
<view :style="{'background-image': 'url('+svg1+')'}" class="icon" @click="clickImg(svg1)"></view>
<image :src="svg1" mode="" class="icon" @click="clickImg()"></image>
呵呵,难点不在这里
需求要求我这边根据后端返回的信息处理svg并给svg重新改变颜色,然后渲染出来
废话一句,上代码
// 渲染数据表
provinceList:[
{
id:'path14',
name: '内蒙古自治区',
color: '#fff',
high: false,
value: 0
},
{
id:'path16',
name: '黑龙江省',
color: '#fff',
high: false,
value: 0
},
{
id:'path18',
name: '吉林省',
color: '#fff',
high: false,
value: 0
},
{
id:'path20',
name: '辽宁省',
color: '#fff',
high: false,
value: 0
}...
],
//初始化
async init(){
this.svg1 = '加载中...'
this.provinceList = this.syncProvinceValues(this.provinceList, this.list)
this.provinceList = this.updateProvinceHigh(this.provinceList, this.province)
this.provinceList = this.assignColorsToProvinces(this.provinceList, this.colorList)
await this.$http3.get('map.txt').then(res => {
this.url = this.updateSvgPathColors(res, this.provinceList)
this.svg1 = this.svgToBase64(this.url)
})
},
//合并value值
syncProvinceValues(provinceArray, listArray) {
return provinceArray.map(province => {
const matchedItem = listArray.find(item => item.key == province.name);
if (matchedItem) {
return {
...province,
value: Number(matchedItem.value) // 确保 value 是数字
};
}
return province; // 如果没有匹配项,保持原样
});
},
//确定high值
updateProvinceHigh(provinceArray, targetName) {
if(targetName == ''){
return provinceArray.map(item => ({
...item,
high: false
}));
}else{
return provinceArray.map(item => ({
...item,
high: item.name.includes(targetName)
}));
}
},
/**
* 根据heatmapData的value值动态分配颜色给province数组
* @param {Array} province - 省份数组,格式:[{id: 'path14', name: '内蒙古自治区', color: '#fff'}]
* @param {Array} colorList - 颜色数组,格式:['#134c8e','#205ca2',...]
* @returns {Array} 更新颜色后的province数组
*/
assignColorsToProvinces(province, colorList) {
// 获取所有value值并排序
const values = province.map(item => item.value).sort((a, b) => a - b)
const minValue = values[0]
const maxValue = values[values.length - 1]
let successCount = 0
let failCount = 0
// 为每个省份分配颜色
province.forEach(provinceItem => {
// 尝试多种匹配策略
if(provinceItem.value == 0){
provinceItem.color = '#fff'
}else{
// 计算颜色索引
const normalizedValue = (provinceItem.value - minValue) / (maxValue - minValue)
const colorIndex = Math.floor(normalizedValue * (colorList.length - 1))
const color = colorList[colorIndex] || colorList[0]
// 更新province的颜色
provinceItem.color = color
successCount++
}
})
// 输出统计信息
console.log(`🎨 颜色分配完成: 成功 ${successCount} 个,失败 ${failCount} 个,总计 ${province.length} 个省份`)
console.log(`📊 数据范围: ${minValue} - ${maxValue}, 颜色数量: ${colorList.length}`)
return province
},
//没错,上面这个方法是AI生成的,好用!得劲!
/**
* 根据province数组更新SVG中对应path标签的fill颜色
* @param {string} svgString - SVG字符串
* @param {Array} province - 省份数组,包含id和color属性
* @returns {string} 更新后的SVG字符串
*/
updateSvgPathColors(svgString, province) {
let updatedSvg = svgString
let successCount = 0
let failCount = 0
province.forEach(provinceItem => {
if (provinceItem.color && !provinceItem.high) {
// 将颜色转换为URL编码格式
// const encodedColor = provinceItem.color.replace("#", "%23")
const encodedColor = provinceItem.color
// 匹配包含指定id的path标签,并更新其fill颜色
const regex = new RegExp(`(id="${provinceItem.id}"[^>]*style="[^"]*fill:)[^;"]+`, 'g')
const match = updatedSvg.match(regex)
if (match) {
updatedSvg = updatedSvg.replace(regex, `$1${encodedColor}`)
successCount++
} else {
failCount++
}
}else if(provinceItem.high){
// 将颜色转换为URL编码格式
const encodedColor = "#00ffb6"
// 匹配包含指定id的path标签,并更新其fill颜色
const regex = new RegExp(`(id="${provinceItem.id}"[^>]*style="[^"]*fill:)[^;"]+`, 'g')
const match = updatedSvg.match(regex)
if (match) {
updatedSvg = updatedSvg.replace(regex, `$1${encodedColor}`)
} else {
failCount++
}
}
})
console.log(`🎨 SVG颜色更新完成: 成功 ${successCount} 个,失败 ${failCount} 个`)
return updatedSvg
},
//这个也是
//然后调用接口获取res
this.url = this.updateSvgPathColors(res, this.provinceList)
this.svg1 = this.svgToBase64(this.url)//调用最上面那个转码
至此,上面需求完成了,后端获取数据,合并数据项,更改渲染数据的高亮,颜色。获取数据后将渲染数据拼接替换。替换完成之后再进行svg转base64
那么,新需求又又又来啦!!!!!!!!!!!预览
在搜罗了uniapp跟微信小程序常用图片预览后,都达不到要求!!!!!!!!!!!!!
没错,不是真机不渲染,没反应,就是一直转圈圈黑屏
包括不限于 wx.previewImage wx.previewmedia 将base64缓存本地使用缓存地址预览 渲染至canvas上预览 使用webview显示
然后我就只好自己找方法。
<uni-popup ref="popup" background-color="#000" :mask-background-color="'rgba(0,0,0,)'" style="width: 100vw;height: 100vh;" maskbg="rgba(225, 225, 225, 1)" @maskClick="closed">
<movable-area scale-area style="background-color: #E1E1E1;">
<movable-view direction="all" :x="-740" :out-of-bounds="true" :y="-500" inertia scale scale-min="1" scale-max="4" scale-value="3" style="width: 100vw;height: 100vh;z-index: 9999;" @click="closed">
<image :src="svg1" mode=""></image>
</movable-view>
</movable-area>
</uni-popup>
//外层是一个弹框,给它加个蒙版,maskbg是我项目里自己配的蒙版颜色,直接改的组件里
//里面movable-area是一个容器,只有10*10大小,需要给定一个背景颜色,要不然就是一个黑点。很突兀
//移动的就是这个了 movable-view,微信小程序文档有介绍,我就不详细说属性了
//最里面就是我们需要预览的那个image/view了。
至此,需求告一段落。但是这里因为影响到了页面的其他样式,调这块的时候真是苦不堪言啊!!!
记录一下。
没有什么是一蹴而就的。
浙公网安备 33010602011771号