本篇大纲:基本散布图范例、进阶散布图范例
今天的一天一图表,我们要来画 散点图 / 散布图
!散布图适合用在以下几种情况:
除了呈现资料之外,也可以加上一些互动效果
今天我们就用这两个范例来实际绘制散点图吧!
我们先来建立一个最基本的散布图。一般来说,这种散布图的资料都是 raw data,就是几百几单一、没有经过统计的资料。这样一来才能将所有的单笔资料变成一个点,并於散布图呈现所有点点的分布情况。
我们今天使用的资料是 这个 ,确定资料後就可以开始画图啦!首先,我们先用async await 的方法串接API,拿到我们的资料;接着起手式一样是建立RWD的svg图表
// css
.scatter1 {
margin: auto;
width: 80%;
min-width: 300px;
margin: auto;
}
// html
<div class="scatter1 m-auto"></div>
// 先取资料
async function getData(){
let dataGet;
const cors = "https://secret-ocean-49799.herokuapp.com/";
const url = 'https://raw.githubusercontent.com/holtzy/data_to_viz/master/Example_dataset/2_TwoNum.csv'
dataGet = await d3.csv(`${cors}${url}`);
scatter1(dataGet)
}
getData()
// 建立图表
function scatter1(data){
// RWD 清除原本的图型
d3.select(".scatter1").select('svg').remove()
// 建立 svg
const svgWidth = parseInt(d3.select('.scatter1').style('width')),
svgHeight = svgWidth
margin = 50
const svg = d3.select('.scatter1')
.append('svg')
.attr('width', svgWidth)
.attr('height', svgHeight)
// 接下来的程序码...
// 接下来的程序码...
// 接下来的程序码...
}
// RWD
d3.select(window).on("resize", scatter1());
建立好 svg 後,我们开始绘制比例尺跟XY座标轴
// 建立X轴线
const xScale = d3.scaleLinear()
.domain([0,4000])
.range([0, (svgWidth - margin*2)])
const xAxis = d3.axisBottom(xScale)
svg.append('g')
.attr('transform', `translate(${margin}, ${svgHeight - margin/2})`)
.call(xAxis)
// 建立Y轴线
console.log(data)
const yScale = d3.scaleLinear()
.domain([0,500000])
.range([(svgHeight - margin), 0])
const yAxis = d3.axisLeft(yScale)
.tickFormat(d=>'$'+d)
svg.append('g')
.attr('transform', `translate(${margin}, ${margin/2})`)
.call(yAxis)
最後我们把资料绑定到 < circle >上
// 加上点点
svg.append('g')
.selectAll('dot')
.data(data)
.enter()
.append('circle')
.attr('cx', d => xScale(d.GrLivArea))
.attr('cy', d => yScale(d.SalePrice))
.attr('r', 1.5)
.style('fill', '#69b3a2')
这样就完成啦!
如果我们想把特定范围的资料设定成不同颜色,也可以这样做
// 加上点点
svg.append('g')
.selectAll('dot')
.data(data)
.enter()
.append('circle')
.attr('cx', d => xScale(d.GrLivArea))
.attr('cy', d => yScale(d.SalePrice))
.attr('r', 1.5)
// 将大於129000的点点都变成粉红色
.style('fill', d => {
return d.SalePrice > 129000? 'pink':'#69b3a2'
})
图表就变成这样!
这样就完成啦!散布图是不是很简单呢~接着我们再看看范例二的图表吧!
范例二画面与互动效果有:
scaleLinear
或 scalePoint
制作我们就按照这些列出效果来绘制散点图吧!首先,我们先建立 svg 跟座标轴
// css
.scatter1 {
margin: auto;
width: 80%;
min-width: 300px;
margin: auto;
}
// html
<div class="scatter2 m-auto"></div>
function scatter2(){
// 建立svg
let w = parseInt(d3.select(".scatter2").style("width")),
h = w*0.8,
margin = {
top: 40,
right: 20,
bottom: 20,
left: 40
},
radius = 5;
let svg = d3.select(".scatter2").append("svg").attr('width', w).attr('height', h);
console.log(w, h)
let dataset = [
{ x: 100,
y: 110 },
{ x: 83,
y: 43 },
{ x: 92,
y: 28 },
{ x: 49,
y: 74 },
{ x: 51,
y: 10 },
{ x: 25,
y: 98 },
{ x: 77,
y: 30},
{ x: 20,
y: 83 },
{ x: 11,
y: 63 },
{ x: 4,
y: 55 },
{ x: 0,
y: 0 },
{ x: 85,
y: 100 },
{ x: 60,
y: 40 },
{ x: 70,
y: 80 },
{ x: 10,
y: 20 },
{ x: 40,
y: 50 },
{ x: 25,
y: 31 }
];
// 接下来的程序码写在这边...
// 接下来的程序码写在这边...
// 接下来的程序码写在这边...
}
// RWD
d3.select(window).on("resize", scatter2());
接着建立比例尺与座标轴
// 建立X比例尺与轴线
const xScale = d3.scaleLinear()
.domain([0, d3.max(dataset, function (d) {
return d.x + 10;
})])
.range([margin.left, w - margin.right]);
const xAxis = d3.axisTop()
.scale(xScale)
const xAxisLine = svg.append('g')
.attr('class', 'xAxis')
.attr('transform', `translate(0, ${margin.top})`)
.call(xAxis)
// 建立Y比例尺与轴线
const yScale = d3.scaleLinear()
.domain([0, d3.max(dataset, function (d) {
return d.y + 10;
})])
.range([margin.top, h - margin.bottom])
const yAxis = d3.axisLeft()
.scale(yScale)
const yAxisLine = svg.append('g')
.attr('class', 'yAxis')
.attr('transform', `translate(${margin.left}, 0)`)
.call(yAxis)
建立好轴线跟比例尺後,开始把资料绑定到 < circle >上
// 资料绑定上circle
svg.selectAll("circle")
.data(dataset)
.enter()
.append("circle")
.attr('cx', function (d) {
return xScale(d.x);
})
.attr('cy', function (d) {
return yScale(d.y);
})
.attr('r', 5)
.attr('fill', '#000')
.on("mouseover", handleMouseOver)
.on("mouseout", handleMouseOut);
这时我们就会得到初步的散点图表了
再来,我们来进行滑鼠的互动设定吧~先来设定 mouseover 跟 mouseleave 的方法
// mouseover 时点点变色+tooltip
function handleMouseOver(d, i) {
// 选定this的元素,改变hover过去的颜色跟形状
d3.select(this)
.attr('fill', 'orange')
.attr('r', radius * 2);
// 加上tooltips
let pt = d3.pointer(event, this)
svg.append("text")
.attr('class', 'hoverTextInfo')
.attr('x', pt[0] + 10)
.attr('y', pt[1] - 10)
.style('fill', 'red')
.text([`x:${d.x}, y:${d.y}`])
}
// mouseleave 时变回原样
function handleMouseOut(d, i) {
d3.selectAll('.hoverTextInfo').remove()
d3.select(this)
.attr('fill', 'black')
.attr('r', radius)
}
接着设定滑鼠点击时,要纪录点击当下的座标,并将这个座标用 .invert
的方法换算成资料,再把这个新增的资料用push的方法推入原本的资料阵列
// 滑鼠click的时候增加一个点
svg.on("click", function () {
let coords = d3.pointer(event, this);
let newData = {
// 把XY座标轴转换成资料
x: Math.round(xScale.invert(coords[0])),
y: Math.round(yScale.invert(coords[1]))
};
// 将增加的资料座标推入原本的data
dataset.push(newData);
最後,我们要重新把更新过後的资料绑定到DOM上,同时把滑鼠over跟leave的方法也绑定上去
// 将新的资料绑定上circle、绑定 mouseover/mouseleave 方法
svg.selectAll("circle")
.data(dataset)
.enter()
.append("circle")
.attr('cx', function (d) {
return xScale(d.x);
})
.attr('cy', function (d) {
return yScale(d.y);
})
.attr('r', 5)
.attr('fill', '#000')
.on("mouseover", handleMouseOver)
.on("mouseout", handleMouseOut);
})
完成!!
这边附上本章的程序码与图表 Github 、 Github Page,需要的人请自行取用~
<<: Alpine Linux Porting (1.99) ES LEBT !!!
>>: 2021-Day28. Serverless(十 六):Deploy Ktor To Azure 的准备工作
大家好,我是长风青云。今天是铁人赛第四天。 今天我真的有点赶,我觉得我以後还是不要当天再开始好了。 ...
Day 17 - Android Studio Toggle按钮 昨天我们介绍了如何写一个简单的加减...
我们在上一篇的文章中,介绍了 Flow 的基本概念,包括如何建立一个 Flow,以及 Flow 是一...
本篇同步发布於个人Blog: [Refactoring] Chapter 1 Refactoring...
思考重点 如何将应用程序消息委托给协议栈发送? socket是调用那些函式进行收发操作? 核心知识 ...