🎈🎈🎈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
- 1.2 ECharts
- 1.3 React
- 2、安装
- 2.1 安装node
- 2.2 安装echarts
- 2.3 安装React
- 2.3.1 CDN库方式
- 2.3.2 npm方式
- 3、测试(React)
- 3.1 修改App.js(hello world)
- 3.2 修改index.js(hello world)
- 3.3 修改index.js(定时器)
- 3.4 修改index.js(按钮button)
- 3.5 修改index.js(请求AJAX)
- 3.6 修改index.js(请求fetch)
- 3.7 修改index.js(Markdown 库)
- 4、测试(React+Echarts)
- 4.1 修改App.js(Echarts例子: 柱状图)
- 4.2 修改App.js(ECharts例子:折线图)
- 4.3 修改App.js(ECharts例子:饼状图)
- 4.4 修改App.js(ECharts例子:玫瑰图)
- 4.5 修改App.js(ECharts例子:面积图)
- 结语
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???
如果您需要相关功能的代码定制化开发,可以留言私信作者;
(✿◡‿◡)
感谢各位大佬童鞋们的支持!
( ´ ▽´ )ノ ( ´ ▽´)っ!!!