龙溪网站制作静态网站开发课程相关新闻

张小明 2026/1/12 13:32:53
龙溪网站制作,静态网站开发课程相关新闻,建个大型网站需,成都网站建设外包公司该图表支持弹框显示支持颜色随数值大小进行变化,定制特殊数据结构为单列数据渲染子组件templatediv classheatmap-container refcontainer!-- 热力图画布 --canvasrefheatmapCanvasclassheatmap-canvas…该图表支持弹框显示支持颜色随数值大小进行变化,定制特殊数据结构为单列数据渲染子组件template div classheatmap-container refcontainer !-- 热力图画布 -- canvas refheatmapCanvas classheatmap-canvas :widthcanvasWidth :heightcanvasHeight mousemovehandleMouseMove mouseleavehandleMouseLeave /canvas !-- 纵向颜色图例 -- div classheatmap-legend div classlegend-gradient reflegendGradient/div div classlegend-labels span{{ maxValue.toFixed(1) }}/span span{{ (maxValue / 2).toFixed(1) }}/span span{{ minValue.toFixed(1) }}/span /div /div !-- 鼠标悬浮弹框 -- div classtooltip v-ifshowTooltip :style{ left: ${tooltipPos.x 10}px, top: ${tooltipPos.y 10}px, } div classtooltip-content p时间{{ tooltipData.xValue.toFixed(2) }} {{ xAxisConfig.unit }}/p p倍频{{ tooltipData.yValue.toFixed(1) }}/p p{{ heatName }}{{ tooltipData.heatValue.toFixed(1) }}/p /div /div /div /template script export default { name: HighResHeatmap, // 接收父组件传入的数据 props: { // 父组件传入的热力图数据格式[列数,行数,列最小值,列最大值,行最小值,行最大值,备用,数值1,...] heatData: { type: Array, required: true, validator: (value) { if (!Array.isArray(value) || value.length 0) return false; const firstCol value[0]; return Array.isArray(firstCol) firstCol.length 8; }, }, heatName: { type: String, default: , }, canvasWidth: { type: Number, default: 1200 }, canvasHeight: { type: Number, default: 800 }, // 横坐标配置刻度数量/单位 xAxisConfig: { type: Object, default: () ({ tickCount: 8, min: 0, unit: s }), }, // 纵坐标配置刻度数量 yAxisConfig: { type: Object, default: () ({ tickCount: 11, min: 0 }), }, }, data() { return { config: { margin: { top: 50, right: 80, bottom: 60, left: 80 }, cellPadding: 0.5, colorRange: [ rgb(249.1095,250.8945,20.5275), rgb(253.4337,188.7056,61.1911), rgb(216.0053,189.7206,39.7772), rgb(163.0175,200.0451,62.5244), rgb(98.8091,204.7115,111.799), rgb(51.9092,198.87,155.5601), rgb(11.1036,188.9886,188.5222), rgb(21.0935,175.455,216.5337), rgb(37.1215,155.6805,231.2719), rgb(45.9746,132.7483,248.1123), rgb(65.8843,106.0061,253.9057), rgb(71.7245,80.5147,242.999), rgb(69.304,55.7722,215.3464), rgb(61.761,38.352,168.3765), ], axisColor: #fff, fontColor: #fff, }, minValue: 0, maxValue: 0, dataConfig: { colMax: 0, rowMax: 0 }, // 缓存colMax/rowMax // 弹框相关 showTooltip: false, tooltipPos: { x: 0, y: 0 }, tooltipData: { xValue: 0, yValue: 0, heatValue: 0 }, gridSize: null, // 缓存网格尺寸 parsedData: null, // 缓存解析后的数据 }; }, watch: { heatData: { deep: true, handler() { this.minValue 0; this.maxValue 0; this.dataConfig { colMax: 0, rowMax: 0 }; this.initHeatmap(); this.renderLegend(); }, }, canvasWidth() { this.initHeatmap(); }, canvasHeight() { this.initHeatmap(); }, xAxisConfig() { this.initHeatmap(); }, yAxisConfig() { this.initHeatmap(); }, }, mounted() { this.initHeatmap(); this.renderLegend(); window.addEventListener(resize, this.handleResize); }, beforeDestroy() { window.removeEventListener(resize, this.handleResize); }, methods: { handleResize() { this.canvasWidth Math.max( 800, document.querySelector(.heatmap-container)?.clientWidth || 1200 ); this.canvasHeight Math.max( 600, document.querySelector(.heatmap-container)?.clientHeight || 800 ); }, initHeatmap() { const canvas this.$refs.heatmapCanvas; if (!canvas) return; const ctx canvas.getContext(2d); if (!ctx) return; ctx.clearRect(0, 0, this.canvasWidth, this.canvasHeight); this.parsedData this.parseHeatData(); // 缓存解析后的数据 if (!this.parsedData.length) return; this.gridSize this.calcGridSize(this.parsedData); // 缓存网格尺寸 this.drawAxis(ctx, this.parsedData, this.gridSize); this.drawHeatGrid(ctx, this.parsedData, this.gridSize); }, parseHeatData() { return this.heatData.map((col) { // 提取配置项修正col对应X轴row对应Y轴 const config { colCount: parseInt(col[0]) || 1, // X轴列数 rowCount: parseInt(col[1]) || 512, // Y轴行数 rowMin: parseFloat(col[2]) || 0, // Y轴最小值 rowMax: parseFloat(col[3]) || 0, // Y轴最大值 colMin: parseFloat(col[4]) || 0, // X轴最小值 colMax: parseFloat(col[5]) || 0, // X轴最大值 reserve: parseFloat(col[6]) || 0, }; // 缓存全局配置仅第一次解析 if (this.dataConfig.colMax 0) { this.dataConfig.colMax config.colMax; this.dataConfig.rowMax config.rowMax; } // 提取数值 const values col .slice(7) .map((val) { const num parseFloat(val); return isNaN(num) ? 0 : num; }) .slice(0, config.rowCount); // 更新数值范围 this.minValue Math.min(this.minValue, ...values); this.maxValue Math.max(this.maxValue, ...values); return { ...config, values }; }); }, calcGridSize(parsedData) { // 有效绘制区域 const drawWidth this.canvasWidth - this.config.margin.left - this.config.margin.right; const drawHeight this.canvasHeight - this.config.margin.top - this.config.margin.bottom; const firstCol parsedData[0] || {}; const totalCols firstCol.colCount || 1; // X轴列数 const totalRows firstCol.rowCount || 512; // Y轴行数 // 核心修正X轴colMaxY轴rowMax const xMin this.xAxisConfig.min; const xMax this.dataConfig.colMax || 1; // X轴最大值colMax const yMin this.yAxisConfig.min; const yMax this.dataConfig.rowMax || 1; // Y轴最大值rowMax // 单元格尺寸修正X轴按列数分Y轴按行数分 const cellWidth drawWidth / totalCols; // X轴单元格宽度 const cellHeight drawHeight / totalRows; // Y轴单元格高度 // 坐标映射比例修正方向 const xScale drawWidth / (xMax - xMin); // X轴像素/数值比例 const yScale drawHeight / (yMax - yMin); // Y轴像素/数值比例 return { drawWidth, drawHeight, totalCols, totalRows, cellWidth, cellHeight, // X轴参数colMax xMin, xMax, xScale, xTickCount: this.xAxisConfig.tickCount, xUnit: this.xAxisConfig.unit, // Y轴参数rowMax yMin, yMax, yScale, yTickCount: this.yAxisConfig.tickCount, }; }, /** * 绘制坐标轴核心修正X轴colMaxY轴rowMax方向正确 */ drawAxis(ctx, parsedData, gridSize) { const { margin, axisColor, fontColor } this.config; const { // X轴参数colMax xMin, xMax, xScale, xTickCount, xUnit, // Y轴参数rowMax yMin, yMax, yScale, yTickCount, drawWidth, drawHeight, } gridSize; // 绘制X轴水平轴对应colMax从左到右xMin→xMax ctx.beginPath(); ctx.moveTo(margin.left, this.canvasHeight - margin.bottom); // X轴起点左下 ctx.lineTo(margin.left drawWidth, this.canvasHeight - margin.bottom); // X轴终点右下 ctx.strokeStyle axisColor; ctx.lineWidth 1; ctx.stroke(); // X轴刻度修正均匀分布从左到右对应xMin→xMax const xTickStep (xMax - xMin) / (xTickCount - 1); for (let i 0; i xTickCount; i) { // 刻度X坐标画布像素 const xPos margin.left i * (drawWidth / (xTickCount - 1)); // 刻度数值xMin → xMax const xValue xMin (i * xTickStep) / 1000000; // 绘制刻度线向下 ctx.beginPath(); ctx.moveTo(xPos, this.canvasHeight - margin.bottom); ctx.lineTo(xPos, this.canvasHeight - margin.bottom 8); ctx.strokeStyle axisColor; ctx.stroke(); // 绘制刻度标签 ctx.fillStyle fontColor; ctx.font 11px Arial; ctx.textAlign center; ctx.textBaseline top; ctx.fillText( ${xValue.toFixed(1)} ${xUnit}, xPos, this.canvasHeight - margin.bottom 10 ); } // 绘制Y轴垂直轴对应rowMax从下到上yMin→yMax ctx.beginPath(); ctx.moveTo(margin.left, this.canvasHeight - margin.bottom); // Y轴起点左下 ctx.lineTo(margin.left, margin.top); // Y轴终点左上 ctx.strokeStyle axisColor; ctx.lineWidth 1; ctx.stroke(); // Y轴刻度修正从下到上对应yMin→yMax const yTickStep (yMax - yMin) / (yTickCount - 1); for (let i 0; i yTickCount; i) { // 刻度Y坐标画布像素从下到上 const yPos this.canvasHeight - margin.bottom - i * (drawHeight / (yTickCount - 1)); // 刻度数值yMin → yMax const yValue yMin i * yTickStep; // 绘制刻度线向左 ctx.beginPath(); ctx.moveTo(margin.left - 5, yPos); ctx.lineTo(margin.left, yPos); ctx.strokeStyle axisColor; ctx.stroke(); // 绘制刻度标签 ctx.fillStyle fontColor; ctx.font 11px Arial; ctx.textAlign right; ctx.textBaseline middle; ctx.fillText(yValue.toFixed(1), margin.left - 8, yPos); } // 坐标轴标题修正对应关系 ctx.fillStyle fontColor; ctx.font 14px Arial; ctx.textAlign center; // X轴标题colMax ctx.fillText( 时间 (${xMin.toFixed(1)} - ${xMax.toFixed(1)} μs), margin.left drawWidth / 2, this.canvasHeight - 15 ); // Y轴标题rowMax ctx.save(); ctx.translate(30, margin.top drawHeight / 2); ctx.rotate(-Math.PI / 2); ctx.fillText(倍频 (${yMin.toFixed(1)} - ${yMax.toFixed(1)}), 0, 0); ctx.restore(); }, /** * 绘制热力网格修正X/Y轴映射 */ drawHeatGrid(ctx, parsedData, gridSize) { const { margin, fontColor } this.config; const { cellWidth, cellHeight, totalCols, totalRows, xMin, xMax, xScale, yMin, yMax, yScale, } gridSize; const colData parsedData[0] || {}; const values colData.values || []; // 遍历所有行Y轴和列X轴 for (let colIndex 0; colIndex totalCols; colIndex) { // X轴列 for (let rowIndex 0; rowIndex totalRows; rowIndex) { // Y轴行 // 核心修正单元格位置计算 // X坐标基于colIndexX轴 const cellX margin.left colIndex * cellWidth this.config.cellPadding; // Y坐标基于rowIndexY轴从下到上 const cellY this.canvasHeight - margin.bottom - (rowIndex 1) * cellHeight this.config.cellPadding; // 单元格尺寸 const drawWidth cellWidth - 2 * this.config.cellPadding; const drawHeight Math.max( 0.5, cellHeight - 2 * this.config.cellPadding ); // 获取当前数值 const value values[rowIndex] || 0; // 绘制单元格 ctx.fillStyle this.getHeatColor(value); ctx.fillRect(cellX, cellY, drawWidth, drawHeight); // 显示数值仅单元格足够大时 if (cellHeight 1.5 cellWidth 8) { ctx.fillStyle value this.maxValue / 4 ? fontColor : #000; ctx.font 8px Arial; ctx.textAlign center; ctx.textBaseline middle; ctx.fillText( value.toFixed(1), cellX drawWidth / 2, cellY drawHeight / 2 ); } } } }, getHeatColor(value) { if (this.maxValue this.minValue) return this.config.colorRange[0]; const gamma 0.2; const normalized Math.pow( (value - this.minValue) / (this.maxValue - this.minValue), gamma ); const colorIndex Math.min( Math.floor(normalized * this.config.colorRange.length), this.config.colorRange.length - 1 ); return this.config.colorRange[colorIndex]; }, /** * 修正渲染纵向颜色图例 */ renderLegend() { const legendEl this.$refs.legendGradient; if (!legendEl) return; // 改为纵向渐变top to bottom颜色顺序反转以匹配数值从大到小 const gradient linear-gradient(to bottom, ${this.config.colorRange .reverse() .join(, )}); legendEl.style.background gradient; // 恢复颜色数组顺序避免影响热力图绘制 this.config.colorRange.reverse(); }, /** * 处理鼠标移动事件 - 显示弹框 */ handleMouseMove(e) { if (!this.gridSize || !this.parsedData.length) return; // 获取画布相对容器的位置 const canvas this.$refs.heatmapCanvas; const rect canvas.getBoundingClientRect(); const containerRect this.$refs.container.getBoundingClientRect(); // 计算鼠标在画布内的相对坐标 const mouseX e.clientX - rect.left; const mouseY e.clientY - rect.top; // 校验鼠标是否在绘制区域内修复边界判断 const { margin } this.config; const { drawWidth, drawHeight } this.gridSize; const drawAreaX1 margin.left - 5; // 左边界容差 const drawAreaX2 margin.left drawWidth 5; // 右边界容差 const drawAreaY1 margin.top - 5; // 上边界容差 const drawAreaY2 this.canvasHeight - margin.bottom 5; // 下边界容差 if ( mouseX drawAreaX1 || mouseX drawAreaX2 || mouseY drawAreaY1 || mouseY drawAreaY2 ) { this.showTooltip false; return; } // 计算当前坐标对应的数值 const { xMin, xMax, yMin, yMax, cellWidth, cellHeight, totalRows } this.gridSize; // X轴数值时间- 限制比例在0~1之间避免越界 const xRatio Math.max( 0, Math.min(1, (mouseX - margin.left) / drawWidth) ); const xValue xMin xRatio * (xMax - xMin); // 转换为秒微秒→秒 const xValueSec xValue / 1000000; // Y轴数值倍频- 限制比例在0~1之间 const yPixelFromBottom this.canvasHeight - margin.bottom - mouseY; const yRatio Math.max(0, Math.min(1, yPixelFromBottom / drawHeight)); const yValue yMin yRatio * (yMax - yMin); // 计算当前单元格索引获取热力值 const rowIndex Math.floor((mouseY - margin.top) / cellHeight); const clampRowIndex Math.max(0, Math.min(totalRows - 1, rowIndex)); const heatValue this.parsedData[0]?.values[clampRowIndex] || 0; // 更新弹框数据和位置 this.tooltipPos { x: e.clientX - containerRect.left, y: e.clientY - containerRect.top, }; this.tooltipData { xValue: xValueSec, yValue: yValue, heatValue: heatValue, }; this.showTooltip true; }, /** * 处理鼠标离开事件 - 隐藏弹框 */ handleMouseLeave() { this.showTooltip false; }, }, }; /script style scoped .heatmap-container { width: 100%; height: 100%; min-height: 600px; position: relative; padding-right: 80px; box-sizing: border-box; /* 允许弹框超出容器显示 */ overflow: visible; } .heatmap-canvas { display: block; width: 100%; height: 100%; cursor: crosshair; /* 十字光标提升体验 */ } /* 纵向图例样式 */ .heatmap-legend { position: absolute; top: 50%; right: 60px; transform: translateY(-50%); width: 20px; height: 300px; display: flex; align-items: center; } /* 纵向渐变颜色块 */ .legend-gradient { width: 100%; height: 80%; border-radius: 10px; } /* 图例标签 - 适配纵向布局 */ .legend-labels { display: flex; flex-direction: column; justify-content: space-between; height: 80%; position: absolute; top: 10%; left: 25px; font-size: 10px; color: #fff; /* 调整文字颜色适配浅色背景 */ line-height: 1; } /* 弹框样式 */ .tooltip { position: absolute; z-index: 1000; background: rgba(0, 0, 0, 0.85); border: 1px solid #444; border-radius: 4px; padding: 8px 12px; color: #fff; font-size: 12px; pointer-events: none; /* 避免弹框遮挡鼠标事件 */ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3); transition: opacity 0.2s ease; /* 防止弹框被截断 */ white-space: nowrap; } .tooltip-content p { margin: 0; line-height: 1.4; } /* 修复最右侧弹框位置 */ .tooltip { transform: translateZ(0); /* 硬件加速避免闪烁 */ } /style父组件调用pieBar :chartIdpqd_chart :heatDataDSFLYList :heatNameheatName /数据结构示例data: [ // 每个数组代表一列 [ 4, //矩阵行数 0, //纵坐标下限 5, //纵坐标上限 0, //横坐标最小值 6, //横坐标最大值 1, // 自上向下排列 这个对应纵坐标的最大值 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, ], [ 4, //矩阵行数 0, //纵坐标下限 5, //纵坐标上限 0, //横坐标最小值 9, //横坐标最大值 6,// 自上向下排列 这个对应纵坐标的最大值 ,值的大小控制颜色的深浅度 6, 2, 1, 5, 6, 7, 8, 9, 9, 11, 12, ], ],效果图
版权声明:本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!

中国网站建设网我的qq中心网页版

苦熬三个月没能秋招上岸!只怪我技术太菜!春招必靠它成功上岸!阿里Java面试题真的太牛了!作为一名计算机专业的应届生,我在今年秋招期间投递了30家公司,参加了15场笔试和8场面试,最终却颗粒无收。…

张小明 2025/12/31 1:08:21 网站建设

织梦网站还原电商网站用什么框架做

第一章:Open-AutoGLM 弹窗识别遗漏问题概述在自动化测试与智能UI交互场景中,Open-AutoGLM作为基于大语言模型的图形界面理解系统,承担着关键的弹窗检测与响应任务。然而,在实际运行过程中,系统偶现对特定类型弹窗的识别…

张小明 2025/12/31 1:08:23 网站建设

微信上怎么做网站链接wordpress禁止图片压缩插件

Excalidraw:产品经理的“数字草稿纸”如何重塑PRD原型创作 在一次跨部门需求评审会上,产品负责人刚讲完一个复杂的用户旅程逻辑,技术主管皱眉:“这段流程文字描述太抽象了,我需要看图。” 会议室陷入短暂沉默——没人想…

张小明 2025/12/31 1:08:23 网站建设

网站服务公司名称西宁网站优化

飞驰星辰发布SpeedAI:以超99%精度引领全球AI检测,获美国竞品官网承认国内AI安全领域迎来里程碑式突破。由北京航空航天大学顶尖计算机博士、硕士团队创立的飞驰星辰公司,今日正式公布其研发的AI生成内容检测产品——SpeedAI。该产品凭借其卓越…

张小明 2025/12/31 1:08:24 网站建设

网站设计文稿开网站需要多少钱

周五下午,老板突然要求周一晨会必须有一份“视觉出彩”的周报PPT;或是活动提前,急需一张能在社群刷屏的预热海报——这种让人心头一紧的紧急任务,你是否也经历过?在时间紧迫、预算有限的双重压力下,寻找合适…

张小明 2026/1/5 21:04:01 网站建设

Html5做旅游网站的设计思路汕头网站建设方案维护

Xray编辑器启动性能优化终极指南:架构深度解析与实战技巧 【免费下载链接】xray An experimental next-generation Electron-based text editor 项目地址: https://gitcode.com/gh_mirrors/xray/xray 想要让你的Xray编辑器启动速度实现质的飞跃吗&#xff1f…

张小明 2026/1/9 18:57:53 网站建设