起首你须要在盘算机上装置Node和npm。
数据的可视化示意是通报庞杂信息的最有用手腕之一,D3.js供应了建立这些数据可视化的壮大东西和灵活性。
D3.js是一个JavaScript库,用于运用SVG,HTML和CSS在Web浏览器中天生动态的交互式数据可视化。
在本教程中,我们将讨论怎样运用D3.js和Pusher Channels构建及时图形。假如您在浏览本教程时想要运用代码,请检察此GitHub存储库,个中包括代码的终究版本。
预备
要完本钱教程,您须要装置Node.js和npm。我在建立本教程时运用的版本以下:
- Node.js v10.4.1
- npm v6.3.0
您还须要在盘算机上装置http-server。它能够经由历程运转以下敕令经由历程npm装置:npm install http-server。
虽然不须要Pusher学问,但假如熟习它后,对进修JavaScript和D3.js会很有协助。
最先
起首,为我们要构建的运用程序建立一个新目次。将其称为及时图形或任何您喜好的图形。在新建立的目次中,建立一个新的index.html文件并粘贴以下代码:
//index.html
<!DOCTYPE html>
<hml lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<link rel="stylesheet" href="style.css">
<title>Realtime D3 Chart</title>
</head>
<body>
<script src="https://js.pusher.com/4.2/pusher.min.js"></script>
<script src="https://d3js.org/d3.v5.min.js"></script>
<script src="app.js"></script>
</body>
</html>
如您所见,HTML文件只是提取构建图形所需的款式和剧本。我们正在运用D3.js来构建图表,并运用Pusher来增加及时功用。app.js文件是运用程序前端代码的写入位置。
在我们最先完成图表之前,让我们在style.css中增加运用程序的款式:
// style.css
html {
height: 100%;
box-sizing: border-box;
padding: 0;
margin: 0;
}
*, *::before, *::after {
box-sizing: inherit;
}
body {
height: 100%;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif;
overflow: hidden;
background: linear-gradient(135deg, #ffffff 0%,#e8f1f5 100%);
}
.container {
position: absolute;
padding: 20px;
top: 50%;
left: 50%;
background-color: white;
border-radius: 4px;
transform: translate(-50%, -50%);
box-shadow: 0px 50px 100px 0px rgba(0,0,102,0.1);
text-align: center;
}
.container h1 {
color: #333;
}
.bar {
fill: #6875ff;
border-radius: 2px;
}
.bar:hover {
fill: #1edede;
}
.tooltip {
opacity: 0;
background-color: rgb(170, 204, 247);
padding: 5px;
border-radius: 4px;
transition: opacity 0.2s ease;
}
装置服务器依靠项
假定您装置了Node和npm,请运转以下敕令来装置运用程序的服务器组件所需的一切依靠项:
npm install express dotenv cors pusher
Pusher 设置
前去Pusher网站并注册一个免费帐户。挑选侧栏上的Channels apps,然后点击Create Channels app以建立新运用。
建立运用程序后,从API Keys选项卡中检索凭证,然后在项目目次根目次中建立一个variables.env文件,将以下内容增加到这个文件中。
// variables.env
PUSHER_APP_ID=<your app id>
PUSHER_APP_KEY=<your app key>
PUSHER_APP_SECRET=<your app secret>
PUSHER_APP_CLUSTER=<your app cluster>
设置服务器
如今我们已装置了相干的依靠项而且已设置了我们的Pusher帐户,我们能够最先构建服务器。
在项目目次的根目次中建立一个名为server.js的新文件,并粘贴以下代码:
// server.js
require('dotenv').config({ path: 'variables.env' });
const express = require('express');
const cors = require('cors');
const poll = [
{
name: 'Chelsea',
votes: 100,
},
{
name: 'Arsenal',
votes: 70,
},
{
name: 'Liverpool',
votes: 250,
},
{
name: 'Manchester City',
votes: 689,
},
{
name: 'Manchester United',
votes: 150,
},
];
const app = express();
app.use(cors());
app.get('/poll', (req, res) => {
res.json(poll);
});
app.set('port', process.env.PORT || 4000);
const server = app.listen(app.get('port'), () => {
console.log(Express running → PORT ${server.address().port});
});
保留文件并从项目目次的根目次运转节点server.js以启动服务器。
设置前端运用程序
运用程序的前端将写在我们之前援用的app.js文件中。在项目目次的根目次中建立此文件,并在个中粘贴以下代码:
// app.js
// set the dimensions and margins of the graph
const margin = { top: 20, right: 20, bottom: 30, left: 40 };
const width = 960 - margin.left - margin.right;
const height = 500 - margin.top - margin.bottom;
// set the ranges for the graph
const x = d3
.scaleBand()
.range([0, width])
.padding(0.1);
const y = d3.scaleLinear().range([height, 0]);
// append the container for the graph to the page
const container = d3
.select('body')
.append('div')
.attr('class', 'container');
container.append('h1').text('Who will win the 2018/19 Premier League Season?');
// append the svg object to the body of the page
// append a 'group' element to 'svg'
// moves the 'group' element to the top left margin
const svg = container
.append('svg')
.attr('width', width + margin.left + margin.right)
.attr('height', height + margin.top + margin.bottom)
.append('g')
.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');
// Create a skeleton structure for a tooltip and append it to the page
const tip = d3
.select('body')
.append('div')
.attr('class', 'tooltip');
// Get the poll data from the /poll endpoint
fetch('http://localhost:4000/poll')
.then(response => response.json())
.then(poll => {
// add the x Axis
svg
.append('g')
.attr('transform', 'translate(0,' + height + ')')
.attr('class', 'x-axis')
.call(d3.axisBottom(x));
// add the y Axis
svg
.append('g')
.attr('class', 'y-axis')
.call(d3.axisLeft(y));
update(poll);
});
function update(poll) {
// Scale the range of the data in the x axis
x.domain(
poll.map(d => {
return d.name;
})
);
// Scale the range of the data in the y axis
y.domain([
0,
d3.max(poll, d => {
return d.votes + 200;
}),
]);
// Select all bars on the graph, take them out, and exit the previous data set.
// Enter the new data and append the rectangles for each object in the poll array
svg
.selectAll('.bar')
.remove()
.exit()
.data(poll)
.enter()
.append('rect')
.attr('class', 'bar')
.attr('x', d => {
return x(d.name);
})
.attr('width', x.bandwidth())
.attr('y', d => {
return y(d.votes);
})
.attr('height', d => {
return height - y(d.votes);
})
.on('mousemove', d => {
tip
.style('position', 'absolute')
.style('left', ${d3.event.pageX + 10}px)
.style('top', ${d3.event.pageY + 20}px)
.style('display', 'inline-block')
.style('opacity', '0.9')
.html(
<div><strong>${d.name}</strong></div> <span>${d.votes} votes</span>
);
})
.on('mouseout', () => tip.style('display', 'none'));
// update the x-axis
svg.select('.x-axis').call(d3.axisBottom(x));
// update the y-axis
svg.select('.y-axis').call(d3.axisLeft(y));
}
在上面的代码块中,我们运用经由历程/ poll端点吸收的初始数据建立了一个基础条形图。假如您熟习D3的事情道理,那末您应当熟习这些代码。我在代码的症结部份增加相识释,以指点您构建图表的体式格局。
在新终端中,启动开辟服务器以供应index.html文件:
npx http-server
我在这里运用http-server,但你能够运用你想要的任何服务器。您以至能够直接在浏览器中翻开index.html。
此时,您的图表应以下所示:
运用Pusher及时更新图表
让我们确保轮询的更新能够经由历程Pusher Channels及时反映在运用程序的前端中。将以下代码粘贴到app.js文件的末端。
// app.js
const pusher = new Pusher('<your app key>', {
cluster: '<your app cluster>',
encrypted: true,
});
const channel = pusher.subscribe('poll-channel');
channel.bind('update-poll', data => {
update(data.poll);
});
在这里,我们翻开了与Channels的衔接,并运用Pusher的subscribe()要领定阅了一个名为poll-channel的新频道。经由历程bind要领监听轮询更新,并在收到更新后运用最新数据挪用update()函数,以便从新显现图形。
不要遗忘运用Pusher帐户信息中心中的响应详细信息替代占位符。
从服务器触发更新
我们将模仿每秒更新一次的轮询,并在数据发生变化时运用Pusher触发更新,以便轮询的定阅者(客户端)能够及时吸收更新的数据。
在其他导入下面的server.js顶部增加以下代码:
const Pusher = require('pusher');
const pusher = new Pusher({
appId: process.env.PUSHER_APP_ID,
key: process.env.PUSHER_APP_KEY,
secret: process.env.PUSHER_APP_SECRET,
cluster: process.env.PUSHER_APP_CLUSTER,
encrypted: true,
});
function getRandomNumber(min, max) {
return Math.floor(Math.random() * (max - min) + min);
}
function increment() {
const num = getRandomNumber(0, poll.length);
poll[num].votes += 20;
}
function updatePoll() {
setInterval(() => {
increment();
pusher.trigger('poll-channel', 'update-poll', {
poll,
});
}, 1000);
}
然后将/ poll端点更改成以下所示:
app.get('/poll', (req, res) => {
res.json(poll);
updatePoll();
});
/ poll路由将初始轮询数据发送到客户端并挪用updatePoll()函数,该函数以三秒为距离递增随机俱乐部的投票,并触发我们在末了一步中在客户端上建立的轮询频道的更新。
经由历程从项目目次的根目次运转节点server.js,停止服务器并从新启动它。此时,您应当有一个及时更新的条形图。
结论
您已看到了运用D3.js建立条形图的历程以及怎样运用Pusher Channels及时建立条形图。
我们已为Pusher和D3供应了一个简朴的用例,但个中一个仅仅是表面上的题目。我发起深入研究docs,相识更多有关Pusher及其他功用的信息。
感谢浏览!您能够在GitHub存储库中找到本教程的完全源代码。