使用 Apache ECharts 实现圣都装饰的延期日历图

使用 Apache ECharts 实现圣都装饰的延期日历图

用户需求:

最近朋友选择圣都装饰公司来装修房子,结果公司管理混乱,延期严重,让我帮忙设计一个类似 github 的日历图,方便更直观的查看延期时间。

需求分析:

Apache ECharts 自带了“日历坐标系 calendar” ,可以很方便的画出日历图。

ECharts 网站有很多的示例代码,可以去 https://echarts.apache.org/examples/zh/index.html#chart-type-calendar 网址查看例子。

获取 Apache ECharts

ECharts 使用很简单,只需要引入 echarts.js 文件即可。生成环境请使用压缩后的 echarts.min.js 文件。

在 https://www.jsdelivr.com/package/npm/echarts 选择 dist/echarts.js,点击并保存为 echarts.js 文件。

引入 Apache ECharts

在刚才保存 echarts.js 的目录新建一个 index.html 文件,内容如下:

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <!-- 引入刚刚下载的 ECharts 文件 -->
    <script src="echarts.js"></script>
  </head>
</html> 

绘制一个简单的图表

在绘图前我们需要为 ECharts 准备一个定义了高宽的 DOM 容器。在刚才的例子 head 标签之后,添加:

<body>
  <!-- 为 ECharts 准备一个定义了宽高的 DOM -->
  <div id="main" style="width: 600px;height:400px;"></div>
</body>

然后就可以通过 echarts.init 方法初始化一个 echarts 实例并通过 setOption 方法生成一个简单的柱状图,下面是完整代码。

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <title>ECharts</title>
    <!-- 引入刚刚下载的 ECharts 文件 -->
    <script src="echarts.js"></script>
  </head>
  <body>
    <!-- 为 ECharts 准备一个定义了宽高的 DOM -->
    <div id="main" style="width: 600px;height:400px;"></div>
    <script type="text/javascript">
      // 基于准备好的dom,初始化echarts实例
      const mainDiv = document.getElementById('main');
      const myChart = echarts.init(mainDiv);

      // 指定图表的配置项和数据
      const option = {
        title: {
          text: 'ECharts 入门示例'
        },
        tooltip: {},
        legend: {
          data: ['销量']
        },
        xAxis: {
          data: ['衬衫', '羊毛衫', '雪纺衫', '裤子', '高跟鞋', '袜子']
        },
        yAxis: {},
        series: [
          {
            name: '销量',
            type: 'bar',
            data: [5, 20, 36, 10, 10, 20]
          }
        ]
      };

      // 使用刚指定的配置项和数据显示图表。
      myChart.setOption(option);
    </script>
  </body>
</html>

通过这个小列子,可以看到,使用 Echarts 画图,最重要的就是配置 setOption 参数对象。

下边我们来实现圣都装修延期日历图。

圣都延期日历图的实现

为了使 index.html 里的代码简洁,我们把 option 配置代码,放到外部 js 里。

index.html 代码如下:

<!DOCTYPE html>
<html>

<head>
    <meta charset="utf-8" />
    <!-- 引入刚刚下载的 ECharts 文件 -->
    <script src="echarts.js"></script>

    <!-- 引入 dayjs 方便处理日期 -->
    <script type="text/javascript" src="dayjs.min.js"></script>

</head>

<body>
    <h1> 圣都装修延期日历 2022 </h1>
    <!-- 为 ECharts 准备一个定义了宽高的 DOM -->
    <div id="main" style="width: 900px;height:800px;"></div>

    <!-- 引入 shengdu_2.js 文件,里边是 echarts 的图形的配置 -->
    <script type="text/javascript" src="shengdu_2.js"></script>
    <script>
        var myChart = echarts.init(document.getElementById('main'));

        // 变量 option 实在 shengdu_2.js 里定义的 
        // 设置配置项,图片会渲染出来
        myChart.setOption(option);
    </script>
</body>

</html>

Day.js 是一个轻量的处理时间和日期的 JavaScript 库,和 Moment.js 的 API 设计保持完全一样。代码可以去网站 https://dayjs.gitee.io/zh-CN/ 下载。

dayjs 的使用示例:

// 格式化: 2022-01-25
dayjs("2022-01-25").format("YYYY-MM-DD")

// 日期转成毫秒数: 1643040000000
dayjs("2022-01-25").valueOf()

// 毫秒数转成unix时间戳(秒)
dayjs(1318781876406).unix()

引入的 shengdu_2.js 文件代码如下:

// shengdu_2.js
function get_all_dates() {
  var date = +echarts.number.parseDate("2021-09-28");
  var end = +echarts.number.parseDate("2022-06-22");
  var dayTime = 3600 * 24 * 1000;
  var showDates = [];

  // 这里是假期,要排除掉
  const holidays = [
    "2021-10-01",
    "2021-10-02",
    "2021-10-03",
    "2021-10-04",
    "2021-10-05",
    "2021-10-06",
    // '2021-10-07',

    "2022-01-01",
    "2022-01-02",
    "2022-01-03",
    "2022-01-31",
    "2022-02-01",
    "2022-02-02",
    "2022-02-03",
    "2022-02-04",
    "2022-02-05",
    "2022-02-06",
    "2022-04-05",
    "2022-05-02",
    "2022-05-03",
    "2022-05-04",
    "2022-06-03",
  ];

  n = 0;
  i = 0;
  delayStart = "2022-02-16";
  delayEnd = "2022-06-22";
  for (var time = date; time < end; time += dayTime) {
    // echarts.time.format(time, "yyyy-mm-dd"),
    let d = dayjs(time);
    let n = 0;
    let str = d.format("YYYY-MM-DD");

    console.log(d.unix());

    if (d.format("ddd") == "Sat" || d.format("ddd") == "Sun") {
      showDates.push([d.format("YYYY-MM-DD"), 501]); // 周末
    } else {
      if (holidays.includes(str)) {
        showDates.push([d.format("YYYY-MM-DD"), 502]); // 法定假日
      } else {
        if (
          time >= dayjs(delayStart).valueOf() &&
          time <= dayjs(delayEnd).valueOf()
        ) {
          i++;
          showDates.push([d.format("YYYY-MM-DD"), i]); // 延期时间
        } else {
          showDates.push([d.format("YYYY-MM-DD"), 500]); // 原排期
        }
      }
    }
  }
  return showDates;
}

option = {
  // 图标的标题
  title: {
    top: 30,
    left: "center",
    text: "延期日历",
  },
  // 设置鼠标悬浮时展示的文案
  tooltip: {
    formatter: (params) => {
      let msg = " 数值: ";
      if (params.value[1] <= 200) {
        msg = " 延期天数: ";
      } else if(params.value[1]==501) {
        msg = " 休息: ";
      }
      else if(params.value[1]==502) {
        msg = " 假期: ";
      }
      return params.value[0]+ msg + params.value[1].toFixed(2);
    },
  },
  // 
  visualMap: {
    // min: 0,
    // max: 1000,
    type: "piecewise",
    orient: "horizontal",
    left: "center",
    top: 65,
    type: "piecewise",
    pieces: [
      { min: 1, max: 499, label: "延期", color: "red" },
      { value: 0, label: "空", color: "white" },
      { value: 500, label: "排期", color: "green" },
      { value: 501, label: "周末", color: "lightgray" },
      { value: 502, label: "假日", color: "gray" },
    ],
    outOfRange: {
      color: "#eee",
    },
    calculable: true,
  },
  // 日历的配置
  calendar: {
    top: 120,
    left: 30,
    right: 30,
    cellSize: [30, 25],
    range: ["2021-09-01", "2022-07-09"],
    itemStyle: {
      borderWidth: 0.5,
    },
    dayLabel: {
      firstDay: 0, // 从周一开始
    },
    yearLabel: { show: false },
  },
  series: [
    {
      // type: "heatmap",
      type: "scatter",
      coordinateSystem: "calendar",
      // <---- 图标里的数据来源
      data: get_all_dates(),
      itemStyle: {
        color: "#ddb926",
      },
      symbolSize:11,
    },
  ],
};

图表的一些参数解析:

日历图主要设置 calendar 参数。calendar 里的 range 指定了日历的范围。

ECharts 中的数据,一般存放于 series.data 中。

series,是设置数据的映射系列。即把数据集( dataset )的行或列映射为系列(series)。
series.type 设置的是图标的类型。比如 柱状图 bar,折线图 line,饼图 pie,散点图 scatter。上边日历的代码里,用的就是散点图 scatter。

visualMap 组件定义了把数据的哪个维度映射到什么视觉元素上。现在提供两种类型的 visualMap 组件,一个是 连续的 continuous ,一个是 分段的 piecewise ,通过 visualMap.type 来区分。(本实例使用的 piecewise 分段的)

上边的日历图例代码里,visualMap 里 pieces 自定义的一些颜色。

tooltip 设置鼠标悬浮时展示的文案。

在这里插入图片描述

感谢阅读。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Web后端技术

您的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值