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

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

文章目录

  • 可视化图表与源代码显示配置项及页面的动态调整功能分析
      • 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.mzph.cn/pingmian/55266.shtml

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

相关文章

华为云LTS日志上报至观测云最佳实践

华为云LTS简介 华为云云日志服务&#xff08;Log Tank Service&#xff0c;简称 LTS&#xff09;&#xff0c;用于收集来自主机和云服务的日志数据&#xff0c;通过海量日志数据的分析与处理&#xff0c;可以将云服务和应用程序的可用性和性能最大化&#xff0c;为您提供实时、…

基于SSM的爱心慈善公益网站的设计与实现

文未可获取一份本项目的java源码和数据库参考。 选题意义 随着经济的不断进步&#xff0c;发展各种进行公益事业的渠道不断的出现&#xff0c;作为一个礼仪之邦&#xff0c;中华民族一直秉承先人的团结与友善精神&#xff0c;对社会和他人给予帮助关怀。但中国的公益事业相对…

【AIGC】2022-CVPR-利用潜在扩散模型进行高分辨率图像合成

2022-CVPR-High-Resolution Image Synthesis with Latent Diffusion Models 利用潜在扩散模型进行高分辨率图像合成摘要1. 引言2. 相关工作3. 方法3.1. 感知图像压缩3.2. 潜在扩散模型3.3. 调节机制 4. 实验4.1. 关于感知压缩权衡4.2. 利用潜在扩散生成图像4.3. 条件潜在扩散4.…

防sql注入的网站登录系统设计与实现

课程名称 网络安全 大作业名称 防sql注入的网站登录系统设计与实现 姓名 学号 班级 大 作 业 要 求 结合mysql数据库设计一个web登录页面密码需密文存放&#xff08;可以采用hash方式&#xff0c;建议用sha1或md5加盐&#xff09;采用服务器端的验证码&#…

基于Hive和Hadoop的招聘分析系统

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

英集芯IP5911:集成锂电池充电管理和检测唤醒功能的低功耗8位MCU芯片

英集芯IP5911是一款集成锂电池充电管理、咪头检测唤醒、负载电阻插拔和阻值检测等功能的8bit MCU芯片。其封装采用QFN16&#xff0c;应用时仅需极少的外围器件&#xff0c;就能够有效减小整体方案的尺寸&#xff0c;降低BOM成本&#xff0c;为小型电子设备提供高集成度的解决方…

【常读常悟】《大数据之路-阿里巴巴大数据实践》一书读书摘要

【常读常悟】《大数据之路-阿里巴巴大数据实践》一书读书摘要 1、背景2、目录结构3、数据加工链路4、章节摘要4.1 第2章 日志采集4.1.1 日志采集方案4.1.2 采集指标 4.2 第3章 数据同步4.2.1 数据的特点4.2.2 数据同步的三种方式4.2.3 数据同步的最佳实践 4.3 第4章 离线数据开…

以太网交换安全:端口安全

一、端口安全介绍 端口安全是一种网络设备防护措施&#xff0c;通过将接口学习到的动态MAC地址转换为安全MAC地址&#xff08;包括安全动态MAC和Sticky MAC&#xff09;&#xff0c;阻止除安全MAC和静态MAC之外的主机通过本接口和设备通信&#xff0c;从而增强设备的安全性。以…

基于muduo库函数实现protobuf协议的通信

文章目录 先定义具体的业务请求类型2. 实现服务端提供的服务protobuf_server.cppprotobuf_client.cpp 建议先去了解muduo库和protobuf协议&#xff1a; Protobuf库的使用Muduo库介绍及使用 先定义具体的业务请求类型 先使用protobuf库创建我们所要完成的业务请求类型&#xf…

YOLOv11改进 | 主干篇 | YOLOv11引入MobileNetV4

1. MobileNetV4介绍 1.1 摘要&#xff1a; 我们推出了最新一代的 MobileNet&#xff0c;称为 MobileNetV4 (MNv4)&#xff0c;具有适用于移动设备的通用高效架构设计。 在其核心&#xff0c;我们引入了通用倒瓶颈&#xff08;UIB&#xff09;搜索块&#xff0c;这是一种统一且…

【MAUI】CommunityToolkit社区工具包介绍

一、为什么需要声明式开发 .NET的MVVM,始于WPF,很古典,它甚至可能是现代前端框架“声明式开发”的鼻祖。声明式开发,之所以出现,是因为命令式开发在UI层和代码层上无法解耦的问题。如下图所示: 1、命令式开发:后台代码需要调用UI层的控件(label.Text),如果更新UI层…

CEPH的写入流程

1、客户端程序发起对文件的读写请求&#xff0c;ceph前端接口&#xff08;RADOS Gateway&#xff09;将文件切分成多个固定大小的对象&#xff08;默认大小为4MB&#xff09; 2、计算文件到对象的映射 (1) 计算OID为每个对象分配一个唯一的OID&#xff08;Object ID&#xff09…

【微服务】初识(day1)

基础概念 集群 集群是将一个系统完整的部署到多个服务器&#xff0c;每个服务器提供系统的所有服务&#xff0c;多个服务器可以通过负载均衡完成任务&#xff0c;每个服务器都可以称为集群的节点。 分布式 分布式是将一个系统拆分为多个子系统&#xff0c;多个子系统部署在…

免费录屏软件工具:助力高效屏幕录制

录屏已经成为了一项非常实用且广泛应用的技术。无论是制作教学视频、记录游戏精彩瞬间&#xff0c;还是进行软件操作演示等&#xff0c;我们都常常需要一款可靠的录屏软件。今天&#xff0c;就让我们一起来探索那些功能强大录屏软件免费版&#xff0c;看看它们是如何满足我们多…

Leecode刷题之路第六天之Z字形变换

题目出处 06-Z字形变换 题目描述 个人解法 思路&#xff1a; todo 代码示例&#xff1a;&#xff08;Java&#xff09; todo复杂度分析 todo 官方解法 06-Z字形变换官方解法 方法1&#xff1a;利用二维矩阵模拟 思路&#xff1a; 代码示例&#xff1a;&#xff08;Java&am…

蓝桥杯【物联网】零基础到国奖之路:十五. 扩展模块之双路ADC

蓝桥杯【物联网】零基础到国奖之路:十五. 扩展模块之双路ADC 第一节 硬件解读第二节 CubeMX配置第三节 代码编写 第一节 硬件解读 STM32的ADC是12位&#xff0c;通过硬件过采样扩展到16位&#xff0c;模数转换器嵌入到STM32L071xx器件中。有16个外部通道和2个内部通道&#xf…

MongoDB微服务部署

一、安装MongoDB 1.在linux中拉去MongoDB镜像文件 docker pull mongo:4.4.18 2. 2.创建数据挂载目录 linux命令创建 命令创建目录: mkdir -p /usr/local/docker/mongodb/data 可以在sshclient工具查看是否创建成功。 进入moogodb目录&#xff0c;给data赋予权限777 cd …

后台管理系统脚手架

后台管理系统脚手架 介绍 在快速迭代的软件开发世界里&#xff0c;时间就是生产力&#xff0c;效率决定成败。对于构建复杂而庞大的后台系统而言&#xff0c;一个高效、可定制的后台脚手架&#xff08;Backend Scaffold&#xff09;无疑是开发者的得力助手。 脚手架 后台脚…

自动驾驶系列—自动驾驶发展史介绍

&#x1f31f;&#x1f31f; 欢迎来到我的技术小筑&#xff0c;一个专为技术探索者打造的交流空间。在这里&#xff0c;我们不仅分享代码的智慧&#xff0c;还探讨技术的深度与广度。无论您是资深开发者还是技术新手&#xff0c;这里都有一片属于您的天空。让我们在知识的海洋中…

C语言、Eazy_x——井字棋

#include<graphics.h>char board_data[3][3] { { -,-,-},{ -,-,-},{ -,-,-}, };char current_piece o;//检测指定棋子玩家是否获胜 bool CheckWin(char c) {if (board_data[0][0] c && board_data[0][1] c && board_data[0][2] c)return true;if (…