ZSWYD

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了。

至此,需求告一段落。但是这里因为影响到了页面的其他样式,调这块的时候真是苦不堪言啊!!!
记录一下。

posted on 2025-08-08 18:01  苏舒  阅读(170)  评论(0)    收藏  举报

导航