您的位置:首页 > 科技 > IT业 > 成都画时网站建设_织梦cms破解版_打开百度搜索网站_100个商业经典案例

成都画时网站建设_织梦cms破解版_打开百度搜索网站_100个商业经典案例

2024/12/22 20:29:37 来源:https://blog.csdn.net/no_money000/article/details/144470895  浏览:    关键词:成都画时网站建设_织梦cms破解版_打开百度搜索网站_100个商业经典案例
成都画时网站建设_织梦cms破解版_打开百度搜索网站_100个商业经典案例

1.效果

       在项目开发过程中,有一个需求是有若干个需要展示的点,每个点icon不一样、对应的广告牌文字不一样、并且文字还需要有图片背景、每个文字背景也不同(抓狂)。这种需求只能编写canvas来绘制“icon+文字背景+文字”的image,并返回给billboard。

        实测100个点渲染,我这小破电脑花费140ms,能够满足项目需求;作为一个新手切图崽,所编写的代码还有很多改进的地方,有请各位大佬在评论区批评指正。


2.代码

       调用renderBillboard(options)方法,将返回一个billboard对象,返回值可以直接使用。也可以使用回调,renderBillboard(options,(result)=>{}),result包含billboard所需的image和pixelOffset。

       需要注意的是,vue3+vite加载图片资源使用的是new URL("地址", import.meta.url).href

而vue2加载图片资源使用的是require,在代码中均有,可以根据需要使用。

import * as Cesium from "cesium";
let canvas, context;
/*** @author: linmaoxin* @date: 2024/12/14* @description 渲染billboard,可选择 带背景的文字+图标icon、仅背景的文字 两种类型。1、返回Promise对象,异步获取billboard;2、也可以使用回调分别获取image和pixelOffset。* @param {*} options* @callback function* @returns Promise<object>* @example* let options = {type: 'text-icon',  // 默认 'text-icon'类型(图标+文字)、 'text' 类型(仅文字)paddingTo: 20, // 图标距离文字背景textPadding: 20, // 文字左右间距textBcgWidth: 200, // 文字背景宽度textBcgHeight: 50, // 文字背景高度iconWidth: 60, // 图标宽度iconHeight: 70, // 图标高度textBcgUrl: '../assets/label-bcg.png', // 文字背景图片地址 iconUrl: '../assets/positionIcon.png', // 图标地址textUrl:'', // 字体地址text: '测试文字测试文字', // 文字内容textColor: '#DCD085', // 字体颜色textFontSize: 16, // 字体大小textFontWeight: 800, // 字体粗细} */
export function renderBillboard(options, callback) {let settings = {type: options.type || 'text-icon', // 默认 'text-icon'类型(图标+文字)、 'text' 类型(仅文字)paddingTo: options.paddingTo || 5, // 默认 图标距离文字背景textPadding: options.textPadding || 20, // 默认 文字左右间距textBcgWidth: options.textBcgWidth || 150, // 默认 文字背景宽度textBcgHeight: options.textBcgHeight || 40,  // 默认 文字背景高度iconWidth: options.iconWidth || 40,  // 默认 图标宽度iconHeight: options.iconHeight || 50, // 默认 图标高度textBcgUrl: options.textBcgUrl || console.error('请传入文字背景图片地址 textBcgUrl '), // 文字背景图片地址 iconUrl: options.iconUrl || console.error('请传入图标图片地址 iconUrl '), // 图标地址textUrl: options.textUrl, // 文字地址text: options.text || '', // 文字内容textColor: options.textColor || '#ffffff', // 默认 文字颜色textFontSize: options.textFontSize || 16, // 默认 文字大小textFontWeight: options.textFontWeight || 500, //默认 文字粗细}if (!canvas) {canvas = document.createElement('canvas');}if (!context) {context = canvas.getContext('2d', { willReadFrequently: true });}// 字体初始化context.font = `${Number(settings.textFontWeight)} ${Number(settings.textFontSize)}px Microsoft Yahei`;context.fillStyle = settings.textColor;context.textAlign = 'center';context.textBaseline = 'middle';context.canvas.willReadFrequently = true;// 根据字数计算宽度 并加上左右间距const textMetrics = context.measureText(settings.text);settings.textBcgWidth = textMetrics.width + settings.textPadding;// 画布大小if (settings.type === 'text-icon') {settings.textBcgWidth = settings.textBcgWidth > settings.iconWidth ? settings.textBcgWidth : settings.iconWidth;canvas.width = settings.textBcgWidth;canvas.height = settings.textBcgHeight + settings.paddingTo + settings.iconHeight;} else if (settings.type === 'text') {canvas.width = settings.textBcgWidth;canvas.height = settings.textBcgHeight;}return new Promise((result) => {// 加载图片资源if (settings.type === 'text-icon') {// 字体二次设置context.font = `${Number(settings.textFontWeight)} ${Number(settings.textFontSize)}px Microsoft Yahei`;context.fillStyle = settings.textColor;context.textAlign = 'center';context.textBaseline = 'middle';const image1 = new Image();const image2 = new Image();//image1.src = require(settings.iconUrl); //图标地址 vue2// image2.src = require(settings.textBcgUrl); //文字背景图片地址 vue2image1.src = new URL(settings.iconUrl, import.meta.url).href // viteimage2.src = new URL(settings.textBcgUrl, import.meta.url).href // viteimage1.onload = () => {context.drawImage(image1, 0, 0, canvas.width, canvas.height);}image2.onload = () => {context.drawImage(image2, 0, 0, canvas.width, canvas.height);}Promise.all([new Promise(resolve1 => { image1.onload = resolve1; }),new Promise(resolve2 => { image2.onload = resolve2; })]).then(() => {// 清除画布context.clearRect(0, 0, canvas.width, canvas.height);context.beginPath();// 渲染context.drawImage(image2, 0, 0, settings.textBcgWidth, settings.textBcgHeight);context.drawImage(image1, (canvas.width / 2) - (settings.iconWidth / 2), (settings.textBcgHeight + settings.paddingTo), settings.iconWidth, settings.iconHeight);context.fillText(settings.text, settings.textBcgWidth / 2, settings.textBcgHeight / 2);//  判断callback是不是函数if (typeof callback === 'function') {callback({ 'image': canvas.toDataURL(), 'pixelOffsetY': Math.round(-canvas.height / 2) })}result({image: canvas.toDataURL(),pixelOffset: new Cesium.Cartesian2(0, Math.round(-canvas.height / 2))})// console.log('canvas', canvas.height)});} else if (settings.type === 'text') {const image2 = new Image();//image2.src = require(settings.textBcgUrl); //文字背景图片地址 vue2image2.src = new URL(settings.textBcgUrl, import.meta.url).href // viteimage2.onload = () => {// 清除画布context.clearRect(0, 0, canvas.width, canvas.height);context.beginPath();// 渲染context.drawImage(image2, 0, 0, canvas.width, canvas.height);context.fillText(settings.text, settings.textBcgWidth / 2, settings.textBcgHeight / 2);//  判断callback是不是函数if (typeof callback === 'function') {callback({ 'image': canvas.toDataURL(), 'pixelOffsetY': Math.round(-canvas.height / 2), })}result({image: canvas.toDataURL(),pixelOffset: new Cesium.Cartesian2(0, Math.round(-canvas.height / 2))})}}})}


3.结尾

(1)加载图片资源其实可以用 new Cesium.Resource.fetchImage(url).then(image => {}这个方法,这是Cesium的一个异步加载图片资源的方法,并不一定要使用 new Image。

(2)实现过程本文章不过多赘述,有不懂的地方可以评论区讨论、或者问问AI。


(PS:创造不易,如果文章对你有帮助,可以点个赞鼓励下博主哦!)

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com