【小沐学前端】Node实现Web图表功能(ECharts.js,React)

在这里插入图片描述

🎈🎈🎈Python实现Web图表功能系列:🎈🎈🎈
1🎈【Web开发】Python实现Web图表功能(D-Tale入门)🎈
2🎈【Web开发】Python实现Web图表功能(D-Tale编译)🎈
3🎈【Web开发】Python实现Web图表功能(pyecharts,Flask)🎈
4🎈【Web开发】Python实现Web图表功能(ECharts.js,Flask)🎈
5🎈【Web开发】Node实现Web图表功能(ECharts.js,Vue)🎈
6🎈【Web开发】Node实现Web图表功能(ECharts.js,React)🎈
7🎈【Web开发】Python实现Web图表功能(Grafana入门)🎈

1、简介

1.1 Node

Node.js 是一个开源和跨平台的 JavaScript 运行时环境。 它几乎是任何类型项目的流行工具!
Node.js 在浏览器之外运行 V8 JavaScript 引擎(Google Chrome 的内核)。 这使得 Node.js 的性能非常好。
在这里插入图片描述

1.2 ECharts

ECharts是一款基于JavaScript的数据可视化图表库,提供直观,生动,可交互,可个性化定制的数据可视化图表。ECharts最初由百度团队开源,并于2018年初捐赠给Apache基金会,成为ASF孵化级项目。
在这里插入图片描述

ECharts,缩写来自 Enterprise Charts,商业级数据图表,是百度的一个开源的数据可视化工具,一个纯 Javascript 的图表库,能够在 PC 端和移动设备上流畅运行,兼容当前绝大部分浏览器(IE6/7/8/9/10/11,chrome,firefox,Safari等),底层依赖轻量级的 Canvas 库 ZRender,ECharts 提供直观,生动,可交互,可高度个性化定制的数据可视化图表。创新的拖拽重计算、数据视图、值域漫游等特性大大增强了用户体验,赋予了用户对数据进行挖掘、整合的能力。

1.3 React

https://reactjs.org/
https://create-react-app.bootcss.com/

React 是一个用于构建用户界面的 JAVASCRIPT 库。
React 主要用于构建 UI,很多人认为 React 是 MVC 中的 V(视图)。
React 起源于 Facebook 的内部项目,用来架设 Instagram 的网站,并于 2013 年 5 月开源。
React 拥有较高的性能,代码逻辑非常简单,越来越多的人已开始关注和使用它。
在这里插入图片描述
React 在设计之初就可以被渐进式适配,并且你可以根据需要选择性地使用 React。可能你只想在现有页面中“局部地添加交互性”。使用 React 组件是一种不错的方式。
在这里插入图片描述

通过仅仅几行代码并且无需使用构建工具,试试在你的网站的一小部分中使用 React。然后,你可以逐步扩展它的存在,或只将其涵盖在少数动态部件中。
在这里插入图片描述

2、安装

2.1 安装node

下载地址:
https://nodejs.org/en/
在这里插入图片描述
输入一下命令,检测node安装是否成功:

node -v

在这里插入图片描述

2.2 安装echarts

mkdir test_echarts
cd test_echarts
npm init -y
npm install echarts --save

在这里插入图片描述

2.3 安装React

在这里插入图片描述

2.3.1 CDN库方式

可以直接使用 Staticfile CDN 的 React CDN 库,地址如下:

<script src="https://cdn.staticfile.org/react/16.4.0/umd/react.development.js"></script>
<script src="https://cdn.staticfile.org/react-dom/16.4.0/umd/react-dom.development.js"></script>
<!-- 生产环境中不建议使用 -->
<script src="https://cdn.staticfile.org/babel-standalone/6.26.0/babel.min.js"></script>

官方提供的 CDN 地址:

<script src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
<!-- 生产环境中不建议使用 -->
<script src="https://unpkg.com/babel-standalone@6.15.0/babel.min.js"></script>

测试网页如下:

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>Hello React!</title>
<script src="https://cdn.staticfile.org/react/16.4.0/umd/react.development.js"></script>
<script src="https://cdn.staticfile.org/react-dom/16.4.0/umd/react-dom.development.js"></script>
<script src="https://cdn.staticfile.org/babel-standalone/6.26.0/babel.min.js"></script>
</head>
<body>
 
<div id="example"></div>
<script type="text/babel">
ReactDOM.render(
    <h1>Hello world, React!</h1>,
    document.getElementById('example')
);
</script>
 
</body>
</html>

在这里插入图片描述
引入了三个库: react.development.min.js 、react-dom.development.min.js 和 babel.min.js:

react.min.js - React 的核心库
react-dom.min.js - 提供与 DOM 相关的功能
babel.min.js - Babel 可以将 ES6 代码转为 ES5 代码,这样我们就能在目前不支持 ES6 浏览器上执行 React 代码。Babel 内嵌了对 JSX 的支持。通过将 Babel 和 babel-sublime 包(package)一同使用可以让源码的语法渲染上升到一个全新的水平。

2.3.2 npm方式

# 使用淘宝定制的 cnpm
npm install -g cnpm --registry=https://registry.npmmirror.com
npm config set registry https://registry.npmmirror.com

# create-react-app 是来自于 Facebook,通过该命令我们无需配置就能快速构建 React 开发环境。
# create-react-app 自动创建的项目是基于 Webpack + ES6 。
cnpm install -g create-react-app
create-react-app my-app   #create-react-app my-app --template typescript
cd my-app/
npm start

命令行执行命令:
在这里插入图片描述
自动创建的react工程的文件夹:
在这里插入图片描述
浏览器显示react默认页面:
在这里插入图片描述
如果在原生的JS应用或者jQuery项目中,我们常用的方式就是直接去官网下载其核心js文件并导入我们的项目中使用。但是在React项目中,就不需要。由于React项目开发基于webpack做了二次封装,而webpack又是基于 Node.js的前端项目部署打包工。

3、测试(React)

3.1 修改App.js(hello world)

为了修改上面网页内容,现修改App.js:
在这里插入图片描述
修改App.js部分代码如下:
在这里插入图片描述
浏览器显示修改后的react页面:
在这里插入图片描述

3.2 修改index.js(hello world)

  • 先来一个例子:为了修改上面网页内容,现修改index.js如下:
    在这里插入图片描述
    修改index.js部分代码如下:
import React from 'react';
import ReactDOM from 'react-dom/client';

class HelloMessage extends React.Component {
  render() {
    return (
      <div>
        Hello {this.props.name}
      </div>
    );
  }
}

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
  <HelloMessage name="爱看书的小沐" />
);

浏览器显示修改后的react页面:
在这里插入图片描述

  • (2)再来一个例子:
import React from 'react';
import ReactDOM from 'react-dom/client';

function Name(props) {
    return <h1>网站名称:{props.name}</h1>;
}
function Url(props) {
    return <h2>网站地址:{props.url}</h2>;
}
function Nickname(props) {
    return <h3>网站小名:{props.nickname}</h3>;
}
function App() {
    return (
    <div>
        <Name name="爱看书的小沐" />
        <Url url="http://www.baidu.com" />
        <Nickname nickname="tomcat" />
    </div>
    );
}

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
  <App />
);

浏览器显示修改后的react页面:
在这里插入图片描述

3.3 修改index.js(定时器)

  • 一个时间的例子:
import React from 'react';
import ReactDOM from 'react-dom/client';

class Clock extends React.Component {
  constructor(props) {
    super(props);
    this.state = {date: new Date()};
  }
 
  componentDidMount() {
    this.timerID = setInterval(
      () => this.tick(),
      1000
    );
  }
 
  componentWillUnmount() {
    clearInterval(this.timerID);
  }
 
  tick() {
    this.setState({
      date: new Date()
    });
  }
 
  render() {
    return (
      <div>
        <h1>Hello world, 爱看书的小沐!</h1>
        <h2>现在是 {this.state.date.toLocaleTimeString()}.</h2>
      </div>
    );
  }
}

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
  <Clock />
);

浏览器显示修改后的react页面:
在这里插入图片描述

3.4 修改index.js(按钮button)

  • 一个按钮的例子:
import React from 'react';
import ReactDOM from 'react-dom/client';

class Toggle extends React.Component {
  constructor(props) {
    super(props);
    this.state = {isToggleOn: true};
 
    // 这边绑定是必要的,这样 `this` 才能在回调函数中使用
    this.handleClick = this.handleClick.bind(this);
  }
 
  handleClick() {
    this.setState(prevState => ({
      isToggleOn: !prevState.isToggleOn
    }));
  }
 
  render() {
    return (
	<div>
	  <p>爱看书的小沐的按钮:</p>
      <button onClick={this.handleClick}>
        {this.state.isToggleOn ? 'ON' : 'OFF'}
      </button>
	  </div>
    );
  }
}

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
  <Toggle />
);

浏览器显示修改后的react页面:
在这里插入图片描述

3.5 修改index.js(请求AJAX)

在 React 开发中,你能使用任何你喜欢的 AJAX 库,比如社区比较流行的 Axios,jQuery AJAX,或者是浏览器内置的 window.fetch。

我们推荐你在 componentDidMount 这个生命周期函数中发起 AJAX 请求。这样做你可以拿到 AJAX 请求返回的数据并通过 setState 来更新组件。

安装jquery库:

npm install jquery --save

修改代码如下:

import React from 'react';
import ReactDOM from 'react-dom/client';
import $ from 'jquery';

class UserGist extends React.Component {
  constructor(props) {
      super(props);
      this.state = {username: '', html_url: ''};
  }
 
  componentDidMount() {
    this.serverRequest = $.get(this.props.source, function (result) {
      var lastGist = result[0];
      this.setState({
        username: lastGist.owner.login,
        html_url: lastGist.html_url,
        id: lastGist.id,
        node_id: lastGist.node_id,
        created_at: lastGist.created_at,
        updated_at: lastGist.updated_at,
        description: lastGist.description,
        comments: lastGist.comments,
      });
    }.bind(this));
  }
 
  componentWillUnmount() {
    this.serverRequest.abort();
  }
 
  render() {
    return (
      <div>
        {this.state.username} 用户最新的 Gist 信息:
        <a href={this.state.id}>{this.state.html_url}</a>
		<p>node_id: {this.state.node_id} </p>
		<p>created_at: {this.state.created_at} </p>
		<p>updated_at: {this.state.updated_at} </p>
		<p>description: {this.state.description} </p>
		<p>comments: {this.state.comments} </p>
      </div>
    );
  }
}
 
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
  <UserGist source="https://api.github.com/users/octocat/gists" />
);

浏览器显示修改后的react页面:
在这里插入图片描述

3.6 修改index.js(请求fetch)

import React from 'react';
import ReactDOM from 'react-dom/client';
import $ from 'jquery';

class MyComponent extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      error: null,
      isLoaded: false,
      items: []
    };
  }

  componentDidMount() {
    fetch("https://api.wmdb.tv/api/v1/top?type=Imdb&skip=0&limit=20&lang=Cn")
      .then(res => res.json())
      .then(
        (result) => {
          this.setState({
            isLoaded: true,
            items: result
          });
        },
        // 注意:需要在此处处理错误
        // 而不是使用 catch() 去捕获错误
        // 因为使用 catch 去捕获异常会掩盖掉组件本身可能产生的 bug
        (error) => {
          this.setState({
            isLoaded: true,
            error
          });
        }
      )
  }

  render() {
    const { error, isLoaded, items } = this.state;
    if (error) {
      return <div>Error: {error.message}</div>;
    } else if (!isLoaded) {
      return <div>Loading...</div>;
    } else {
      return (
        <ul>
          {items.map(item => (
            <li key={item.data[0].id}>
              <p>{item.dateReleased} {item.data[0].country}  {item.data[0].name} </p> {item.data[0].description}
            </li>
          ))}
        </ul>
      );
    }
  }
}
 
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
  <MyComponent />
);

浏览器显示修改后的react页面:
在这里插入图片描述

3.7 修改index.js(Markdown 库)

import React from 'react';
import ReactDOM from 'react-dom/client';

import { Remarkable } from 'remarkable';

class MarkdownEditor extends React.Component {
  constructor(props) {
    super(props);
    this.md = new Remarkable();
    this.handleChange = this.handleChange.bind(this);
    this.state = { value: 'Hello, **world**!' };
  }

  handleChange(e) {
    this.setState({ value: e.target.value });
  }

  getRawMarkup() {
    return { __html: this.md.render(this.state.value) };
  }

  render() {
    return (
      <div className="MarkdownEditor">
        <h3>Input</h3>
        <label htmlFor="markdown-content">
          Enter some markdown
        </label>
        <textarea
          id="markdown-content"
          onChange={this.handleChange}
          defaultValue={this.state.value}
        />
        <h3>Output</h3>
        <div
          className="content"
          dangerouslySetInnerHTML={this.getRawMarkup()}
        />
      </div>
    );
  }
}

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
  <MarkdownEditor />
);

浏览器显示修改后的react页面:
在这里插入图片描述

4、测试(React+Echarts)

4.1 修改App.js(Echarts例子: 柱状图)

import React, { PureComponent } from "react";
import * as eCharts from "echarts";

export default class App extends PureComponent {

  eChartsRef: any = React.createRef();

  componentDidMount() {
    const myChart = eCharts.init(this.eChartsRef.current);

    let option = {
      title: {
        text: "ECharts 入门示例(爱看书的小沐)",
      },
      tooltip: {},
      legend: {
        data: ["销量"],
      },
      xAxis: {
        data: ["衬衫", "羊毛衫", "雪纺衫", "裤子", "高跟鞋", "袜子"],
      },
      yAxis: {},
      series: [
        {
          name: "销量",
          type: "bar",
          data: [5, 20, 36, 10, 10, 20],
        },
      ],
    };

    myChart.setOption(option);
  }

  render() {
    return <div ref={this.eChartsRef} style={{
      width: 600,
      height: 400,
      margin: 100
    }}></div>;
  }
}

浏览器显示修改后的react页面:
在这里插入图片描述

4.2 修改App.js(ECharts例子:折线图)

安装库:

#git clone https://github.com/hustcc/echarts-for-react.git
#npm install
#npm start

npm install --save echarts-for-react
npm install echarts --save
npm start

修改App.js代码测试:

import React from 'react';
//import {Card} from 'antd';
//import echartTheme from './../themeLight'
//不是按需加载的话文件太大
//import echarts from 'echarts'
//下面是按需加载
import echarts from 'echarts/lib/echarts'
import 'echarts/lib/chart/line';  //折线图是line,饼图改为pie,柱形图改为bar
import 'echarts/lib/component/tooltip';
import 'echarts/lib/component/title';
import 'echarts/lib/component/legend';
import 'echarts/lib/component/markPoint';
import ReactEcharts from 'echarts-for-react';
export default class App extends React.Component{
  getOption =()=> {
    let option = {
      title:{
        text:'用户骑行订单(爱看书的小沐)',
        x:'center'
      },
      tooltip:{
        trigger:'axis',
      },
      xAxis:{
        data:['周一','周二','周三','周四','周五','周六','周日']
      },
      yAxis:{
        type:'value'
      },
      series:[
        {
          name:'OFO订单量',
          type:'line',   //折线图是line,饼图改为pie,柱形图改为bar
          data:[1000,2000,1500,3000,2000,1200,800]
        }
      ]
    }
   return option
  }

  render(){
    return(
      <div>
        <div title="折线图表之一">
            <ReactEcharts option={this.getOption()} theme="Imooc"  style={{height:'400px'}}/>
        </div>

      </div>
    )
  }
}

浏览器显示修改后的react页面:
在这里插入图片描述

4.3 修改App.js(ECharts例子:饼状图)

import React, {
    Component
} from "react";
// 引入ECharts主模块 
import * as echarts from "echarts/lib/echarts";
// 引入饼状图需要的模块 
import "echarts/lib/chart/pie";
import "echarts/lib/component/title";
import "echarts/lib/component/tooltip";
import "echarts/lib/component/legend";
class App extends Component { // 初始化状态 
    state = {
        data: [
            {value: 150, name: '语文'},
            {value: 110, name: '物理'},
            {value: 150, name: '数学'},
            {value: 100, name: '化学'},
            {value: 150, name: '英语'},
            {value: 90, name: '生物'},
        ],
        celldata:['语文', '物理', '数学', '化学', '英语', '生物']
    };
    async componentDidMount() {
        
        var myChart = echarts.init(document.getElementById("main"));
        myChart.setOption(
            {
                title: {
                    text: '高考理科分数占比(爱看书的小沐)',
                    left: 'center'
                },
                tooltip: {
                    trigger: 'item',
                    formatter: '{a} <br/>{b} : {c} ({d}%)'
                },
                legend: {
                    left: 'center',
                    top: 'bottom',
                    data: this.state.celldata
                },
                toolbox: {
                    show: true,
                    feature: {
                        mark: {show: true},
                        dataView: {show: true, readOnly: false},
                        magicType: {
                            show: true,
                            type: ['pie', 'funnel']
                        },
                        restore: {show: true},
                        saveAsImage: {show: true}
                    }
                },
                series: [
                    {
                        name: '分数',
                        type: 'pie',
                        radius: [30, 110],
                        center: ['50%', '50%'],
                        roseType: 'area',
                        data: this.state.data
                    }
                ]
            }            
        );
    }
    render() {
            return <div id = "main" style = { {  width: 1000, height: 400 }}> </div>; 
    }
}
export default App; 

浏览器显示修改后的react页面:
在这里插入图片描述

4.4 修改App.js(ECharts例子:玫瑰图)

import React, { Component} from "react";
// 引入ECharts主模块 
import * as echarts from "echarts/lib/echarts";
// 引入折线图需要的模块 
import "echarts/lib/chart/line";
import "echarts/lib/component/title";
import "echarts/lib/component/tooltip";
import "echarts/lib/component/legend";
import 'echarts/lib/component/polar';
class App extends Component { 
    state = {
        sourceData: [],
    };
    async componentDidMount() {
        let data = [];
        for (let i = 0; i <= 100; i++) {
            let theta = i / 100 * 360;
            let r = 5 * (1 + Math.sin(theta / 180 * Math.PI));
            data.push([r, theta]);
        }
        this.setState(() => {
            return {
                sourceData: data
            };
        });
        let myChart = echarts.init(document.getElementById("main"));
        myChart.setOption({
                title: {
                    text: '极坐标双数值轴(爱看书的小沐)'
                },
                legend: {
                    data: ['line']
                },
                polar: {},
                tooltip: {
                    trigger: 'axis',
                    axisPointer: {
                        type: 'cross'
                    }
                },
                angleAxis: {
                    type: 'value',
                    startAngle: 0
                },
                radiusAxis: {
                },
                series: [{
                    coordinateSystem: 'polar',
                    name: 'line',
                    type: 'line',
                    data: data 
                }]
            }
        );
    }
    render() {
        return <div id = "main" style = { {  width: 1000, height: 600 }}> </div>; 
    }
}
export default App; 

浏览器显示修改后的react页面:
在这里插入图片描述

4.5 修改App.js(ECharts例子:面积图)

  • (1)在App.js代码修改如下:
import React from "react";
import './App.css';
import BaseRouter from './component/test-echarts.js'

function App() {
  return (
    <div>
      hello world
      <BaseRouter/>
    </div>
  );
}
export default App;
  • (2)在APP.js同层级的component下新建test-echarts.js
    在这里插入图片描述
    在这里插入图片描述
import React from 'react'
import * as echarts from 'echarts';
// console.log(echarts)

class TestChart extends React.Component {
  componentDidMount () {
     // 初始化图表效果
    let mychart = echarts.init(document.getElementById('main'))
    let option ={
      xAxis: {
          type: 'category',
          boundaryGap: false,
          data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
      },
      yAxis: {
          type: 'value'
      },
      series: [{
          data: [820, 932, 901, 934, 1290, 1330, 1320],
          type: 'line',
          areaStyle: {}
      }]
  }

  // 必须调用setOption设置图表的配置
        mychart.setOption(option)
  }
  render () {
    let styles = {
      height: '300px',
      width: '300px'
    }
    return (
      <div>
        <div>测试图表echarts</div>
        {/*图表显示位置*/}
        <div id="main" style={styles}></div>
      </div>
    )
  }
} 

export default TestChart

在这里插入图片描述


结语

如果您觉得该方法或代码有一点点用处,可以给作者点个赞,或打赏杯咖啡;╮( ̄▽ ̄)╭
如果您感觉方法或代码不咋地//(ㄒoㄒ)//,就在评论处留言,作者继续改进;o_O???
如果您需要相关功能的代码定制化开发,可以留言私信作者;(✿◡‿◡)
感谢各位大佬童鞋们的支持!( ´ ▽´ )ノ ( ´ ▽´)っ!!!

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值