可视化图表与源代码显示配置项及页面的动态调整功能分析

可视化图表与源代码显示配置项及页面的动态调整功能分析

文章目录

  • 可视化图表与源代码显示配置项及页面的动态调整功能分析
      • 1.分析图表源代码
      • 2.分析源代码显示功能
        • **完整代码参考:**
      • 3.分析源代码显示及动态调整
        • **完整代码参考:**
      • 4.分析代码编辑器及运行效果显示
        • **完整代码参考:**

继 “可视化图表与源代码显示的动态调整” 文章后的功能更新及功能代码分析

功能展示如下:

1.分析图表源代码

首先我们先看一下在ECharts下载的图表示例中拿取到的源代码,我对其进行了详细的注释

<!DOCTYPE html>  
<html lang="en" style="height: 100%"> <!-- 设置html元素的高度为100%,以便其子元素可以继承并使用百分比高度 -->  
<head>  <meta charset="utf-8"> <!-- 设置文档的字符编码为UTF-8 -->  
</head>  
<body style="height: 100%; margin: 0"> <!-- 设置body的高度为100%,并移除默认的边距 -->  <div id="container" style="height: 100%"></div> <!-- 创建一个div元素,用于容纳ECharts图表,并设置其高度为100% -->  <!-- 引入ECharts的JavaScript库 -->  <script type="text/javascript" src="https://registry.npmmirror.com/echarts/5.5.1/files/dist/echarts.min.js"></script>  <script type="text/javascript">  var dom = document.getElementById('container'); // 获取用于容纳ECharts图表的div元素  var myChart = echarts.init(dom, null, { // 初始化ECharts实例  renderer: 'canvas', // 设置渲染器为canvas  useDirtyRect: false // 关闭脏矩形渲染优化  });  var app = {}; // 这里的代码没有什么作用  var option; // 声明一个变量用于存储图表的配置项  // 定义图表的配置项  option = {  xAxis: { // X轴配置  type: 'category', // 设置X轴类型为类目轴  data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'] // 设置X轴数据  },  yAxis: { // Y轴配置  type: 'value' // 设置Y轴类型为数值轴  },  series: [ // 系列列表配置  {  data: [120, 200, 150, 80, 70, 110, 130], // 设置系列中的数据  type: 'line', // 设置系列类型为折线图  symbol: 'triangle', // 设置系列中数据点的标记形状为三角形  symbolSize: 20, // 设置数据点标记的大小  lineStyle: { // 设置线条的样式  color: '#5470C6', // 设置线条颜色  width: 4, // 设置线条宽度  type: 'dashed' // 设置线条类型为虚线  },  itemStyle: { // 设置数据点标记的样式  borderWidth: 3, // 设置标记边框的宽度  borderColor: '#EE6666', // 设置标记边框的颜色  color: 'yellow' // 设置标记的填充颜色  }  }  ]  };  // 如果存在配置项且配置项是一个对象,则使用配置项初始化图表  if (option && typeof option === 'object') {  myChart.setOption(option);  }  // 监听窗口大小变化事件,以便在窗口大小变化时更新图表大小  window.addEventListener('resize', myChart.resize);  </script>  
</body>  
</html>

它的运行效果图是这样的:
在这里插入图片描述

2.分析源代码显示功能

在图表显示的基础上,我增添了对图表源代码的显示

源代码显示功能主要依赖于以下几个技术功能点

  1. 使用document.documentElement.outerHTML这个 JavaScript 表达式获取到当前页面的完整HTML源代码;将这个源代码字符串设置为#source-code元素的textContent属性,这样就会在页面上显示出来。

以下是实现源代码显示功能的代码及解析:

<!-- 显示HTML源码 -->
<pre id="source-code"></pre> 
// 设置源代码显示
document.getElementById('source-code').textContent=document.documentElement.outerHTML;
  1. 用户可以通过点击“下载”按钮,触发downloadSource()函数,将源代码保存为一个HTML文件。这个函数创建了一个Blob对象,并将其URL设置为一个<a>标签的href属性,然后模拟点击这个标签以下载文件

以下是实现源代码下载功能的代码及解析:

<!-- 下载按钮 -->
<button id="downloadButton" onclick="downloadSourceCode()">下载</button>
// 定义一个名为downloadSourceCode的函数,用于下载当前页面的源代码  
function downloadSourceCode() {  // 创建一个新的<a>元素,用于模拟点击下载  var element = document.createElement('a');  // 设置<a>元素的href属性,设置其href属性为一个包含当前页面HTML源代码的data URL// data URL的格式为:data:[<mediatype>][;base64],<data>  // 这里mediatype是text/plain,charset设置为utf-8,data是当前页面的outerHTML,经过encodeURIComponent编码  element.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(document.documentElement.outerHTML));  // 设置<a>元素的download属性,指定下载文件的名称  element.setAttribute('download', '折线图.html');  // 设置<a>元素的display样式为none,使其在页面上不可见  element.style.display = 'none';  // 将<a>元素添加到文档的body中  document.body.appendChild(element);  // 模拟点击<a>元素,触发下载  element.click();  // 从文档的body中移除<a>元素  document.body.removeChild(element);  
}
完整代码参考:
<!DOCTYPE html>
<html lang="en" style="height: 100%"> <!-- 设置html元素的高度为100%,以便其子元素可以继承并使用百分比高度 -->
<head><meta charset="utf-8"> <!-- 设置文档的字符编码为UTF-8 --><style>body {display: flex; /* 使用Flexbox布局 */height: 100%; /* 设置body的高度为100% */margin: 0; /* 移除body的默认边距 */}#container{flex: 1; /* 分配相等的空间给容器 */height: 100%; /* 设置容器的高度为100% */}#source-container {background-color: rgba(111, 231, 35, 0.36); /* 设置背景色以便区分 */padding: 20px; /* 设置内边距 */overflow: auto; /* 设置溢出内容为自动滚动 */flex: 1; /* 分配相等的空间给容器 */}#downloadButton {padding: 10px 20px; /* 设置按钮的内边距 */background-color: #007bff; /* 设置按钮的背景色 */color: #1ed5cf; /* 设置按钮的文字颜色 */border: none; /* 移除按钮的边框 */border-radius: 5px; /* 设置按钮的边框圆角 */cursor: pointer; /* 设置鼠标悬停时的光标样式为指针 */font-size: 16px; /* 设置按钮的文字大小 */position: absolute; /* 设置按钮的定位方式为绝对定位 */top: 20px; /* 设置按钮距离容器顶部的距离 */right: 20px; /* 设置按钮距离容器右侧的距离 */z-index: 1000; /* 设置按钮的堆叠顺序 */}</style>
</head>
<body style="height: 100%; margin: 0"> <!-- 设置body的高度为100%,并移除默认的边距 --><div id="container" style="height: 100%"></div> <!-- 创建一个div元素,用于容纳ECharts图表,并设置其高度为100% --><div id="source-container"><pre id="source-code"></pre> <!-- 创建一个pre元素,用于显示页面的HTML源代码 --><button id="downloadButton" onclick="downloadSourceCode()">下载</button> <!-- 创建一个按钮,点击时调用downloadSourceCode函数下载页面源代码 --></div><!-- 引入ECharts的JavaScript库 --><script type="text/javascript" src="https://registry.npmmirror.com/echarts/5.5.1/files/dist/echarts.min.js"></script><script type="text/javascript">var dom = document.getElementById('container'); // 获取用于容纳ECharts图表的div元素var myChart = echarts.init(dom, null, { // 初始化ECharts实例renderer: 'canvas', // 设置渲染器为canvasuseDirtyRect: false // 关闭脏矩形渲染优化});var option; // 声明一个变量用于存储图表的配置项// 定义图表的配置项option = {xAxis: { // X轴配置type: 'category', // 设置X轴类型为类目轴data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'] // 设置X轴数据},yAxis: { // Y轴配置type: 'value' // 设置Y轴类型为数值轴},series: [ // 系列列表配置{data: [120, 200, 150, 80, 70, 110, 130], // 设置系列中的数据type: 'line', // 设置系列类型为折线图symbol: 'triangle', // 设置系列中数据点的标记形状为三角形symbolSize: 20, // 设置数据点标记的大小lineStyle: { // 设置线条的样式color: '#5470C6', // 设置线条颜色width: 4, // 设置线条宽度type: 'dashed' // 设置线条类型为虚线},itemStyle: { // 设置数据点标记的样式borderWidth: 3, // 设置标记边框的宽度borderColor: '#EE6666', // 设置标记边框的颜色color: 'yellow' // 设置标记的填充颜色}}]};// 如果存在配置项且配置项是一个对象,则使用配置项初始化图表if (option && typeof option === 'object') {myChart.setOption(option);}// 监听窗口大小变化事件,以便在窗口大小变化时更新图表大小window.addEventListener('resize', myChart.resize);// 设置源代码显示document.getElementById('source-code').textContent = document.documentElement.outerHTML;// 下载源代码功能function downloadSourceCode() {var element = document.createElement('a'); // 创建一个a元素element.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(document.documentElement.outerHTML)); // 设置href属性为包含页面HTML源代码的data URLelement.setAttribute('download', '折线图.html'); // 设置下载文件的名称element.style.display = 'none'; // 设置a元素不可见document.body.appendChild(element); // 将a元素添加到文档中element.click(); // 模拟点击a元素以下载文件document.body.removeChild(element); // 从文档中移除a元素}</script>
</body>
</html>

它的运行效果图是这样的:
在这里插入图片描述

3.分析源代码显示及动态调整

在源代码显示的基础上,为了更加方便显示数据量过多的图表,我对右页面的代码显示区域进行了可动态式调整对图表显示区域进行覆盖的功能

右侧代码显示区域的动态化调整主要依赖于以下几个技术功能点:

  1. Flex布局#main-container 使用了Flex布局,这使得其子元素(#chart-container#source-container)能够灵活地分配空间。

以下是实现Flex布局的代码及解析:

   <div id="main-container"><div id="chart-container"><div id="container" style="height: 100%;"></div> <!-- ECharts图表容器 --><div id="splitter"></div> <!-- 分割线,用于拖动调整大小 --></div><div id="source-container"><pre id="source-code"></pre> <!-- 显示HTML源码 --><button id="downloadButton" onclick="downloadSourceCode()">下载</button> <!-- 下载按钮 --></div></div>
/* 主容器,使用flex布局,占据剩余空间 */  
#main-container {  display: flex; /* 设置为flex布局 */  flex: 1; /* flex属性设置为1,表示该元素将占据剩余的全部空间 */  overflow: hidden; /* 当内容溢出容器时,隐藏溢出的内容 */  
}  /* 图表容器,初始时占据全部剩余空间 */  
#chart-container {  flex: 1; /* flex属性设置为1,表示该元素将占据其父元素中的剩余空间 */  height: 100%; /* 高度设置为100%,使其充满父容器的高度 */  overflow: hidden; /* 当内容溢出容器时,隐藏溢出的内容 */  position: relative; /* 设置定位方式为相对定位,便于内部元素的绝对定位 */  
}  /* 数据源容器,初始时不占据空间,根据需要调整 */  
#source-container {  flex: 0; /* flex属性设置为0,表示该元素初始时不占据空间 */  background-color: rgba(111, 231, 35, 0.36); /* 设置背景颜色,使用rgba表示半透明 */  padding: 30px; /* 设置内边距为30px */  overflow: auto; /* 当内容溢出容器时,显示滚动条 */  
}
  1. 拖动事件监听:通过监听mousedownmousemovemouseup事件,实现了拖动分割线(#splitter)来调整#chart-container#source-container的大小。

以下是实现分割线的拖动的代码及解析:

/* 分割线,用于调整#chart-container和#source-container的大小 */  
#splitter {  background-color: #ccc; /* 设置分割线的背景颜色为灰色 */  cursor: ew-resize; /* 设置鼠标悬停在分割线上时的光标样式为东西向调整大小 */  width: 5px; /* 设置分割线的宽度为5像素 */  position: absolute; /* 设置分割线的定位方式为绝对定位,便于控制其位置 */  right: 0; /* 设置分割线距离其父容器右边的距离为0,即贴紧父容器的右边 */  top: 0; /* 设置分割线距离其父容器顶部的距离为0,即贴紧父容器的顶部 */  bottom: 0; /* 设置分割线距离其父容器底部的距离为0,即分割线的高度会撑满父容器的高度 */  z-index: 1; /* 设置分割线的层叠顺序为1,确保它位于其他内容之上 */  
}
  1. 动态计算宽度:在拖动过程中,动态计算#chart-container的新宽度,并相应地更新其flex属性以及#source-containerflex属性,以实现两部分的宽度调整。

以下是实现动态调整的代码及解析:

// 分割线拖动调整大小的逻辑  
let startX, startWidth, isResizing = false;  // 初始化变量,startX记录鼠标按下时的X坐标,startWidth记录#chart-container的初始宽度,isResizing表示是否正在调整大小  document.getElementById('splitter').addEventListener('mousedown', function(e) {  // 为分割线添加mousedown事件监听器  isResizing = true;  // 设置正在调整大小的状态为true  startX = e.clientX; // 记录鼠标按下时的X坐标  startWidth = document.getElementById('chart-container').offsetWidth; // 记录当前#chart-container的宽度  document.addEventListener('mousemove', onMouseMove);  // 为document添加mousemove事件监听器,以便在鼠标移动时调整大小  document.addEventListener('mouseup', onMouseUp);  // 为document添加mouseup事件监听器,以便在鼠标松开时停止调整大小  document.addEventListener('mouseleave', onMouseUp);  // 为document添加mouseleave事件监听器,以便在鼠标离开时停止调整大小  
});  /* 拖动时调整大小的逻辑 */  
function onMouseMove(e) {  // 定义鼠标移动时的处理函数  if (!isResizing) return;  // 如果不是正在调整大小,则直接返回  let newWidth = startWidth + (e.clientX - startX); // 计算新的宽度  newWidth = Math.max(100, Math.min(document.getElementById('main-container').offsetWidth - 5, newWidth)); // 限制新宽度的范围,不小于100,不大于主容器宽度减5  document.getElementById('chart-container').style.flex = `${newWidth / document.getElementById('main-container').offsetWidth * 100}%`; // 更新#chart-container的flex属性  document.getElementById('source-container').style.flex = `calc(100% - ${newWidth}px)`; // 更新#source-container的flex属性,使其占据剩余空间  
}  /* 停止拖动时的清理逻辑 */  
function onMouseUp() {  // 定义鼠标松开或离开时的处理函数  isResizing = false;  // 设置正在调整大小的状态为false  document.removeEventListener('mousemove', onMouseMove);  // 移除mousemove事件监听器  document.removeEventListener('mouseup', onMouseUp);  // 移除mouseup事件监听器  document.removeEventListener('mouseleave', onMouseUp);  // 移除mouseleave事件监听器  
}
完整代码参考:
<!DOCTYPE html>
<html lang="en" style="height: 100%"> <!-- 设置html元素的高度为100%,以便其子元素可以继承并使用百分比高度 -->
<head><meta charset="utf-8"> <!-- 设置文档的字符编码为UTF-8 --><style>/* 设置html和body元素高度为100%,并启用flex布局 */body, html {height: 100%;margin: 0;display: flex;flex-direction: column;}/* 主容器,flex布局,占据剩余空间 */#main-container {display: flex;flex: 1; /* 占据剩余空间 */overflow: hidden;}/* 图表容器,初始时占据全部剩余空间 */#chart-container {flex: 1;height: 100%;overflow: hidden;position: relative;}#source-container {flex: 0; /* 初始时不占据空间,根据需要调整 */background-color: rgba(111, 231, 35, 0.36);padding: 30px;overflow: auto;}/* 分割线,用于调整#chart-container和#source-container的大小 */#splitter {background-color: #ccc;cursor: ew-resize;width: 5px;position: absolute;right: 0;top: 0;bottom: 0;z-index: 1;}/* 下载按钮样式 */#downloadButton {padding: 10px 20px;background-color: #007bff;color: #1ed5cf;border: none;border-radius: 5px;cursor: pointer;font-size: 16px;position: absolute;top: 20px;right: 20px;z-index: 1000;}</style>
</head>
<body style="height: 100%; margin: 0"> <!-- 设置body的高度为100%,并移除默认的边距 --><div id="main-container"><div id="chart-container"><div id="container" style="height: 100%;"></div> <!-- ECharts图表容器 --><div id="splitter"></div> <!-- 分割线,用于拖动调整大小 --></div><div id="source-container"><pre id="source-code"></pre> <!-- 显示HTML源码 --><button id="downloadButton" onclick="downloadSourceCode()">下载</button> <!-- 下载按钮 --></div></div><!-- 引入ECharts的JavaScript库 --><script type="text/javascript" src="https://registry.npmmirror.com/echarts/5.5.1/files/dist/echarts.min.js"></script><script type="text/javascript">var dom = document.getElementById('container'); // 获取用于容纳ECharts图表的div元素var myChart = echarts.init(dom, null, { // 初始化ECharts实例renderer: 'canvas', // 设置渲染器为canvasuseDirtyRect: false // 关闭脏矩形渲染优化});var option; // 声明一个变量用于存储图表的配置项// 定义图表的配置项option = {xAxis: { // X轴配置type: 'category', // 设置X轴类型为类目轴data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'] // 设置X轴数据},yAxis: { // Y轴配置type: 'value' // 设置Y轴类型为数值轴},series: [ // 系列列表配置{data: [120, 200, 150, 80, 70, 110, 130], // 设置系列中的数据type: 'line', // 设置系列类型为折线图symbol: 'triangle', // 设置系列中数据点的标记形状为三角形symbolSize: 20, // 设置数据点标记的大小lineStyle: { // 设置线条的样式color: '#5470C6', // 设置线条颜色width: 4, // 设置线条宽度type: 'dashed' // 设置线条类型为虚线},itemStyle: { // 设置数据点标记的样式borderWidth: 3, // 设置标记边框的宽度borderColor: '#EE6666', // 设置标记边框的颜色color: 'yellow' // 设置标记的填充颜色}}]};// 如果存在配置项且配置项是一个对象,则使用配置项初始化图表if (option && typeof option === 'object') {myChart.setOption(option);}// 监听窗口大小变化以调整图表大小window.addEventListener('resize', myChart.resize);// 设置源代码显示document.getElementById('source-code').textContent = document.documentElement.outerHTML;// 分割线拖动调整大小的逻辑let startX, startWidth, isResizing = false;document.getElementById('splitter').addEventListener('mousedown', function(e) {isResizing = true;startX = e.clientX;startWidth = document.getElementById('chart-container').offsetWidth;document.addEventListener('mousemove', onMouseMove);document.addEventListener('mouseup', onMouseUp);document.addEventListener('mouseleave', onMouseUp);});/* 拖动时调整大小的逻辑 */function onMouseMove(e) {if (!isResizing) return;let newWidth = startWidth + (e.clientX - startX);newWidth = Math.max(100, Math.min(document.getElementById('main-container').offsetWidth - 5, newWidth));document.getElementById('chart-container').style.flex =`${newWidth / document.getElementById('main-container').offsetWidth * 100}%`;document.getElementById('source-container').style.flex = `calc(100% - ${newWidth}px)`;}/* 停止拖动时的清理逻辑 */function onMouseUp() {isResizing = false;document.removeEventListener('mousemove', onMouseMove);document.removeEventListener('mouseup', onMouseUp);document.removeEventListener('mouseleave', onMouseUp);}// 下载源代码功能function downloadSourceCode() {var element = document.createElement('a');element.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(document.documentElement.outerHTML));element.setAttribute('download', '图表.html');element.style.display = 'none';document.body.appendChild(element);element.click();document.body.removeChild(element);}</script>
</body>
</html>

它的运行效果图是这样的:(右侧是可以动态拖动的)
在这里插入图片描述
在这里插入图片描述

4.分析代码编辑器及运行效果显示

根据上面所有功能的基础上,由于具体的实际需求,数据也是会发生变化的,因此,在原页面中添加了一个 “修改” 按钮,用于跳转到另一个页面进行配置项编译及运行效果展示这样的一个功能;同时也添加了对图表保存为图片的工具。

代码编辑器及运行效果显示功能主要依赖于以下几个技术功能点

  1. 使用HTMLCSS来布局和样式化代码编辑器、图表容器和运行按钮
<div class="container">  <textarea id="codeEditor" style="height: 495px; resize: none;"></textarea>  <div id="chartContainer" style="height: 500px;"></div>  
</div>  
<button onclick="runCode()">运行</button>
  1. JavaScript代码的动态执行
function runCode() {  // 获取页面中ID为'codeEditor'的元素(代码编辑器),并读取其内的值(即用户编写的代码)  var code = document.getElementById('codeEditor').value;  try {  // 创建一个新的函数实例,该函数接受一个名为'option'的参数,并执行用户提供的代码  // 用户代码执行完毕后,返回一个'option'对象,该对象将被用于配置ECharts图表  var userFunction = new Function('option', code + '; return option;');  // 调用上一步创建的函数,不传递任何实际参数(因为ECharts的option将在函数内部定义并返回)  // 函数执行的结果(即用户定义的图表配置)被存储在userOption变量中  var userOption = userFunction();  // 检查userOption是否存在且为对象类型  // 如果是,则使用ECharts实例的setOption方法更新图表配置  if (userOption && typeof userOption === 'object') {  myChart.setOption(userOption);  }  } catch (error) {  // 如果在尝试执行用户代码的过程中发生错误,则捕获该错误  // 在控制台输出错误信息,并向用户显示一个警告框,提示检查自己的代码  console.error('代码执行出错:', error);  alert('代码执行出错,请检查您的代码。');  }  
}
完整代码参考:

(1)主页面.html

<!DOCTYPE html> <!-- 声明这是一个HTML5文档 -->
<html lang="en" style="height: 100%"> <!-- HTML文档的根元素,lang="en"表示文档的主要语言是英语;style="height: 100%" 设置整个页面的高度为浏览器窗口的100% -->
<head><meta charset="utf-8"> <!-- 设置文档的字符编码为UTF-8 --><style>/* 设置html和body元素高度为100%,并启用flex布局 */body, html {height: 100%; /* 设置高度为100% */margin: 0; /* 移除默认的边距 */display: flex; /* 启用Flex布局 */flex-direction: column; /* 设置主轴方向为垂直方向 */overflow: hidden; /* 隐藏溢出内容 */}/* 主容器,flex布局,占据剩余空间 */#main-container {display: flex; /* 启用Flex布局 */flex: 1; /* 占据剩余空间 */overflow: hidden; /* 隐藏溢出内容 */}/* 图表容器,初始时占据全部剩余空间 */#chart-container {flex: 1; /* 占据剩余空间 */height: 100%; /* 设置高度为100% */overflow: hidden; /* 隐藏溢出内容 */position: relative; /* 设置定位方式为相对定位 */}#source-container {flex: 0; /* 初始时不占据空间,根据需要调整 */background-color: rgba(111, 231, 35, 0.36); /* 设置背景颜色 */padding: 30px; /* 设置内边距 */overflow: auto; /* 设置溢出内容自动显示滚动条 */}/* 分割线,用于调整#chart-container和#source-container的大小 */#splitter {background-color: #ccc; /* 设置背景颜色 */cursor: ew-resize; /* 设置鼠标悬停时的形状为水平调整大小 */width: 5px; /* 设置宽度 */position: absolute; /* 设置定位方式为绝对定位 */right: 0; /* 设置右边界为0 */top: 0; /* 设置上边界为0 */bottom: 0; /* 设置下边界为0 */z-index: 1; /* 设置层叠顺序 */}/* 下载按钮样式 */#downloadButton {padding: 10px 20px; /* 设置内边距 */background-color: #007bff; /* 设置背景颜色 */color: #1ed5cf; /* 设置文本颜色 */border: none; /* 移除边框 */border-radius: 5px; /* 设置边框圆角 */cursor: pointer; /* 设置鼠标悬停时的形状为指针 */font-size: 16px; /* 设置字体大小 */position: absolute; /* 设置定位方式为绝对定位 */top: 20px; /* 设置上边界 */right: 20px; /* 设置右边界 */z-index: 1000; /* 设置层叠顺序 */}#modifyButton {padding: 10px 20px; /* 设置内边距 */background-color: #007bff; /* 设置背景颜色 */color: #1ed5cf; /* 设置文本颜色 */border: none; /* 移除边框 */border-radius: 5px; /* 设置边框圆角 */cursor: pointer; /* 设置鼠标悬停时的形状为指针 */font-size: 16px; /* 设置字体大小 */position: absolute; /* 设置定位方式为绝对定位 */top: 10px; /* 设置上边界 */left: 10px; /* 设置左边界 */z-index: 1000; /* 设置层叠顺序 */}</style>
</head><body style="height: 100%; margin: 0; overflow: hidden;"><!-- 添加一个按钮,并设置其样式以便将其定位到页面的左上角 --><button id="modifyButton" style="position: absolute; top: 10px; left: 10px;">修改</button><a id="hiddenLink" href="配置项编辑.html" style="display: none;"></a> <!-- 一个隐藏的链接,用于页面跳转 --><div id="main-container"><div id="chart-container"><div id="container" style="height: calc(100% - 10px); margin-top: 25px;"></div> <!-- 添加了上边距和计算高度 --><div id="splitter"></div> <!-- 分割线,用于拖动调整大小 --></div><div id="source-container"><pre id="source-code"></pre> <!-- 显示HTML源码 --><button id="downloadButton" onclick="downloadSourceCode()">下载</button> <!-- 下载按钮 --></div></div><!-- 引入ECharts库 --><script type="text/javascript" src="echarts.min.js"></script>
<!-- 开始一个JavaScript脚本块 --><script type="text/javascript">// 获取id为container的DOM元素,这个元素将作为ECharts图表的容器var dom = document.getElementById('container');// 使用echarts.init方法初始化一个ECharts实例,指定容器、主题和配置项。这里使用canvas渲染器,并关闭useDirtyRect优化var myChart = echarts.init(dom, null, {renderer: 'canvas',useDirtyRect: false});// 声明一个变量option,用于存储图表的配置项var option;option = {xAxis: {type: 'category',data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'] // X轴数据},yAxis: {type: 'value' // Y轴类型},series: [ // 系列列表{data: [120, 200, 150, 80, 70, 110, 130], // 数据type: 'line', // 图表类型symbol: 'triangle', // 标记的图形symbolSize: 20, // 标记的大小lineStyle: { // 线条样式color: '#5470C6', // 线条颜色width: 4, // 线条宽度type: 'dashed' // 线条类型},itemStyle: { // 图形样式borderWidth: 3, // 描边宽度borderColor: '#EE6666', // 描边颜色color: 'yellow' // 填充颜色}}],toolbox: { // 工具栏show: true, // 显示工具栏feature: {saveAsImage: {} // 保存为图片},right: '100', // 控制工具箱距离容器右侧的距离top: '20' // 控制工具箱距离容器顶部的距离},};// 检查option是否存在且为对象类型,如果是,则使用setOption方法将配置项应用到ECharts实例上if (option && typeof option === 'object') {myChart.setOption(option);}// 给窗口添加一个resize事件监听器,当窗口大小改变时,调用myChart.resize方法使图表自适应新的容器大小window.addEventListener('resize', myChart.resize);</script>
<!-- 按钮的点击事件监听器 -->
<script type="text/javascript">document.getElementById('modifyButton').addEventListener('click', function() {// 触发隐藏 <a> 标签的点击事件,实现页面跳转document.getElementById('hiddenLink').click();});// 设置源代码显示document.getElementById('source-code').textContent = document.documentElement.outerHTML;// 分割线拖动调整大小的逻辑let startX, startWidth, isResizing = false;document.getElementById('splitter').addEventListener('mousedown', function(e) {isResizing = true;startX = e.clientX;startWidth = document.getElementById('chart-container').offsetWidth;document.addEventListener('mousemove', onMouseMove);document.addEventListener('mouseup', onMouseUp);document.addEventListener('mouseleave', onMouseUp);});/* 拖动时调整大小的逻辑 */function onMouseMove(e) {if (!isResizing) return;let newWidth = startWidth + (e.clientX - startX);newWidth = Math.max(100, Math.min(document.getElementById('main-container').offsetWidth - 5, newWidth));document.getElementById('chart-container').style.flex =`${newWidth / document.getElementById('main-container').offsetWidth * 100}%`;document.getElementById('source-container').style.flex = `calc(100% - ${newWidth}px)`;}/* 停止拖动时的清理逻辑 */function onMouseUp() {isResizing = false;document.removeEventListener('mousemove', onMouseMove);document.removeEventListener('mouseup', onMouseUp);document.removeEventListener('mouseleave', onMouseUp);}// 下载源代码功能function downloadSourceCode() {var element = document.createElement('a');element.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(document.documentElement.outerHTML));element.setAttribute('download', '图表.html');element.style.display = 'none';document.body.appendChild(element);element.click();document.body.removeChild(element);}
</script>
</body>
</html>

(2)配置项编辑.html

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>动态代码运行</title>
<!-- 引入ECharts文件 -->
<script src="https://registry.npmmirror.com/echarts/5.5.1/files/dist/echarts.min.js"></script>
<style>/* 设置容器样式 */.container {margin-top: 25px;display: flex;justify-content: space-between;}/* 设置代码编辑器和图表容器的样式 */#codeEditor, #chartContainer {flex: 1; /* 使两个元素占据相等的空间 */margin: 5px; /* 添加一些外边距来分隔元素 */background-image: linear-gradient(to right, rgba(154, 89, 168, 0.67), rgba(30, 145, 199, 0.67), rgba(0, 255, 153, 0.67));}/* 设置按钮样式 */button
{/* 设置按钮为绝对定位,使其能够相对于其最近的已定位(非static)祖先元素进行定位 */position: absolute;/* 设置按钮的顶部位置为父元素高度的50% */top: 50%;/* 设置按钮的左侧位置为父元素宽度的50% */left: 50%;/* 使用transform属性将按钮向左和向上移动其自身宽度和高度的50%,以实现居中效果 */transform: translate(-50%, -50%);/* 设置按钮的内边距 */padding: 2px 10px;/* 设置按钮的背景颜色 */background-color: #007bff;/* 设置按钮的文字颜色 */color: #1ed5cf;/* 去除按钮的边框 */border: none;/* 设置按钮的边框圆角 */border-radius: 7px;/* 设置鼠标悬停在按钮上时的光标样式为指针 */cursor: pointer;/* 设置按钮的文字大小 */font-size: 15px;/* 设置按钮的堆叠顺序,确保它位于其他元素之上 */z-index: 1000;
}
</style>
</head>
<body><div class="container"><!-- 代码编辑器 --><textarea id="codeEditor" style="height: 495px; resize: none;">// 定义图表配置项var option = {xAxis: {type: 'category',data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'] // X轴数据},yAxis: {type: 'value' // Y轴为数值轴},series: [ // 数据系列{data: [120, 200, 150, 80, 70, 110, 130], // 数据type: 'line', // 图表类型为折线图symbol: 'triangle', // 数据点形状为三角形symbolSize: 20, // 数据点大小lineStyle: {color: '#5470C6', // 线条颜色width: 4, // 线条宽度type: 'dashed' // 线条类型为虚线},itemStyle: {borderWidth: 3, // 数据点边框宽度borderColor: '#EE6666', // 数据点边框颜色color: 'yellow' // 数据点填充颜色}}]};</textarea><!-- 图表容器 --><div id="chartContainer" style="height: 500px;"></div>
</div><!-- 运行按钮 -->
<button onclick="runCode()">运行</button><script>
// 初始化ECharts实例
var myChart = echarts.init(document.getElementById('chartContainer'));// 运行代码的函数
function runCode() {// 获取代码编辑器中的代码var code = document.getElementById('codeEditor').value;try {// 将获取的代码转换为函数,并执行,返回option对象var userFunction = new Function('option', code + '; return option;');var userOption = userFunction();// 如果返回的userOption是对象,则使用setOption方法更新图表if (userOption && typeof userOption === 'object') {myChart.setOption(userOption);}} catch (error) {// 如果代码执行出错,则在控制台输出错误信息,并弹出提示console.error('代码执行出错:', error);alert('代码执行出错,请检查您的代码。');}
}</script>
</body>
</html>

它的运行效果图是这样的:
在这里插入图片描述
在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

中国电信解锁万亿参数大模型:TeleAI的创新与突破

首个由万卡集群训练出来的万亿参数大模型&#xff0c;已被一家央企解锁。 具体而言&#xff0c;为了推动纯国产人工智能的探索&#xff0c;带来这条新路径的正是中国电信人工智能研究院&#xff08;TeleAI&#xff09;。 该研究院由中国电信集团的CTO、首席科学家兼院长李学龙…

CSS中字体图标的使用

引言&#xff1a; 在网页设计当中&#xff0c;会有很多很简洁的图标&#xff0c;比如箭头&#xff0c;照相机&#xff0c;放大镜等 这些大概率都是使用字体图标来完成的&#xff0c;因为字体图标比较简洁高效&#xff0c;不会像图片一样需要向浏览器请求数据。那么字体图标该…

使用powershell的脚本报错:因为在此系统中禁止执行脚本

1.添加powershell功能环境&#xff1a; 2.启动powershell的执行策略 因为在此系统中禁止执行脚本。 set-executionpolicy unrestricted

Redis: 主从复制读写分离环境搭建

概述 Redis 的单机模式实际上就是在一个服务器上装了一个单节点的Redis通过简单的配置和简单的命令启动起来就可以使用这种搭建环境&#xff0c;不保证高可用的情况下&#xff0c;完全没有问题如果说你的项目必须要具备高可用&#xff0c;而且 Redis 也要提供更高的性能这个单…

【hot100-java】【寻找重复数】

技巧 使用字典&#xff0c;边记录边比较&#xff0c;有直接输出。 def findDuplicate(nums):seen {}for num in nums:if num in seen:return numseen[num] Truereturn None 可惜不是O(1) 二分查找 class Solution {public int findDuplicate(int[] nums) {int left0;int ri…

宝塔搭建nextcould 30docker搭建onlyoffic8.0

宝塔搭建nextcould 宝塔搭建nextcould可以参考这两个博文 我搭建的是30版本的nextcould&#xff0c;服务组件用的是下面这些&#xff0c;步骤是一样的&#xff0c;只是版本不一样而已 nginx 1.24.0 建议选择nginx&#xff0c;apache没成功。 MySQL 8.0以上都可以 php 8.2.…

Certbot自动申请并续期https证书

Certbot自动申请并续期https证书 一、 安装 Certbot&#xff1a;使用命令安装 Certbot&#xff1a; dnf install certbot python3-certbot-nginx获取 SSL 证书&#xff1a;运行 Certbot 命令来获取并安装 SSL 证书。 示例命令&#xff0c;替换其中的域名和路径信息&#xff1a…

jmeter-请求参数加密-MD5加密

方法1 &#xff1a;使用jmeter自带的函数助手digest Tool(工具)---Function Helper Dialog(函数助手对话框) 第一个参数是要md5加密的值&#xff0c;第二个参数是保存加密后值的变量 &#xff08; 此处变量是从txt文件导入的&#xff0c;所以使用的是${wd} &#xff09; …

Linux网络操作命令与函数全面总结

1. 引言 Linux作为服务器和开发平台&#xff0c;网络操作是其核心功能之一。本文旨在全面总结Linux系统中的网络操作方法&#xff0c;包括命令行工具和编程接口&#xff0c;帮助读者深入理解Linux网络管理的机制。 2. 命令行工具 2.1 ping 命令 ping 命令用于测试网络连接和…

基于投影滤波算法的rick合成地震波滤波matlab仿真

目录 1.课题概述 2.系统仿真结果 3.核心程序与模型 4.系统原理简介 4.1 RICK合成地震波模型 4.2 投影滤波算法原理 5.完整工程文件 1.课题概述 基于投影滤波算法的rick合成地震波滤波matlab仿真。分别通过标准的滤波投影滤波以及卷积滤波投影滤波对合成地震剖面进行滤波…

基于Hive和Hadoop的共享单车分析系统

本项目是一个基于大数据技术的共享单车分析系统&#xff0c;旨在为用户提供全面的单车使用信息和深入的出行行为分析。系统采用 Hadoop 平台进行大规模数据存储和处理&#xff0c;利用 MapReduce 进行数据分析和处理&#xff0c;通过 Sqoop 实现数据的导入导出&#xff0c;以 S…

论文阅读 | HiDDeN网络架构

ECCV 2018 斯坦福-李飞飞团队 一、问题描述 受以下启发&#xff1a; 对抗性例子的发现&#xff1a;深度学习模型在图像识别任务中对微小的、难以察觉的输入扰动非常敏感&#xff0c;这些扰动可以导致模型错误分类图像。这一现象表明&#xff0c;神经网络可以在图像中编码信息&…

Python或R时偏移算法实现

&#x1f3af;要点 计算单变量或多变量时序距离&#xff0c;使用欧几里得、曼哈顿等函数量化不同时序差异。量化生成时序之间接近度相似性矩阵。使用高尔距离和堪培拉距离等相似度测量。实现最小方差匹配算法&#xff0c;绘制步进模式的图形表示。其他语言包算法实现。 &…

IP协议讲解

IP协议 IP协议的本质&#xff1a;提供一种能力&#xff0c;将数据跨网络从A主机传输到B主机 4位版本号(version): 指定IP协议的版本, 对于IPv4来说, 就是4. 4位头部长度(header length): IP头部的长度是多少个32bit, 也就是 length * 4 的字节数. 4bit表示最大 的数字是15, 因…

【数据结构初阶】排序算法(下)冒泡排序与归并排序

文章目录 4. 交换排序4. 1 冒泡排序 5. 归并排序6. 非比较排序6. 1 计数排序 5. 排序性能分析6. 排序算法复杂度及稳定度分析 4. 交换排序 交换排序基本思想: 所谓交换**&#xff0c;就是根据序列中两个记录键值的比较结果来对换这两个记录在序列中的位置**。 交换排序的特点是…

归并排序【C语言版-笔记】

目录 一、概念二、排序流程理解三、代码实现3.1主调函数3.2 merge函数 四、性能分析 一、概念 归并是一种算法思想&#xff0c;是将两个或两个一上的有序表合并成一个长度较大的有序表。若一开始无序表中有n个元素&#xff0c;可以把n个元素看作n个有序表&#xff0c;把它们两…

计算机前沿技术-人工智能算法-大语言模型-最新研究进展-2024-09-27

计算机前沿技术-人工智能算法-大语言模型-最新研究进展-2024-09-27 目录 文章目录 计算机前沿技术-人工智能算法-大语言模型-最新研究进展-2024-09-27目录1. VisScience: An Extensive Benchmark for Evaluating K12 Educational Multi-modal Scientific Reasoning VisScience:…

java中的强软弱虚

在java中对象的引用有强、软、弱、虚四种&#xff0c;这些引用级别的区别主要体现在对象的生命周期、回收时机的不同。 文章目录 准备工作1. 设置内存2. 内存检测 强引用软引用弱引用虚引用 准备工作 1. 设置内存 为方便调试&#xff0c;将内存设置为16MB 依次点击菜单栏的R…

初识算法 · 双指针(1)

目录 前言&#xff1a; 双指针算法 题目一&#xff1a; ​编辑 题目二: 前言&#xff1a; 本文作为算法部分的第一篇文章&#xff0c;自然是少不了简单叭叭两句&#xff0c;对于算法部分&#xff0c;多刷是少不了&#xff0c;我们刷题从暴力过度到算法解法&#xff0c;自…

【Linux】进程概念-2

文章目录 1.环境变量1.1 基本概念1.2 常见环境变量1.3 查看环境变量方法1.4 测试PATH1.5 测试HOME1.6 和环境变量相关的命令1.7 环境变量的组织方式1.8 通过代码如何获取环境变量1.9 通过系统调用获取或设置环境变量1.10 环境变量通常是具有全局属性的1.11 实验 2. 程序地址空间…