图片热区功能

一、需求描述及效果图

1.需求描述:

根据后端返回的坐标及人员信息,在图片上的相应位置添加图片热区功能,点击可展示出对应的人员信息。
图片可进行缩放

2.示例:

(定位是随便写的,仅做示例)
鼠标悬浮到坐标位置上会出现水波纹的效果,点击定位处出现信息框来描述定位位置的信息。
image.png

二、思路

1.使用结合设置图片热区

官网地址:
https://developer.mozilla.org/en-US/docs/Web/HTML/Element/area

代码示例:
image.png

2.数据结构
{
  "code": 0,
  "data": {
    "picture": "base64字符串",
    "personnel": [
      {
        "id": 1,
        "personCode": "code_9527",
        "personName": "nameA",
        "personCard": "320123199901011234",
        "personPhone": "13777777777",
        "personPosition": "position01",
        "personTail": 175,
        "personWeight": 70,
        "registerCamera": "Y",
        "imgPath": "/home/picData/test_9527.jpg",
        "coordinate": {
          "x": 10,
          "y": 20,
          "width": 100,
          "height": 100
        }
      },
      {
        "id": 2,
        "personCode": "code_10000",
        "personName": "nameB",
        "personCard": "320123199901022234",
        "personPhone": "13777777777",
        "personPosition": "position01",
        "personTail": 190,
        "personWeight": 120,
        "registerCamera": "Y",
        "imgPath": "/home/picData/test_10000.jpg",
        "coordinate": {
          "x": 10,
          "y": 20,
          "width": 100,
          "height": 100
        }
      }
    ]
  },
  "message": "请求成功!",
  "time": 0
}
  • props.imageUrl是父组件传递过来的图片地址,上面数据结构中的picture
  • state.areaMap是人员信息数组,上面数据结构中的personnel
  • 数据结构中的coordinate是坐标信息,x和y是热区左上角的坐标;因为热区是矩形的,需要知道左上角和右下角的坐标,需根据热区的宽高来计算出右下角的坐标(热区形状根据需求来定,不唯一)
3.计算坐标
3.1 图片原始尺寸和渲染尺寸

需要获取到图片的原始固定尺寸和渲染的尺寸,从而计算出宽高的比例来正确定位
image.png

  • 图片原始尺寸:
// 图片原始尺寸
const naturalWidth = ref(0);
const naturalHeight = ref(0);
// 获取el-image组件实例的根DOM元素,也就是<img>元素,从而获取到图片的原始宽高
const imgEl = imageRef.value?.$el.querySelector('img');
  if (imgEl) {
    naturalHeight.value = imgEl.naturalHeight;
    naturalWidth.value = imgEl.naturalWidth;
  }

获取el-image组件实例的根DOM元素,元素,从而获取到图片的原始宽高

const imgEl = imageRef.value?.$el.querySelector('img');

注意:确保在组件已正确渲染并挂载到DOM树上之后再尝试获取img元素,以避免在组件尚未准备好时获取null值

  • 图片渲染尺寸:
  const renderWidth = imageRef.value?.$el.clientWidth;
  const renderHeight = imageRef.value?.$el.clientHeight;
3.2 根据缩放比例重新计算坐标

根据图片的原始尺寸和渲染尺寸计算出缩放比

  // 计算比例
  const ratioWidth = renderWidth / naturalWidth.value;
  const ratioHeight = renderHeight / naturalHeight.value;

根据缩放比重新计算热区

const imageRef = ref<any>(null);
const naturalWidth = ref(0);
const naturalHeight = ref(0);

// 计算图片缩放比例
function ratioPic() {
  // 获取图片的原始尺寸
  const imgEl = imageRef.value?.$el.querySelector('img');
  console.log('imgEl', imageRef.value, imgEl.value)
  if (imgEl) {
    naturalHeight.value = imgEl.naturalHeight;
    naturalWidth.value = imgEl.naturalWidth;
  }
  // 图片渲染大小
  const renderWidth = imageRef.value?.$el.clientWidth;
  const renderHeight = imageRef.value?.$el.clientHeight;
  // 计算宽高缩放比例
  const ratioWidth = renderWidth / naturalWidth.value;
  const ratioHeight = renderHeight / naturalHeight.value;
  // 重新计算热区
  state.areaMap = [];
  state.initAreaMap.map((item) => {
    const obj = {
      ...item,
      coordinate: {
        ...item.coordinate,
        width: Math.round(item.coordinate.width * ratioWidth),
        height: Math.round(item.coordinate.height * ratioHeight),
        x: Math.round(item.coordinate.x * ratioWidth),
        y: Math.round(item.coordinate.y * ratioHeight),
      },
    };
    state.areaMap.push(obj);
  });
}

initAreaMap 存放的时候从接口获取的图片热区坐标数据
areaMap 存放经过缩放比计算后的图片热区新坐标(计算时注意要置空)

3.3 监听窗口尺寸变化,实时调整热区
onMounted(async () => {
  // 添加窗口尺寸变化的监听以实时调整热区
  window.addEventListener('resize', handleResize);
});
  
onUnmounted(() => {
  window.removeEventListener('resize', handleResize);
});
  
// 监听屏幕变化重新计算图片热区宽高
function handleResize() {
  // 在这里获取图片当前的实际尺寸,并重新计算热区坐标
  ratioPic();
}
3.4 处理矩形坐标: 左上角 ,右下角
function handleCoordinate(coordinate: Coordinate) {
  const x2 = coordinate.x + coordinate.width;
  const y2 = coordinate.y + coordinate.height;
  return `${coordinate.x},${coordinate.y},${x2},${y2}`;
}

因为后端返回的坐标数据是图片热区的左上角坐标和宽高,在使用时需计算出右下角坐标
矩形热区需要坐标:(左上角x,y 右下角x,y)
coords=“x1, y1, x2, y2”

以上,浏览器自带的缩放功能可正确渲染出热区; 如果需要对图片进行放大和缩小功能,对热区坐标的处理请看下面第4点【图片缩放功能】

4.图片缩放功能

Element Plus的组件可通过 previewSrcList 开启预览大图功能可对图片进行放大缩小
image.png但是这个功能并没有提供方法进行其他操作,所以根据需求我放弃使用previewSrcList,重写了一个图片预览缩放功能。
image.png

4.1 遮罩层及图片缩放组件

通过对scaleVisible的控制来打开/关闭遮罩层和图片预览
是图片缩放组件的内容,将图片地址及人员信息传递过去
image.png
样式设置:
注意层级关系

// 遮罩层样式
.mask {
  // 相对于浏览器窗口进行定位,全屏遮住
  position: fixed; 
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background-color: #808080;
  opacity: 0.5;
  z-index: 8888;
}
// 遮罩层上的关闭按钮
.mask_close {
  position: fixed;
  right: 40px;
  top: 40px;
  width: 50px;
  height: 50px;
  cursor: pointer;
  z-index: 10000;
}
// 图片缩放组件
.pic_scale {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  z-index: 9999;
  display: flex;
  justify-content: center;
  align-items: center;
}
4.2 缩放工具栏

image.png

.flow-toolbar-wrap {
  position: absolute;
  bottom: 30px;
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: center;

  .flow-toolbar {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 10px;
    height: 40px;
    box-shadow: var(--el-box-shadow-light);
    background-color: #66686b;
    opacity: 0.8;
    border-radius: 20px;
    padding: 0 25px;
    z-index: 1;
    .toolbar-item {
      user-select: none;
      color: #fff;
      font-size: 20px;
      cursor: pointer;
    }
  }
}
4.4 计算缩放比
const state = reactive({
  areaMap: [] as PicInfo[],
  initAreaMap: [] as PicInfo[],
  scale: 1, // 图片缩放比例
  originWidth: 0,
  originHeight: 0,
});

// 放大操作
function toolbarZoomIn() {
  state.scale = Number((state.scale + 0.1).toFixed(1));
  applyZoom();
}
// 缩小操作
function toolbarZoomOut() {
  if (state.scale === 0.7) return;
  state.scale = Number((state.scale - 0.1).toFixed(1));
  applyZoom();
}
// 1.图片加载完成之后再去计算宽高,避免网络请求被延迟或阻塞导致尺寸无法获取。
function imgOnLoad() {
  ratioPic();
  state.originWidth = imageRef.value?.$el.clientWidth;
  state.originHeight = imageRef.value?.$el.clientHeight;
}
// 计算经过缩放后的宽高 
function applyZoom() {
  // 2.整体放大图片外层盒子和图片
  const divEl = document.querySelector('.scaleImage') as HTMLElement;
  divEl.style.transform = `scale(${state.scale})`;
  divEl.style.width = `${state.originWidth * state.scale}px`;
  divEl.style.height = `${state.originHeight * state.scale}px`;
  // 3.重新计算热区,同前面的3.2的操作
  ratioPic();
}

注意点:

  1. 要在图片加载完成之后再去计算宽高,避免网络请求被延迟或阻塞导致尺寸无法获取
  2. 放大/缩小时要整体放大/缩小外层盒子和图片
4.5鼠标滚动缩放
onMounted(async () => {
  // 添加鼠标滚动缩放
  const mapEl = document.querySelector('.scaleImage') as HTMLElement;
  mapEl.addEventListener('mousewheel', (e) => {
    if (e instanceof WheelEvent) {
      e.preventDefault(); // 阻止默认的滚轮行为,如页面滚动
      const delta = Math.sign(e.deltaY);
      // 根据滚动方向和步长调整缩放比例
      if (delta > 0) {
        toolbarZoomIn();
      } else {
        toolbarZoomOut();
      }
    }
  });
});
5.添加热区样式及信息框样式
5.1 热区样式

设置鼠标悬浮到热区范围内时的样式:两个圈的水波纹效果
image.png
样式:

:deep(.areaHighlight) {
  /* 设置高亮区域的背景颜色和透明度等样式 */
  pointer-events: none; /* 防止覆盖原始交互 */
  width: 50px;
  height: 50px;
  position: relative;
}

:deep(.areaHighlight)::before,
:deep(.areaHighlight)::after {
  position: absolute;
  content: '';
  width: 100%;
  height: 0;
  padding-bottom: 100%; /* 设置为宽度的百分比,实现宽高比为1:1 */
  top: 0;
  left: 0;
  background: #a5d7ff;
  border-radius: 50%;
  animation: animLoader 2s linear infinite;
}

:deep(.areaHighlight)::after {
  animation-delay: 1s;
  opacity: 0.1;
}
// 水波纹动画
@keyframes animLoader {
  0% {
    transform: scale(0);
    opacity: 1;
  }
  100% {
    transform: scale(1);
    opacity: 0;
  }
}

利用鼠标的移入和移出事件来添加样式
image.png

// 热区高亮
function highlightArea(area: any) {
  const overlay = document.createElement('div');
  overlay.style.position = 'absolute';
  // 根据area.shape和area.coords计算并设置overlay的位置和尺寸
  overlay.id = `overlay-${area.personCode}`;
  overlay.style.left = `${area.coordinate.x}px`;
  overlay.style.top = `${area.coordinate.y}px`;
  overlay.style.width = `${area.coordinate.width}px`;
  overlay.style.height = `${area.coordinate.height}px`;
  overlay.classList.add('areaHighlight');
  mapContainer.value?.appendChild(overlay);
}
// 移除高亮
function removeHighlight() {
  const overlayDiv = document.querySelectorAll('.areaHighlight');
  overlayDiv.forEach((item) => {
    mapContainer.value?.removeChild(item);
  });
}
5.2 信息框动画效果
.model_scale {
  display: none;
  position: absolute;
  width: 35%;
  min-width: 300px;
  max-width: 350px;
  border-radius: 10px;
  z-index: 2;
  color: #fff;
  border: 2px solid gold;
  border-radius: 10px;
  background: #ffd700;
  transition: all 0.3s;
}
// 边框动画
.model_scale::before {
  content: '';
  position: absolute;
  top: -10px;
  left: -10px;
  right: -10px;
  bottom: -10px;
  border: 2px solid #ffd700;
  border-radius: 10px;
  animation: borderAni 3s infinite linear;
}

.model_scale::after {
  content: '';
  position: absolute;
  top: -10px;
  left: -10px;
  right: -10px;
  bottom: -10px;
  border: 2px solid #ffd700;
  border-radius: 10px;
  animation: borderAni 3s infinite linear;
}

@keyframes borderAni {
  0%,
  100% {
    clip-path: inset(0 0 98% 0);
  }

  25% {
    clip-path: inset(0 98% 0 0);
  }
  50% {
    clip-path: inset(98% 0 0 0);
  }
  75% {
    clip-path: inset(0 0 0 98%);
  }
}

.model_scale::after {
  animation: borderAni 3s infinite -1.5s linear;
}
.model_close {
  position: absolute;
  top: -15px;
  right: -15px;
  width: 30px;
  height: 30px;
  cursor: pointer;
  z-index: 3;
}
.model_content {
  color: #000;
  font-size: 13px;
}

image.png

// 点击热区
function areaClick(area: any) {
  // 获取要展示的信息
  personnelInfo.forEach((item: InfoList) => {
    item.value = area[item.key] ?? '';
  });
  // 打开信息框,定位
  const modelEl = document.querySelector('.model_scale') as HTMLElement;
  modelEl.style.display = 'block';
  modelEl.style.left = area.coordinate.x + 100 + 'px';
  modelEl.style.top = area.coordinate.y + 50 + 'px';
}

// 关闭信息框
function closeModel() {
  const modelEl = document.querySelector('.model_scale') as HTMLElement;
  modelEl.style.display = 'none';
}

三、遇到的问题

1.无法正确获取图片到宽高时,值为0

问题描述: 在浏览器中,通过JavaScript获取图片(元素)的宽高属性时,在某些情况下可能会获取不到正确的值或者得到0

  1. 异步加载:浏览器加载网页时,HTML文档结构优先于外部资源(如图片、样式表和脚本)。当JavaScript代码执行时,如果图片尚未完全加载完成,则其naturalWidth或clientWidth等尺寸属性可能还未被浏览器填充,因此返回值为0。
  2. 事件监听不足:为了确保能够获取到图片的真实尺寸,应当在图片加载完成后触发一个事件处理函数,比如使用onload事件来确保图片已经加载完毕。
  3. 调试器影响:虽然不常见,但在极少数情况下,打开浏览器调试器并刷新页面可能导致渲染过程中的细微差别,这可能是由于强制重新布局(relayout)或重绘(repaint)引起的。如果你是在DOMContentLoaded或load事件触发之前就尝试获取图片尺寸,并且同时打开了调试器,那可能由于网络请求被延迟或阻塞导致尺寸无法获取。
  4. 缓存问题:有时候,特别是开发环境下,浏览器缓存可能导致实际图片未被重新加载,因此onload事件没有触发,尺寸信息也就无法更新。

此处我是遇到了第三个问题:打开调试器时无法正确获取图片宽高。

解决方法:确保在图片加载完成后才去读取其尺寸属性,或者是使用Promise或者async/await方式来等待图片加载完成。

使用load方法
image.png
在图片加载完成之后再去操作

// 图片加载完成之后再去计算宽高,避免网络请求被延迟或阻塞导致尺寸无法获取。
function imgOnLoad() {
  ratioPic();
  state.originWidth = imageRef.value?.$el.clientWidth;
  state.originHeight = imageRef.value?.$el.clientHeight;
}
2.图片在缩放时,外层div无法和图片一样大导致信息框等样式产生定位错误

如果在缩放时只控制图片的放大和缩小,缩放到一定程度时图片外层的div无法和图片的DOM元素一样大,且基于外层div进行定位的元素定位会产生误差

解决方法:
1.计算图片元素和外层div缩放产生的误差值,在计算坐标时加上误差值
2.缩放时直接对外层div进行缩放,需让图片和外层div保持一样的宽高

这里我选择了第二种方式

function applyZoom() {
  /*   const imgEl = imageRef.value?.$el.querySelector('img');
  imgEl.style.transform = `scale(${state.scale})`;
  imgEl.style.width = `${state.originWidth * state.scale}px`;
  imgEl.style.height = `${state.originHeight * state.scale}px`; */
  
  // 整体放大图片外层盒子和图片
  const divEl = document.querySelector('.scaleImage') as HTMLElement;
  divEl.style.transform = `scale(${state.scale})`;
  divEl.style.width = `${state.originWidth * state.scale}px`;
  divEl.style.height = `${state.originHeight * state.scale}px`;
  ratioPic();
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/366102.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【Algorithms 4】算法(第4版)学习笔记 03 - 1.3 背包、队列和栈

文章目录 前言参考目录学习笔记0&#xff1a;预热1&#xff1a;栈1.1&#xff1a;栈的链表实现1.1.1 代码实现1.2&#xff1a;栈的数组实现1.2.1&#xff1a;定容栈1.2.2&#xff1a;可调整大小数组1.2.3&#xff1a;代码实现1.3&#xff1a;链表与数组的取舍2&#xff1a;队列…

MySQL原理(一)架构组成之逻辑模块(1)组成

总的来说&#xff0c;MySQL可以看成是二层架构&#xff0c;第一层我们通常叫做SQL Layer&#xff0c;在MySQL数据库系统处理底层数据之前的所有工作都是在这一层完成的&#xff0c;包括权限判断&#xff0c;sql解析&#xff0c;执行计划优化&#xff0c;query cache的处理等等&…

算法——A/算法通识

目录 一、复杂度分析 A/时间复杂度 B/空间复杂度 C/分析技巧 二、枚举分析 A/枚举算法介绍 B/解空间的类型 C/循环枚举解空间 三、模拟算法 四、递归 A/递归介绍 递归的两个关键要素&#xff1a; B/递归如何实现 C/递归和循环的比较 一、复杂度分析 A/时间复杂度…

AVL树

文章目录 AVL树平衡因子 AVL树结点的定义AVL树类和函数接口AVL树插入元素最小不平衡子树旋转 AVL树的验证参考源码 AVL树是对普通二叉搜索树的一种优化。当二叉搜索树插入的元素是有序的时候或者接近有序的时候&#xff0c;二叉搜索树的性能会大大降低。二叉搜索树可能会变成一…

中二少年工具箱(PC端)简介

同学们可以私信我加入学习群&#xff01; 正文开始 简介一、功能模块1.node版本管理工具 总结 简介 中二少年开发的中二少年工具箱&#xff0c;相信博主&#xff0c;功能不孬。 辅助自己开发工作&#xff0c;帮助新人快速入门&#xff0c;提供交互式文档辅助学习……如果还不…

LDRA Testbed软件静态分析_Jenkins持续集成_(2)配置邮件自动发送静态分析结果

系列文章目录 LDRA Testbed软件静态分析_操作指南 LDRA Testbed软件静态分析_自动提取静态分析数据生成文档 LDRA Testbed软件静态分析_Jenkins持续集成_(1)自动进行静态分析的环境搭建 LDRA Testbed软件静态分析_Jenkins持续集成_(2)配置邮件自动发送静态分析结果 LDRA Testb…

arcgis自定义dem高程实现地形抬高 - 操作矢量,转tin、adf(tif),cesiumlab切高程服务

这次记录分享一下arcgis自定义高程全过程 /(ㄒoㄒ)/~~ 我的场景&#xff1a;前端实现地面抬高效果 自定义高程实现地形抬高 一、数据处理 - arcgis操作矢量1、准备工作&#xff08;可选&#xff09;2、绘制外围矢量&#xff08;可选&#xff09;3、操作矢量数据 二、创建tin - …

opencvb 十七 使用cmake配置opencv c++项目

1、cmake简介 1.1 cmake是什么 CMake是一个开源、跨平台的编译&#xff08;Build&#xff09;工具&#xff0c;是用来构建、测试和打包软件的。它能够用简单的语句来描述所有平台的编译过程。它能够输出各种各样的makefile或者project文件&#xff0c;能测试编译器所支持的C特…

记录一次k8s集群镜像恢复到harbor的过程

之前由于harbor的存储空间不够了&#xff0c;同事干掉了好多镜像&#xff0c;结果把现网生产的镜像也搞掉了。进行了找回操作&#xff0c;这里做下记录。 环境是k8s集群&#xff0c;容器引擎用的containerd。 最初发现这个问题是在增加节点的时候&#xff0c;发现有的节点主机…

【DPI(Direct Programming Interface)_2024.02.01】

DPI接口&#xff1a;实现SV与C的交互 ① DPI_svc test.sv文件&#xff1a; 从C import task/function到SV 从SV export task到C 利用DPI调用C code访问register test.c文件&#xff1a; C调用apb_write驱动 ② dpi_perl test.sv文件&#xff1a; 利用DPI调用c code间接调…

CKS1.28【1】kube-bench 修复不安全项

Context 针对 kubeadm 创建的 cluster 运行 CIS 基准测试工具时&#xff0c;发现了多个必须立即解决的问题。 Task 通过配置修复所有问题并重新启动受影响的组件以确保新的设置生效。 修复针对 API 服务器发现的所有以下违规行为&#xff1a; 1.2.7 Ensure that the --authoriz…

【华为】GRE Over IPsec 实验配置

【思科】GRE Over IPsec 实验配置 前言报文格式 实验需求配置拓扑GRE配置步骤IPsec 配置步骤R1基础配置GRE 配置IPsec 配置 ISP_R2基础配置 R3基础配置GRE 配置IPsec 配置 PCPC1PC2 抓包检查OSPF建立GRE隧道建立IPsec 隧道建立Ping 配置文档 前言 GRE over IPSec可利用GRE和IP…

echarts条形图添加滚动条

效果展示: 测试数据: taskList:[{majorDeptName:测试,finishCount:54,notFinishCount:21}, {majorDeptName:测试,finishCount:54,notFinishCount:21}, {majorDeptName:测试,finishCount:54,notFinishCount:21}, {majorDeptName:测试,finishCount:54,notFinishCount:21}, {maj…

关于JVM面试题汇总

JVM是如何运行的&#xff1f; JVM的执行流程如下&#xff1a; 程序再执行之前先要把Java代码转换成字节码&#xff08;class文件&#xff09;&#xff0c;JVM首先需要把字节码通过一定的方式类加载器&#xff08;ClassLoader&#xff09;把文件加载到内存中运行时数据区&…

Weblogic反序列化漏洞分析之CVE-2021-2394

目录 简介 前置知识 Serializable示例 Externalizable示例 联系weblogic ExternalizableLite接口 ExternalizableHelperl类 JdbcRowSetImpl类 MethodAttributeAccessor类 AbstractExtractor类 FilterExtractor类 TopNAggregator$PartialResult类 SortedBag$Wrappe…

【A题完整论文】2024美赛完整论文+代码参考(无偿分享)

A题&#xff1a;资源可用性和性别比例 一、问题分析 1.1 问题一分析 针对该问题&#xff0c;若七鳃鮼的性别比例受到外部环境因素的影响&#xff0c;那么这可能会导致种群大小和结构的变化。如果雌性在某些环境条件下更为优势&#xff0c;种群的增加可能对其他物种的竞争和资源…

【Python】一个简单的小案例:实现批量修改图片格式

1.代码 import os from tkinter import Tk, Button from PIL import Imagedef check_and_create_folders():# 获取当前目录current_directory os.getcwd()# 定义文件夹名称folders_to_check ["JPG", "PNG"]for folder_name in folders_to_check:folder_…

nvm-windows的安装和配置

下载安装nvm-setup.zip用于切换node版本&#xff0c;旧项目用的是14版本&#xff0c;vue3需要的node版本要高些,所以运行vue3项目前需要用nvm切换node的版本先。 下载安装好nvm-setup.zip后检查是否配置好如下信息&#xff1a; 之后在 PATH 变量中添加 %NVM_HOME% 和 %NVM_SYM…

2024年美赛 (B题MCM)| 潜水艇 |数学建模完整代码+建模过程全解全析

当大家面临着复杂的数学建模问题时&#xff0c;你是否曾经感到茫然无措&#xff1f;作为2022年美国大学生数学建模比赛的O奖得主&#xff0c;我为大家提供了一套优秀的解题思路&#xff0c;让你轻松应对各种难题。 让我们来看看美赛的B题&#xff01; 完整内容可以在文章末尾领…

找不到d3dcompiler_43.dll,无法继续执行代码的原因分析与解决方法

在运行某些软件或游戏时&#xff0c;可能会遇到系统提示找不到 d3dcompiler_43.dll 文件的情况。这个特定的动态链接库文件 (dll) 是 DirectX 3D 编译器组件的一部分&#xff0c;对于许多现代软件游戏的正常运行起着不可或缺的作用。它的主要功能在于将高级着色语言编写的代码转…