实现人体模型可点击
简化需求:实现项目内嵌人体模型,实现点击不同部位弹出部位名称
一:优先3d,
方案:基于three.js,.gltf格式模型,vue3
缺点:合适且免费的3d模型找不到,因为项目对部位有要求。
注意:模型地址请使用绝对路径。
效果图:

代码:
<template><div ref="canvasContainer" class="canvas-container"></div>
</template><script setup>
import * as THREE from 'three'
import { onMounted, ref } from 'vue'
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js'const canvasContainer = ref(null)onMounted(() => {let scene, camera, renderer, modellet raycaster = new THREE.Raycaster()let mouse = new THREE.Vector2()let selectedPart = nulllet isDragging = falselet previousMousePosition = { x: 0, y: 0 }const init = () => {// 创建场景scene = new THREE.Scene()scene.background = new THREE.Color(0xeeeeee)// 创建相机camera = new THREE.PerspectiveCamera(45, 500 / 500, 0.1, 1000)camera.position.set(0, 1.6, 3) // 相机位置// 创建渲染器,并设置大小为500px × 500pxrenderer = new THREE.WebGLRenderer({ antialias: true })renderer.setSize(500, 500)canvasContainer.value.appendChild(renderer.domElement)// 添加光源const light = new THREE.DirectionalLight(0xffffff, 1)light.position.set(5, 10, 7.5)scene.add(light)// 加载3D模型const loader = new GLTFLoader()loader.load('src/assets/models/b1_battle_droid/scene.gltf', (gltf) => {model = gltf.scenescene.add(model)})// 鼠标事件监听window.addEventListener('mousemove', onMouseMove)window.addEventListener('click', onClick)window.addEventListener('mousedown', onMouseDown)window.addEventListener('mouseup', onMouseUp)window.addEventListener('mousemove', onMouseMoveRotation)}const onMouseMove = (event) => {// 将鼠标位置标准化为Three.js坐标const rect = renderer.domElement.getBoundingClientRect()mouse.x = ((event.clientX - rect.left) / rect.width) * 2 - 1mouse.y = -((event.clientY - rect.top) / rect.height) * 2 + 1raycaster.setFromCamera(mouse, camera)const intersects = raycaster.intersectObjects(scene.children, true)if (intersects.length > 0) {if (selectedPart) {// 恢复之前选中的部件颜色selectedPart.material.emissive.setHex(selectedPart.currentHex)}selectedPart = intersects[0].objectselectedPart.currentHex = selectedPart.material.emissive.getHex()selectedPart.material.emissive.setHex(0xff0000) // 悬浮变色} else if (selectedPart) {// 鼠标离开时恢复颜色selectedPart.material.emissive.setHex(selectedPart.currentHex)selectedPart = null}}const onClick = (event) => {if (selectedPart) {alert(`你点击了: ${selectedPart.name}`)}}const onMouseDown = () => {isDragging = true}const onMouseUp = () => {isDragging = false}const onMouseMoveRotation = (event) => {if (isDragging) {const deltaMove = {x: event.clientX - previousMousePosition.x,y: event.clientY - previousMousePosition.y,}const rotationSpeed = 0.005model.rotation.y += deltaMove.x * rotationSpeedmodel.rotation.x += deltaMove.y * rotationSpeed}previousMousePosition = {x: event.clientX,y: event.clientY,}}const animate = () => {requestAnimationFrame(animate)renderer.render(scene, camera)}init()animate()
})
</script><style>
.canvas-container {width: 500px;height: 500px;overflow: hidden;margin: 0 auto;/* 居中对齐 */
}
</style>
方案二:差强人意选2d
方案:基于canvas,.png格式图片,vue3
缺点:效果差一些,旋转没有了,身体部位区分做不到很细致。
注意:图片地址import引入,再引用。
效果图:

代码:
<template><div><canvas ref="canvas" @click="handleClick"></canvas></div>
</template><script setup>
import { onMounted, ref } from 'vue'
import imgsrc from '@/assets/models/person.png'
const canvas = ref(null)
const bodyParts = [{ name: 'Head', x: 50, y: 30, width: 100, height: 100 },{ name: 'Chest', x: 50, y: 150, width: 100, height: 100 },{ name: 'Abdomen', x: 50, y: 270, width: 100, height: 100 },{ name: 'Legs', x: 50, y: 390, width: 100, height: 100 },
]onMounted(() => {handleImage()
})
const handleImage = () => {const ctx = canvas.value.getContext('2d')canvas.value.width = 200 // 设置 canvas 的宽度canvas.value.height = 500 // 设置 canvas 的高度const img = new Image()img.src = imgsrc // 使用 Vue 项目中的图片路径img.onload = function () {// 确保图片加载完成后绘制到 canvas 上ctx.clearRect(0, 0, canvas.value.width, canvas.value.height) // 清空 canvasctx.drawImage(img, 0, 0, canvas.value.width, canvas.value.height) // 绘制图片// 调试用:绘制点击区域的边框bodyParts.forEach((part) => {ctx.strokeStyle = 'red' // 用红色边框标记部位ctx.strokeRect(part.x, part.y, part.width, part.height)})}console.log('path is ' + img.src)
}
const handleClick = (event) => {const rect = canvas.value.getBoundingClientRect()const x = event.clientX - rect.leftconst y = event.clientY - rect.topconst clickedPart = bodyParts.find((part) => {return (x >= part.x &&x <= part.x + part.width &&y >= part.y &&y <= part.y + part.height)})if (clickedPart) {alert(`You clicked on: ${clickedPart.name}`)}
}
</script><style scoped>
canvas {border: 1px solid black;
}
</style>
三:蹲蹲更好的解决方法。
相关文章:
实现人体模型可点击
简化需求:实现项目内嵌人体模型,实现点击不同部位弹出部位名称 一:优先3d, 方案:基于three.js,.gltf格式模型,vue3 缺点:合适且免费的3d模型找不到,因为项目对部位有要…...
C++ | Leetcode C++题解之第429题N叉树的层序遍历
题目: 题解: class Solution { public:vector<vector<int>> levelOrder(Node* root) {if (!root) {return {};}vector<vector<int>> ans;queue<Node*> q;q.push(root);while (!q.empty()) {int cnt q.size();vector<…...
Pandas简介
Pandas 是一个流行的开源数据分析库,它是基于 NumPy 构建的,为 Python 编程语言提供了高性能、易用的数据结构和数据分析工具。Pandas 主要用于数据清洗、数据转换、数据分析等任务,使得数据处理工作变得更加高效和便捷。 Pandas 的两个主要…...
Python | Leetcode Python题解之第430题扁平化多级双向链表
题目: 题解: class Solution:def flatten(self, head: "Node") -> "Node":def dfs(node: "Node") -> "Node":cur node# 记录链表的最后一个节点last Nonewhile cur:nxt cur.next# 如果有子节点&#…...
机器人机构、制造
简单整理一下,在学习了一些运动学和动力学之类的东西,简单的整合了一些常用的机械结构和图片。 1.电机: 市面上的电机有:直流电机,交流电机,舵机,步进电机,电缸,无刷电…...
《拿下奇怪的前端报错》:nvm不可用报错`GLIBC_2.27‘‘GLIBCXX_3.4.20‘not Found?+ 使用docker构建多个前端项目实践
有些前端的小伙伴可能会好奇,nvm是什么?这里接简单介绍下,它是一个Nodejs版本管理工具。为什么需要它呢?当然是需要多个Nodejs版本的时候,那什么时候需要多个Nodejs版本?那肯定是在有点年头的公司了&#x…...
5.《DevOps》系列K8S部署CICD流水线之K8S通过Yaml部署GitLab
架构 服务器IP服务名称硬件配置192.168.1.100k8s-master8核、16G、120G192.168.1.101k8s-node18核、16G、120G192.168.1.102k8s-node28核、16G、120G192.168.1.103nfs2核、4G、500G操作系统:Rocky9.3 后续通过K8S部署Jenkins NFS的SC创建参考:2.《DevOps》系列K8S部署CICD流…...
[SAP ABAP] 创建数据库视图和维护视图
数据准备 学校表(ZDBT_SCH_437) 学生表(ZDBT_STU_437) 学校表(ZDBT_SCH_437)与学生表(ZDBT_STU_437)字段 学校表(ZDBT_SCH_437)与学生表(ZDBT_STU_437)行数据明细 1.创建数据库视图 使用SE11创建数据库视图 填写视图名称ZV_DATABASEV_437,点击创建按钮 选择数据库视…...
【最快最简单的排序 —— 桶排序算法】
最快最简单的排序 —— 桶排序算法 桶排序是一种排序算法,其工作原理是将数据分到有限数量的桶子里,然后对每个桶内的元素进行单独排序,最后依次把各个桶中的记录列出来。桶排序的效率取决于映射函数的选择和桶的数量。 桶排序适用于数据分…...
AI时代,服务器厂商能否打破薄利的命运?
文|刘俊宏 编|王一粟 AI大模型正在引发新一轮的“算力焦渴”。 近日,OpenAI刚发布的o1大模型再次刷新了大模型能力的上限。对比上一次迭代的版本,o1的推理能力全方位“吊打”了GPT-4o。更优秀的能力,来自与o1将思维…...
2024年9月python二级易错题和难题大全(附详细解析)(二)
2024年9月python二级易错题和难题大全(附详细解析)(二) 第1题第2题第3题第4题第5题第6题第7题第8题第9题第10题第11题第12题第13题第14题第15题第16题第17题第18题第19题第20题第1题 1、以下代码的输出结果是() x = 12 + 3 * ((5 * 8) - 14) // 6 print(x) A、25.0 B、6…...
4.结构型设计模式 - 第1回:引言与适配器模式 (Adapter Pattern) ——设计模式入门系列
一、引言 在现代软件开发中,设计模式是帮助我们解决复杂问题的工具,它们提供了在常见场景下重用已验证解决方案的途径。而结构型设计模式主要关注类与对象之间的组合方式,旨在通过增强灵活性和降低耦合度来改进代码的结构。 本次讨论的是结…...
解决mybatis plus 中 FastjsonTypeHandler无法正确反序列化List类型的问题
由于是根据自动映射类型,我们设置的字段类型是List 也就是反序列化的时候也只是用 FastjsonTypeHandler中的 Override protected Object parse(String json) { return JSON.parseObject(json, type); } 反序列化方法,这是type为List 反序列后我们并没…...
MacOS安装homebrew,jEnv,多版本JDK
1 安装homebrew homebrew官网 根据官网提示,运行安装命令 /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"安装后,bash会提示执行两条命令 (echo; echo eval "$(/opt/homebrew/b…...
【HTTP】认识 URL 和 URL encode
文章目录 认识 URLURL 基本格式**带层次的文件路径****查询字符串****片段标识符** URL encode 认识 URL 计算机中非常重要的概念,并不仅仅是在 HTTP 中使用。用来描述一个网络资源所处的位置,全称“唯一资源定位符” URI 是“唯一资源标识符“严格的说…...
【AI学习笔记】初学机器学习西瓜书概要记录(二)常用的机器学习方法篇
初学机器学习西瓜书的概要记录(一)机器学习基础知识篇(已完结) 初学机器学习西瓜书的概要记录(二)常用的机器学习方法篇(持续更新) 初学机器学习西瓜书的概要记录(三)进阶知识篇(待更) 文字公式撰写不易&am…...
[SDX35+WCN6856]SDX35 + WCN6856 默认增加打包wifi配置hostapd_24g.conf和hostapd_5g.conf操作方法
SDX35 SDX35介绍 SDX35设备是一种多模调制解调器芯片,支持 4G/5G sub-6 技术。它是一个4nm芯片专为实现卓越的性能和能效而设计。它包括一个 1.9 GHz Cortex-A7 应用处理器。 SDX35主要特性 ■ 3GPP Rel. 17 with 5G Reduced Capability (RedCap) support. Backward compati…...
【iOS】OC高级编程 iOS多线程与内存管理阅读笔记——自动引用计数
文章目录 什么是自动引用计数 内存管理/引用计数 概要 内存管理的思考方式 自己生成的对象,自己所持有 非自己生成的对象,自己也能持有 不再需要自己持有的对象时释放 无法释放非自己持有的对象 什么是自动引用计数 自动引用计数(AR…...
网络安全-LD_PRELOAD,请求劫持
目录 一、环境 二、开始做题 三、总结原理 四、如何防护 一、环境 我们这里用蚁剑自带的靶场第一关来解释 docker制作一下即可 二、开始做题 首先环境内很明显给我们已经写好了webshell 同样我们也可以访问到 我们使用这个蚁剑把这个webshell连上 我们发现命令不能执行&am…...
GO入门之值传递于引用(指针、内存地址)传递扫盲
GO入门之值传递于引用(指针、内存地址)传递扫盲 Go 语言中,值传递和引用(指针)传递是两个关键的概念。通过案例可以很好地展示两者的区别。 值传递与引用传递的区别: 值传递:传递的是变量的副…...
KubeSphere 容器平台高可用:环境搭建与可视化操作指南
Linux_k8s篇 欢迎来到Linux的世界,看笔记好好学多敲多打,每个人都是大神! 题目:KubeSphere 容器平台高可用:环境搭建与可视化操作指南 版本号: 1.0,0 作者: 老王要学习 日期: 2025.06.05 适用环境: Ubuntu22 文档说…...
多模态2025:技术路线“神仙打架”,视频生成冲上云霄
文|魏琳华 编|王一粟 一场大会,聚集了中国多模态大模型的“半壁江山”。 智源大会2025为期两天的论坛中,汇集了学界、创业公司和大厂等三方的热门选手,关于多模态的集中讨论达到了前所未有的热度。其中,…...
在rocky linux 9.5上在线安装 docker
前面是指南,后面是日志 sudo dnf config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo sudo dnf install docker-ce docker-ce-cli containerd.io -y docker version sudo systemctl start docker sudo systemctl status docker …...
【JVM】- 内存结构
引言 JVM:Java Virtual Machine 定义:Java虚拟机,Java二进制字节码的运行环境好处: 一次编写,到处运行自动内存管理,垃圾回收的功能数组下标越界检查(会抛异常,不会覆盖到其他代码…...
Opencv中的addweighted函数
一.addweighted函数作用 addweighted()是OpenCV库中用于图像处理的函数,主要功能是将两个输入图像(尺寸和类型相同)按照指定的权重进行加权叠加(图像融合),并添加一个标量值&#x…...
[10-3]软件I2C读写MPU6050 江协科技学习笔记(16个知识点)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16...
精益数据分析(97/126):邮件营销与用户参与度的关键指标优化指南
精益数据分析(97/126):邮件营销与用户参与度的关键指标优化指南 在数字化营销时代,邮件列表效度、用户参与度和网站性能等指标往往决定着创业公司的增长成败。今天,我们将深入解析邮件打开率、网站可用性、页面参与时…...
Java编程之桥接模式
定义 桥接模式(Bridge Pattern)属于结构型设计模式,它的核心意图是将抽象部分与实现部分分离,使它们可以独立地变化。这种模式通过组合关系来替代继承关系,从而降低了抽象和实现这两个可变维度之间的耦合度。 用例子…...
逻辑回归暴力训练预测金融欺诈
简述 「使用逻辑回归暴力预测金融欺诈,并不断增加特征维度持续测试」的做法,体现了一种逐步建模与迭代验证的实验思路,在金融欺诈检测中非常有价值,本文作为一篇回顾性记录了早年间公司给某行做反欺诈预测用到的技术和思路。百度…...
CVPR2025重磅突破:AnomalyAny框架实现单样本生成逼真异常数据,破解视觉检测瓶颈!
本文介绍了一种名为AnomalyAny的创新框架,该方法利用Stable Diffusion的强大生成能力,仅需单个正常样本和文本描述,即可生成逼真且多样化的异常样本,有效解决了视觉异常检测中异常样本稀缺的难题,为工业质检、医疗影像…...
