SpringBoot集成echarts实现k线图功能

1.什么是echats?

ECharts是一款基于JavaScript的数据可视化图表库,提供直观,生动,可交互,可个性化定制的数据可视化图表。 ECharts最初由百度团队开源,并于2018年初捐赠给Apache基金会,成为ASF孵化级项目。 2021年1月26日晚,Apache基金会官方宣布ECharts项目正式毕业。

2.代码工程

实验目的

实现股票日K线图

pom.xml

xml 复制代码
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>springboot-demo</artifactId>
        <groupId>com.et</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>echarts</artifactId>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-autoconfigure</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
    </dependencies>
</project>

controller

访问根目录,跳转到首页

kotlin 复制代码
package com.et.echats.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;


@Controller
public class HelloWorldController {
    @RequestMapping("/")
    public String index()
    {
        return"index";
    }

}

index.html

常量data0 可以通过接口从后端获取,这里直接用静态数据

yaml 复制代码
<!DOCTYPE html>
<html lang="en">
   <head>
      <meta charset="UTF-8">
      <title>flask+echarts项目</title>
      <!-- 导入下载的 echarts.min.js -->
      <script src="../js/echarts.min.js"></script>
   </head>
   <body>
      <div id="main" style="width:100%;height:500px;"></div>

      <script type="text/javascript">
         // 基于准备好的dom,初始化echarts实例
         var myChart = echarts.init(document.getElementById('main'));

         // 自定义图表的宽高
         // var myChart=echarts.init(document.getElementById('main'),null,{width:500,height:400});

         // 跟随浏览器的宽度自适应图表大小
         // var myChart=echarts.init(document.getElementById('main'));
         // window.addEventListener('resize',function(){myChart.resize();});

         const upColor = "#ec0000";
         const upBorderColor = "#8A0000";
         const downColor = "#00da3c";
         const downBorderColor = "#008F28";

         // 拆分数据
         function splitData(rawData) {
            // 类型年份数据
            const categoryData = [];
            // 开盘价,收盘价,最低价,最高价
            const values = [];
            for (var i = 0; i < rawData.length; i++) {
               categoryData.push(rawData[i].splice(0, 1)[0]);
               values.push(rawData[i]);
            }
            return {
               categoryData: categoryData,
               values: values
            }
         };

         // 数据解释:时间,开盘价,收盘价,最低价,最高价
         const data0 = splitData([
            ['2023/1/24', 2320.26, 2320.26, 2287.3, 2362.94],
            ['2023/1/25', 2300, 2291.3, 2288.26, 2308.38],
            ['2023/1/28', 2295.35, 2346.5, 2295.35, 2346.92],
            ['2023/1/29', 2347.22, 2358.98, 2337.35, 2363.8],
            ['2023/1/30', 2360.75, 2382.48, 2347.89, 2383.76],
            ['2023/1/31', 2383.43, 2385.42, 2371.23, 2391.82],
            ['2023/2/1', 2377.41, 2419.02, 2369.57, 2421.15],
            ['2023/2/4', 2425.92, 2428.15, 2417.58, 2440.38],
            ['2023/2/5', 2411, 2433.13, 2403.3, 2437.42],
            ['2023/2/6', 2432.68, 2434.48, 2427.7, 2441.73],
            ['2023/2/7', 2430.69, 2418.53, 2394.22, 2433.89],
            ['2023/2/8', 2416.62, 2432.4, 2414.4, 2443.03],
            ['2023/2/18', 2441.91, 2421.56, 2415.43, 2444.8],
            ['2023/2/19', 2420.26, 2382.91, 2373.53, 2427.07],
            ['2023/2/20', 2383.49, 2397.18, 2370.61, 2397.94],
            ['2023/2/21', 2378.82, 2325.95, 2309.17, 2378.82],
            ['2023/2/22', 2322.94, 2314.16, 2308.76, 2330.88],
            ['2023/2/25', 2320.62, 2325.82, 2315.01, 2338.78],
            ['2023/2/26', 2313.74, 2293.34, 2289.89, 2340.71],
            ['2023/2/27', 2297.77, 2313.22, 2292.03, 2324.63],
            ['2023/2/28', 2322.32, 2365.59, 2308.92, 2366.16],
            ['2023/3/1', 2364.54, 2359.51, 2330.86, 2369.65],
            ['2023/3/4', 2332.08, 2273.4, 2259.25, 2333.54],
            ['2023/3/5', 2274.81, 2326.31, 2270.1, 2328.14],
            ['2023/3/6', 2333.61, 2347.18, 2321.6, 2351.44],
            ['2023/3/7', 2340.44, 2324.29, 2304.27, 2352.02],
            ['2023/3/8', 2326.42, 2318.61, 2314.59, 2333.67],
            ['2023/3/11', 2314.68, 2310.59, 2296.58, 2320.96],
            ['2023/3/12', 2309.16, 2286.6, 2264.83, 2333.29],
            ['2023/3/13', 2282.17, 2263.97, 2253.25, 2286.33],
            ['2023/3/14', 2255.77, 2270.28, 2253.31, 2276.22],
            ['2023/3/15', 2269.31, 2278.4, 2250, 2312.08],
            ['2023/3/18', 2267.29, 2240.02, 2239.21, 2276.05],
            ['2023/3/19', 2244.26, 2257.43, 2232.02, 2261.31],
            ['2023/3/20', 2257.74, 2317.37, 2257.42, 2317.86],
            ['2023/3/21', 2318.21, 2324.24, 2311.6, 2330.81],
            ['2023/3/22', 2321.4, 2328.28, 2314.97, 2332],
            ['2023/3/25', 2334.74, 2326.72, 2319.91, 2344.89],
            ['2023/3/26', 2318.58, 2297.67, 2281.12, 2319.99],
            ['2023/3/27', 2299.38, 2301.26, 2289, 2323.48],
            ['2023/3/28', 2273.55, 2236.3, 2232.91, 2273.55],
            ['2023/3/29', 2238.49, 2236.62, 2228.81, 2246.87],
            ['2023/4/1', 2229.46, 2234.4, 2227.31, 2243.95],
            ['2023/4/2', 2234.9, 2227.74, 2220.44, 2253.42],
            ['2023/4/3', 2232.69, 2225.29, 2217.25, 2241.34],
            ['2023/4/8', 2196.24, 2211.59, 2180.67, 2212.59],
            ['2023/4/9', 2215.47, 2225.77, 2215.47, 2234.73],
            ['2023/4/10', 2224.93, 2226.13, 2212.56, 2233.04],
            ['2023/4/11', 2236.98, 2219.55, 2217.26, 2242.48],
            ['2023/4/12', 2218.09, 2206.78, 2204.44, 2226.26],
            ['2023/4/15', 2199.91, 2181.94, 2177.39, 2204.99],
            ['2023/4/16', 2169.63, 2194.85, 2165.78, 2196.43],
            ['2023/4/17', 2195.03, 2193.8, 2178.47, 2197.51],
            ['2023/4/18', 2181.82, 2197.6, 2175.44, 2206.03],
            ['2023/4/19', 2201.12, 2244.64, 2200.58, 2250.11],
            ['2023/4/22', 2236.4, 2242.17, 2232.26, 2245.12],
            ['2023/4/23', 2242.62, 2184.54, 2182.81, 2242.62],
            ['2023/4/24', 2187.35, 2218.32, 2184.11, 2226.12],
            ['2023/4/25', 2213.19, 2199.31, 2191.85, 2224.63],
            ['2023/4/26', 2203.89, 2177.91, 2173.86, 2210.58],
            ['2023/5/2', 2170.78, 2174.12, 2161.14, 2179.65],
            ['2023/5/3', 2179.05, 2205.5, 2179.05, 2222.81],
            ['2023/5/6', 2212.5, 2231.17, 2212.5, 2236.07],
            ['2023/5/7', 2227.86, 2235.57, 2219.44, 2240.26],
            ['2023/5/8', 2242.39, 2246.3, 2235.42, 2255.21],
            ['2023/5/9', 2246.96, 2232.97, 2221.38, 2247.86],
            ['2023/5/10', 2228.82, 2246.83, 2225.81, 2247.67],
            ['2023/5/13', 2247.68, 2241.92, 2231.36, 2250.85],
            ['2023/5/14', 2238.9, 2217.01, 2205.87, 2239.93],
            ['2023/5/15', 2217.09, 2224.8, 2213.58, 2225.19],
            ['2023/5/16', 2221.34, 2251.81, 2210.77, 2252.87],
            ['2023/5/17', 2249.81, 2282.87, 2248.41, 2288.09],
            ['2023/5/20', 2286.33, 2299.99, 2281.9, 2309.39],
            ['2023/5/21', 2297.11, 2305.11, 2290.12, 2305.3],
            ['2023/5/22', 2303.75, 2302.4, 2292.43, 2314.18],
            ['2023/5/23', 2293.81, 2275.67, 2274.1, 2304.95],
            ['2023/5/24', 2281.45, 2288.53, 2270.25, 2292.59],
            ['2023/5/27', 2286.66, 2293.08, 2283.94, 2301.7],
            ['2023/5/28', 2293.4, 2321.32, 2281.47, 2322.1],
            ['2023/5/29', 2323.54, 2324.02, 2321.17, 2334.33],
            ['2023/5/30', 2316.25, 2317.75, 2310.49, 2325.72],
            ['2023/5/31', 2320.74, 2300.59, 2299.37, 2325.53],
            ['2023/6/3', 2300.21, 2299.25, 2294.11, 2313.43],
            ['2023/6/4', 2297.1, 2272.42, 2264.76, 2297.1],
            ['2023/6/5', 2270.71, 2270.93, 2260.87, 2276.86],
            ['2023/6/6', 2264.43, 2242.11, 2240.07, 2266.69],
            ['2023/6/7', 2242.26, 2210.9, 2205.07, 2250.63],
            ['2023/6/13', 2190.1, 2148.35, 2126.22, 2190.1]
         ]);

         // 计算MA(移动平均值)
         function calaculateMA(dayCount) {
            var result = [];
            for (var i = 0, len = data0.values.length; i < len; i++) {
               if (i < dayCount) {
                  result.push("-");
                  continue;
               }
               var sum = 0;
               for (var j = 0; j < dayCount; j++) {
                  sum += data0.values[i - j][1];
               }
               result.push(Math.round(sum/dayCount));
            }
            return result
         };

         // 指定图表的配置项和数据
         var option = {
            // 图表标题配置
            title: {
               text: 'K line graph'
            },
            // 提示框配置
            tooltip: {
               // 是否显示提示框
               show: true,
               // 触发类型,axis 移动到坐标轴就触发
               trigger: "axis",
               // 坐标轴上提示点设置
               axisPointer: {
                  type: "cross"
               }
            },
            // 图例配置
            legend: {
               data: ['day K', 'MA5', 'MA10', 'MA20', 'MA30']
            },
            // X 轴配置项
            xAxis: {
               type: "category",
               data: data0.categoryData,
               boundaryGap: false,
               axisLine: {
                  onZero: false
               },
               splitLine: {
                  show: true
               },
               min: "dataMin",
               max: "dataMax"
            },
            // y 轴配置项
            yAxis: {
               scale: true,
               splitArea: {
                  show: true
               }
            },
            dataZoom: [{
                  type: "inside",
                  start: 50,
                  end: 100
               },
               {
                  show: true,
                  type: "slider",
                  top: "90%",
                  start: 50,
                  end: 100
               }
            ],
            // 系列配置,根据不同图表有不同的配置
            series: [
               {
               name: "day K",
               // 图表类型
               type: 'candlestick',
               // 数据内容
               data: data0.values,
               // K 线图的图形样式
               itemStyle: {
                  // 阳线 图形的颜色
                  color: upColor,
                  // 阴线 图形的颜色。
                  color0: downColor,
                  // 阳线 图形的描边颜色
                  borderColor: upBorderColor,
                  // 阴线 图形的描边颜色
                  borderVolor0: downBorderColor
               },
               // 标记点配置
               markPoint: {
                  // 标注的文本
                  label: {
                     // 标签内容格式器,支持字符串模板和回调函数两种形式,字符串模板与回调函数返回的字符串均支持用 \n 换行。
                     // 参数 params 是 formatter 需要的单个数据集, value是传入的数据值。
                     formatter: function(param) {
                        return param != null ? Math.round(param.value) + "" : "";
                     }
                  },
                  // 标注的数据数组。每个数组项是一个对象
                  data: [
                     // 用 coord 属性指定数据在相应坐标系上的坐标位置
                     {
                        name: "Mark",
                        // 标注的坐标。坐标格式视系列的坐标系而定
                        coord: ['2023/5/31', 2300],
                        value: 2300,
                        itemStyle: {
                           color: 'rgb(41,60,85)'
                        }
                     },
                     // 特殊的标注类型,用于标注最大值最小值等
                     {
                        name: "highest value",
                        type: "max",
                        // 在使用 type 时有效,用于指定在哪个维度上指定最大值最小值。
                        valueDim: "highest",
                     },
                     {
                        name: 'lowest value',
                        type: 'min',
                        valueDim: 'lowest'
                     },
                     {
                        name: 'average value on close',
                        type: 'average',
                        valueDim: 'close'
                     }
                  ],
                  // 提示框浮层内容格式器,支持字符串模板和回调函数两种形式。
                  tooltip:{
                     // params 是 formatter 需要的数据集
                     formatter:function(param){
                        // name数据名,类目名,data传入的原始数据项
                        return param.name+"<br>"+(param.data.coord || "")
                     }
                  }
               },
               markLine:{
                  // 标线两端的标记类型,可以是一个数组分别指定两端,也可以是单个统一指定
                  symbol:['none','none'],
                  // 标线的数据数组。每个数组项可以是一个两个值的数组,分别表示线的起点和终点,每一项是一个对象
                  data:[
                     [
                        // 定义从最小值到最大值的线
                        {
                           name:"from lowest to highest",
                           type:"min",
                           valueDim:"lowest",
                           symbol:"circle",
                           symbolSize: 10,
                           label:{show:false},
                           emphasis:{label:{show:false}}
                        },
                        {
                           type:"max",
                           valueDim:"highest",
                           symbol:"circle",
                           symbolSize:10,
                           label:{show:false},
                           emphasis:{label:{show:false}}
                        },
                     ],
                     // 最小值水平线
                     {
                        name:"min line on close",
                        type:"min",
                        valueDim:"close"
                     },
                     // 最大值水平线
                     {
                        name:"max line on close",
                        type:"max",
                        valueDim:"close"
                     },
                  ],
               }
            },
            {
               name:"MA5",
               type:"line",
               data:calaculateMA(5),
               smooth:true,
               lineStyle:{opacity:0.5}
            },
            {
               name:"MA10",
               type:"line",
               data:calaculateMA(10),
               smooth:true,
               lineStyle:{opacity:0.5}
            },
            {
               name:"MA20",
               type:"line",
               data:calaculateMA(20),
               smooth:true,
               lineStyle:{opacity:0.5}
            },
            {
               name:"MA30",
               type:"line",
               data:calaculateMA(30),
               smooth:true,
               lineStyle:{opacity:0.5}
            },
            ]
         };
         //使用刚指定的配置项和数据显示图像
         myChart.setOption(option);
      </script>
   </body>
</html>

application.yaml

ini 复制代码
spring.thymeleaf.cache=false
spring.thymeleaf.suffix=.html

以上只是一些关键代码,所有代码请参见下面代码仓库

代码仓库

3.测试

4.引用

相关推荐
uzong5 小时前
技术故障复盘模版
后端
GetcharZp5 小时前
基于 Dify + 通义千问的多模态大模型 搭建发票识别 Agent
后端·llm·agent
桦说编程6 小时前
Java 中如何创建不可变类型
java·后端·函数式编程
IT毕设实战小研6 小时前
基于Spring Boot 4s店车辆管理系统 租车管理系统 停车位管理系统 智慧车辆管理系统
java·开发语言·spring boot·后端·spring·毕业设计·课程设计
wyiyiyi6 小时前
【Web后端】Django、flask及其场景——以构建系统原型为例
前端·数据库·后端·python·django·flask
一只爱撸猫的程序猿7 小时前
使用Spring AI配合MCP(Model Context Protocol)构建一个"智能代码审查助手"
spring boot·aigc·ai编程
甄超锋7 小时前
Java ArrayList的介绍及用法
java·windows·spring boot·python·spring·spring cloud·tomcat
阿华的代码王国7 小时前
【Android】RecyclerView复用CheckBox的异常状态
android·xml·java·前端·后端
Jimmy7 小时前
AI 代理是什么,其有助于我们实现更智能编程
前端·后端·ai编程
AntBlack8 小时前
不当韭菜V1.1 :增强能力 ,辅助构建自己的交易规则
后端·python·pyqt