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

news2024/11/18 3:19:20

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

文章目录

  • 可视化图表与源代码显示配置项及页面的动态调整功能分析
      • 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', // 设置渲染器为canvas
      useDirtyRect: 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 URL
      element.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', // 设置渲染器为canvas
      useDirtyRect: 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.coloradmin.cn/o/2184360.html

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

相关文章

第1篇:Window日志分析----应急响应之日志分析篇

0x01 Window事件日志简介 Windows系统日志是记录系统中硬件、软件和系统问题的信息&#xff0c;同时还可以监视系统中发生的事件。用户可以通过它来检查错误发生的原因&#xff0c;或者寻找受到攻击时攻击者留下的痕迹。 Windows主要有以下三类日志记录系统事件&#xff1a;应…

一文彻底搞懂多模态 - 多模态理解+视觉大模型+多模态检索

文章目录 技术交流多模态理解一、图像描述1. 基于编码器-解码器的方法2. 基于注意力机制的方法3. 基于生成对抗网络的方法 二、视频描述三、视觉问答 视觉大模型一、通用图像理解模型二、通用图像生成模型 多模态检索一、单模态检索二、多模态检索三、跨模态检索 最近这一两周看…

ml sys

https://zhuanlan.zhihu.com/p/65242220 sys是为了ml落地&#xff1a;机器学习分为若干阶段&#xff1a;数据收集和标定&#xff0c;处理数据&#xff0c;特征工程&#xff0c;编写模型&#xff0c;训练模型&#xff0c;模型管理&#xff0c;模型部署&#xff0c;其实每个阶段…

【LeetCode: 1870. 准时到达的列车最小时速 | 二分】

&#x1f680; 算法题 &#x1f680; &#x1f332; 算法刷题专栏 | 面试必备算法 | 面试高频算法 &#x1f340; &#x1f332; 越难的东西,越要努力坚持&#xff0c;因为它具有很高的价值&#xff0c;算法就是这样✨ &#x1f332; 作者简介&#xff1a;硕风和炜&#xff0c;…

Reality Expansion Vault:基于Vision Pro + AI的冥想应用

在当今快节奏的生活中,人们常常感到与精神原则脱节。为了帮助用户重新与深层的智慧和洞见建立联系,一款名为Reality Expansion Vault(现实扩展库)的应用应运而生。这款专为Apple Vision Pro设计的应用,通过增强现实技术将精神智慧嵌入用户的环境中,改变人们对世界的看法。…

应用于人形手机器人超小型HarmonicDrive哈默纳科减速机

人形手机器人需要高度的精准性和灵活性以完成各种复杂的任务。减速机的应用&#xff0c;为其提供了关键的动力传输和运动控制支持&#xff0c;它能够将电机的高速旋转转换为适合人形手机器人动作的低速高扭矩输出&#xff0c;确保机器人的动作平稳、准确。HarmonicDrive哈默纳科…

LabVIEW回转支承间隙自动化检测系统

开发了一种基于LabVIEW软件的回转支承间隙检测系统&#xff0c;通过高精度传感器和数据采集卡&#xff0c;自动化、高效地测量回转支承的轴向间隙和径向间隙&#xff0c;提高了检测精度和生产质量。以下是对系统的详细描述与应用案例分析&#xff0c;希望能为有类似需求的开发者…

房屋水电费:重新布局,重构JS代码

<!DOCTYPE html> <html lang"zh-CN"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>房租水电费</title><script type"…

Windows 环境安装配置 Python 保姆级教程

Python Python 是一种解释型、高级、通用的编程语言。它由 Guido van Rossum 于 1989 年底发明&#xff0c;并于 1991 年首次发布。Python 的设计哲学强调代码的可读性和简洁的语法&#xff08;尤其是使用空格缩进来表示代码块&#xff0c;而非使用大括号或关键词&#xff09;。…

利用PDLP扩展线性规划求解能力

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…

智慧产业城智能化总体解决方案

1. 智慧产业城项目概述 智慧产业城项目位于中国武汉高新区&#xff0c;旨在打造一个集高端住宅和商业写字楼于一体的智能化区域。项目规划净用地面积广阔&#xff0c;包含多栋超高层大楼、办公楼、酒店和公寓楼&#xff0c;预计引进众多企业&#xff0c;推动区域经济发展。 2…

搭建帮助中心:8款优质工具分享【2024年最新】

在当今数字化时代&#xff0c;优秀的客户服务已成为企业成功的关键因素之一。一个高效、易用的帮助中心不仅能够提升用户体验&#xff0c;还能有效降低客服成本&#xff0c;增强品牌忠诚度。为了帮助您搭建一个功能强大、内容丰富的帮助中心&#xff0c;我们精心挑选了8款优质工…

「重构:改善既有代码的设计」实战篇

前言 在软件开发的世界里&#xff0c;代码重构是提升项目质量、适应业务变化的关键步骤。最近&#xff0c;我重新翻阅了《重构&#xff1a;改善既有代码的设计 第二版》&#xff0c;这本书不仅重新点燃了我对重构的热情&#xff0c;还深化了我的理解&#xff1a;重构不仅仅是代…

ROM、RAM 和 Flash 的区别

目录 一、ROM二、RAM1、内存工作原理 三、Flash 在计算机的组成结构中&#xff0c;有一个很重要的部分&#xff0c;就是存储器。存储器是用来存储程序和数据的部件&#xff0c;对于计算机来说&#xff0c;有了存储器&#xff0c;才有记忆功能&#xff0c;才能保证正常工作。存储…

RocketMQ 消息示例-topic、broker、messagequeue

topic主题里面是会有一些队列的。 可以看到消费的消息来自于不同的broker。broker后面还带有queueid&#xff0c;可以看到brokera后面是带有四个队列。 同理brokerb也会有四条队列。 创建topic并没有指定创建在哪个broker上面。它会去创建在默认的broker cluster上面。 brokerC…

DataFlow 专业版 标准版奶牛管理系统软件

DataFlow 专业版 标准版奶牛管理系统软件特点&#xff1a;是一个控制挤奶和奶牛监测的综合管理系统&#xff0c;能够通过挤奶设备等进行信息采集&#xff0c;生成报告、图表、分析、任务列表和终生奶牛卡历史等。该系统还可以控制和支持分群门、饲喂系统和称重系统等奶厅相关组…

嵌入向量生成与查询

嵌入向量生成与查询 文本嵌入模型 M3E 是 Moka Massive Mixed Embedding 的缩写 Moka&#xff0c;此模型由 MokaAI 训练&#xff0c;开源和评测&#xff0c;训练脚本使用 uniem&#xff0c;评测 BenchMark 使用 MTEB-zh Massive&#xff0c;此模型通过千万级 (2200w) 的中文句…

React 原理分析

优质博文&#xff1a;IT-BLOG-CN 一、简介 为什么我要用react&#xff1f;JQuery也挺好的呀&#xff1f; 1、因为浏览器和JavaScript一直在更新&#xff0c;新版前端框架可以更好对接新的API&#xff0c;更好的利用浏览器的能力&#xff0c; 提供更新潮强大的功能。 2、react…

C++中,如何使你设计的迭代器被标准算法库所支持。

iterator&#xff08;读写迭代器&#xff09; const_iterator&#xff08;只读迭代器&#xff09; reverse_iterator&#xff08;反向读写迭代器&#xff09; const_reverse_iterator&#xff08;反向只读迭代器&#xff09; 以经常介绍的_DList类为例&#xff0c;它的迭代…

番茄间的一分钟休息

很多人喜欢使用番茄工作法&#xff0c;在25分钟内集中工作。这种方法提高了25分钟内的工作效率&#xff0c;但是也增加了自己的疲劳程度。 我建议&#xff0c;在25分钟的工作时间内&#xff0c;要保持对自己身体的觉察。如果感觉呼吸短促&#xff0c;有一些紧张&#xff0c;用…