141. Sprite标签(Canvas作为贴图)
上节课案例创建标签的方式,是把一张图片作为Sprite
精灵模型的颜色贴图,本节给大家演示把Canvas画布作为Sprite
精灵模型的颜色贴图,实现一个标签。
注意:本节课主要是技术方案讲解,默认你有Canvas基础,如果没有Canvas基础,可以学习之后再来学习本节课内容。
Canvas画布绘制一个标签
你可以使用Canvas绘制特定轮廓的标签,比如加上指引线或箭头,可以输入特定文字。
下面代码自动适配了不同长度的文字标注,文字符号越多,canvas画布越长。
// 生成一个canvas对象,标注文字为参数name
function createCanvas(name) {/*** 创建一个canvas对象,绘制几何图案或添加文字*/const canvas = document.createElement("canvas");const arr = name.split(""); //分割为单独字符串let num = 0;const reg = /[\u4e00-\u9fa5]/;for (let i = 0; i < arr.length; i++) {if (reg.test(arr[i])) { //判断是不是汉字num += 1;} else {num += 0.5; //英文字母或数字累加0.5}}// 根据字符串符号类型和数量、文字font-size大小来设置canvas画布宽高度const h = 80; //根据渲染像素大小设置,过大性能差,过小不清晰const w = h + num * 32;canvas.width = w;canvas.height = h;const h1 = h * 0.8;const c = canvas.getContext('2d');// 定义轮廓颜色,黑色半透明c.fillStyle = "rgba(0,0,0,0.5)";// 绘制半圆+矩形轮廓const R = h1 / 2;c.arc(R, R, R, -Math.PI / 2, Math.PI / 2, true); //顺时针半圆c.arc(w - R, R, R, Math.PI / 2, -Math.PI / 2, true); //顺时针半圆c.fill();// 绘制箭头c.beginPath();const h2 = h - h1;c.moveTo(w / 2 - h2 * 0.6, h1);c.lineTo(w / 2 + h2 * 0.6, h1);c.lineTo(w / 2, h);c.fill();// 文字c.beginPath();c.translate(w / 2, h1 / 2);c.fillStyle = "#ffffff"; //文本填充颜色c.font = "normal 32px 宋体"; //字体样式设置c.textBaseline = "middle"; //文本与fillText定义的纵坐标c.textAlign = "center"; //文本居中(以fillText定义的横坐标)c.fillText(name, 0, 0);return canvas;
}
const canvas = createCanvas('设备A')
CanvasTexture
把canvas转化为纹理对象
canvas
画布作为CanvasTexture
的参数创建一个纹理对象,本质上你可以理解为CanvasTexture
把canvas画布当做图片,读取参数canvas画布上的像素值,创建纹理贴图Texture
。
loader.load("../工厂.glb", function (gltf) {model.add(gltf.scene);const canvas = createCanvas('设备A');//创建一个canvas画布// canvas画布作为CanvasTexture的参数创建一个纹理对象// 本质上你可以理解为CanvasTexture读取参数canvas画布上的像素值const texture = new THREE.CanvasTexture(canvas);const spriteMaterial = new THREE.SpriteMaterial({map: texture,});const sprite = new THREE.Sprite(spriteMaterial);
})
精灵模型尺寸和位置设置
精灵模型尺寸和位置设置具体思路可以参考上节课讲解。
注意精灵模型宽高比和canvas画布宽高比保持一致即可。
const y = 4;//精灵y方向尺寸
// sprite宽高比和canvas画布保持一致
const x = canvas.width/canvas.height*y;//精灵x方向尺寸
sprite.scale.set(x, y, 1);// 控制精灵大小
sprite.position.y = y / 2; //标签底部箭头和空对象标注点重合
const obj = gltf.scene.getObjectByName('设备A标注'); // obj是建模软件中创建的一个空对象
obj.add(sprite); //tag会标注在空对象obj对应的位置
cavnas精灵标签封装(标注多个)
封装一个创建cavnas精灵标签的函数,可以根据需要调用,标注任何需要标注的地方。
import * as THREE from 'three';
import createCanvas from './canvas';
// 标注位置对应的模型对象obj
// name:标注文字
function createSprite(obj,name) {const canvas = createCanvas(name);//创建一个canvas画布// canvas画布作为CanvasTexture的参数创建一个纹理对象const texture = new THREE.CanvasTexture(canvas);const spriteMaterial = new THREE.SpriteMaterial({map: texture,});const sprite = new THREE.Sprite(spriteMaterial);// 控制精灵大小(sprite宽高比和canvas画布保持一致)const s = 0.05;//通过canvas宽高度缩放后,设置sprite.scale,避免图文宽高比变形const x = canvas.width*s;const y = canvas.height*s;sprite.scale.set(x, y, 1);sprite.position.y = y / 2; //标签底部箭头和空对象标注点重合 obj.add(sprite); //tag会标注在空对象obj对应的位置
}export default createSprite;
Canvas包含外部图片
如果Canvas包含外部图片作为背景,注意创建CanvasTexture
的时候,不管你的代码结构怎么组织,主要要等图像加载完成再执行THREE.CanvasTexture(canvas)
,如果还未加载完成,创建纹理时候,读取画布像素时候,会不包含图片。
// 生成一个canvas对象,标注文字为参数name
function createCanvas(img,name) {/*** 创建一个canvas对象,绘制几何图案或添加文字*/const canvas = document.createElement("canvas");const w = 140; //根据渲染像素大小设置,过大性能差,过小不清晰const h = 80;canvas.width = w;canvas.height = h;const h1 = h * 0.8;const c = canvas.getContext('2d');c.fillStyle = "rgba(0,0,0,0.0)"; //背景透明c.fillRect(0, 0, w, h);c.drawImage(img, 0, 0, w, h);//图片绘制到canvas画布上// 文字c.beginPath();c.translate(w / 2, h1 / 2);c.fillStyle = "#ffffff"; //文本填充颜色c.font = "normal 32px 宋体"; //字体样式设置c.textBaseline = "middle"; //文本与fillText定义的纵坐标c.textAlign = "center"; //文本居中(以fillText定义的横坐标)c.fillText(name, 0, 0);return canvas;
}
const img = new Image();img.src = "./标签箭头背景.png";img.onload = function () {const canvas = createCanvas(img,'设备A');//创建一个canvas画布// 图片加载完成后,读取canvas像素数据创建CanvasTextureconst texture = new THREE.CanvasTexture(canvas);...const sprite = new THREE.Sprite(spriteMaterial);...}
相关文章:

141. Sprite标签(Canvas作为贴图)
上节课案例创建标签的方式,是把一张图片作为Sprite精灵模型的颜色贴图,本节给大家演示把Canvas画布作为Sprite精灵模型的颜色贴图,实现一个标签。 注意:本节课主要是技术方案讲解,默认你有Canvas基础,如果没有Canvas基…...

【IDEA】解决总是自动导入全部类(.*)问题
文章目录 问题描述解决方法 我是一名立志把细节说清楚的博主,欢迎【关注】🎉 ~ 原创不易, 如果有帮助 ,记得【点赞】【收藏】 哦~ ❥(^_-)~ 如有错误、疑惑,欢迎【评论】指正探讨,我会尽可能第一时间回复…...
python中的OS模块的基本使用
🎉🎉🎉欢迎来到我的博客,我是一名自学了2年半前端的大一学生,熟悉的技术是JavaScript与Vue.目前正在往全栈方向前进, 如果我的博客给您带来了帮助欢迎您关注我,我将会持续不断的更新文章!!!🙏🙏🙏 文章目录…...

【Qt】QComboBox设置默认显示为空
需求 使用QComboBox,遇到一个小需求是,想要设置未点击出下拉列表时,内容显示为空。并且不想在下拉列表中添加一个空条目。 实现 使用setPlaceholderText()接口。我们先来看下帮助文档: 这里说的是,placeholderText是…...

LeetCode - #139 单词拆分
文章目录 前言摘要1. 描述2. 示例3. 答案题解动态规划的思路代码实现代码解析1. **将 wordDict 转换为 Set**2. **初始化 DP 数组**3. **状态转移方程**4. **返回结果** **测试用例**示例 1:示例 2:示例 3: 时间复杂度空间复杂度总结关于我们 前言 本题由于没有合适答案为以往遗…...
服务器作业4
[rootlocalhost ~]# vim 11.sh #关闭防火墙 systemctl stop firewalld setenforce 0 #1.接收用户部署的服务名称 read -p "服务名称:(nginx)" server_name if [ $server_name ! nginx ];then echo "输入的不是nginx,脚本退出" exit 1 fi # 判断是…...

IOC控制反转---相关的介绍和6大注解解读(类注解+方法注解)
文章目录 1.传统方式造车2.传统方法的弊端3.IOC的引入3.IOC对于图书管理系统进行改进(初识)4.注解的使用说明4.1controller注解4.2service注解4.3component注解4.4关于spring命名的问题4.5component重命名4.6repository注解4.7configuration注解4.8注解之…...

SpringBoot(8)-任务
目录 一、异步任务 二、定时任务 三、邮件任务 一、异步任务 使用场景:后端发送邮件需要时间,前端若响应不动会导致体验感不佳,一般会采用多线程的方式去处理这些任务,但每次都需要自己去手动编写多线程来实现 1、编写servic…...

【机器学习】如何配置anaconda环境(无脑版)
马上就要上机器学习的实验,这里想写一下我配置机器学习的anaconda环境的二三事 一、首先,下载安装包: Download Now | Anaconda 二、打开安装包,一直点NEXT进行安装 这里要记住你要下载安装的路径在哪,后续配置环境…...
java 可以跨平台的原因是什么?
我们对比一个东西就可以了,那就是chrome浏览器。 MacOS/Linux/Windows上的Chrome浏览器,那么对于HTML/CSS/JS的渲染效果都一样的。 我们就可以认为ChromeHTML/CSS/JS是跨平台的。 这里面,HTML/CSS/JS是不变的的,对于一个网页&a…...

Solana应用开发常见技术栈
编程语言 Rust Rust是Solana开发中非常重要的编程语言。它具有高性能、内存安全的特点。在Solana智能合约开发中,Rust可以用于编写高效的合约代码。例如,Rust的所有权系统可以帮助开发者避免常见的内存错误,如悬空指针和数据竞争。通过合理利…...
npm | Yarn | pnpm Node.js包管理器比较与安装
一、包管理器比较 参考原文链接: 2024 Node.js Package Manager 指南:npm、Yarn、pnpm 比较 — 2024 Node.js Package Manager Guide: npm, Yarn, pnpm Compared (nodesource.com) 以下是对 Node.js 的三个包管理工具 npm、Yarn 和 pnpm 的优缺点总结&am…...

Linux下编译MFEM
本文记录在Linux下编译MFEM的过程。 零、环境 操作系统Ubuntu 22.04.4 LTSVS Code1.92.1Git2.34.1GCC11.4.0CMake3.22.1Boost1.74.0oneAPI2024.2.1 一、安装依赖 二、编译代码 附录I: CMakeUserPresets.json {"version": 4,"configurePresets": [{&quo…...

【团购核销】抖音生活服务商家应用快速接入②——商家授权
文章目录 一、前言二、授权流程三、授权Url3.1 Url参数表3.2 授权能力表3.3 源码示例 四、授权回调4.1 添加授权回调接口4.2 授权回调接口源码示例 五、实际操作演示六、参考 一、前言 目的:将抖音团购核销的功能集成到我们自己开发的App和小程序中 【团购核销】抖音…...

django宠物服务管理系统
摘 要 宠物服务管理系统是一种专门为宠物主人和宠物服务提供商设计的软件。它可以帮助用户快速找到附近的宠物医院、宠物美容店、宠物寄养中心等服务提供商,并预订相关服务。该系统还提供了一系列实用的功能。通过使用宠物服务管理系统,用户可以更加方便…...
vue2中使用three.js步骤
1.使用npm 下载依赖这里以0.158.0版本为例 npm install three0.158.0 --save 2. <template><div id"container"></div> </template><script> import * as THREE from three; import { OBJLoader } from three/examples/jsm/loaders/O…...

部落商城App开发笔记 2024.11.21 实现进入app就是短视频
初步效果: 基于图鸟UI二次开发, 这里静态资源没有加载, 我在本机上安装了一个nginx, 需要启动一下. PS C:\dev\nginx-1.26.2> start .\nginx.exe重新刷新就有数据了. 先看看目前的页面吧. 首页. 分类: 发现. 消息. 购物车. 我的. 这个项目是有短视频的功能…...
解决.DS_Store 在项目一致无法排除,.gitignore里也不生效
.DS_Store 是 macOS 操作系统创建的隐藏文件,通常用于存储目录的属性,比如视图设置、图标位置等。它通常不应包含在代码仓库中,因此需要排除它。你提到即使将其添加到 .gitignore 文件中,仍然无法排除它,可能是由于以下…...

MySQL-关键字执行顺序
💖简介 在MySQL中,SQL查询语句的执行遵循一定的逻辑顺序,即使这些关键字在SQL语句中的物理排列可能有所不同。 🌟语句顺序 (8) SELECT (9) DISTINCT<select_list> (1) FROM <left_table> (3) <join_type> JO…...
极客时间《Redis核心技术与实战》开篇词 知识点总结
Redis 主要的数据持久化方式 RDB(Redis Database Backup file) RDB 是 Redis 提供的一种数据快照持久化方式,它会在指定的时间间隔内生成数据集的时间点快照,并将这些快照保存到磁盘上的一个 RDB 文件中。RDB 文件是一个压缩的二…...
web vue 项目 Docker化部署
Web 项目 Docker 化部署详细教程 目录 Web 项目 Docker 化部署概述Dockerfile 详解 构建阶段生产阶段 构建和运行 Docker 镜像 1. Web 项目 Docker 化部署概述 Docker 化部署的主要步骤分为以下几个阶段: 构建阶段(Build Stage):…...
应用升级/灾备测试时使用guarantee 闪回点迅速回退
1.场景 应用要升级,当升级失败时,数据库回退到升级前. 要测试系统,测试完成后,数据库要回退到测试前。 相对于RMAN恢复需要很长时间, 数据库闪回只需要几分钟。 2.技术实现 数据库设置 2个db_recovery参数 创建guarantee闪回点,不需要开启数据库闪回。…...

docker详细操作--未完待续
docker介绍 docker官网: Docker:加速容器应用程序开发 harbor官网:Harbor - Harbor 中文 使用docker加速器: Docker镜像极速下载服务 - 毫秒镜像 是什么 Docker 是一种开源的容器化平台,用于将应用程序及其依赖项(如库、运行时环…...
Java 语言特性(面试系列1)
一、面向对象编程 1. 封装(Encapsulation) 定义:将数据(属性)和操作数据的方法绑定在一起,通过访问控制符(private、protected、public)隐藏内部实现细节。示例: public …...

简易版抽奖活动的设计技术方案
1.前言 本技术方案旨在设计一套完整且可靠的抽奖活动逻辑,确保抽奖活动能够公平、公正、公开地进行,同时满足高并发访问、数据安全存储与高效处理等需求,为用户提供流畅的抽奖体验,助力业务顺利开展。本方案将涵盖抽奖活动的整体架构设计、核心流程逻辑、关键功能实现以及…...

P3 QT项目----记事本(3.8)
3.8 记事本项目总结 项目源码 1.main.cpp #include "widget.h" #include <QApplication> int main(int argc, char *argv[]) {QApplication a(argc, argv);Widget w;w.show();return a.exec(); } 2.widget.cpp #include "widget.h" #include &q…...
python如何将word的doc另存为docx
将 DOCX 文件另存为 DOCX 格式(Python 实现) 在 Python 中,你可以使用 python-docx 库来操作 Word 文档。不过需要注意的是,.doc 是旧的 Word 格式,而 .docx 是新的基于 XML 的格式。python-docx 只能处理 .docx 格式…...

vue3+vite项目中使用.env文件环境变量方法
vue3vite项目中使用.env文件环境变量方法 .env文件作用命名规则常用的配置项示例使用方法注意事项在vite.config.js文件中读取环境变量方法 .env文件作用 .env 文件用于定义环境变量,这些变量可以在项目中通过 import.meta.env 进行访问。Vite 会自动加载这些环境变…...
Spring AI与Spring Modulith核心技术解析
Spring AI核心架构解析 Spring AI(https://spring.io/projects/spring-ai)作为Spring生态中的AI集成框架,其核心设计理念是通过模块化架构降低AI应用的开发复杂度。与Python生态中的LangChain/LlamaIndex等工具类似,但特别为多语…...
Angular微前端架构:Module Federation + ngx-build-plus (Webpack)
以下是一个完整的 Angular 微前端示例,其中使用的是 Module Federation 和 npx-build-plus 实现了主应用(Shell)与子应用(Remote)的集成。 🛠️ 项目结构 angular-mf/ ├── shell-app/ # 主应用&…...