最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • D3基础03 - 比例尺与坐标轴

    正文概述 掘金(普通上班族)   2021-01-06   1351

    D3基础03 - 比例尺与坐标轴

    我们可以利用D3提供的比例尺、坐标轴以及绘图功能,实现一个简单的柱状图。并且通过增加鼠标事件、transition动画和缓动动画来优化柱状图的用户体验,接下来我们逐步看一下如何实现柱状图。

    D3基础03 - 比例尺与坐标轴

    比例尺

    D3的比例尺功能可以让我们自由的建立起一个坐标系统,并设置每一个坐标轴的分量大小,同时可以让坐标轴的刻度与画布坐标轴的像素点对应起来。

    坐标轴的刻度可以分成两种:

    • 类目型坐标轴:坐标轴是由不连续的元素组成,如[张三,李四,王五]
    • 数值型坐标轴:坐标轴是由连续的数值组成,如[0,1,2],这里指的是数组,不是数学上的区间,这一点需要区分开,后续以中括号出现的数值对都是数组。

    因此比例尺规则也就与之对应的有两种:

    • scaleBand 类目轴型比例尺规则
    • scaleLinear 数值轴型比例尺规则

    利用比例尺建立x坐标轴

    • x轴是类目型坐标轴
    • 首先需要获取x轴数据的长度并将每个数据的索引存储起来
    • 然后设置x坐标轴起始和结束的坐标轴像素位置
    • 然后利用比例尺将数据与坐标轴刻度对应起来
    • 基于x轴比例尺建立x轴坐标生成器
    • 调用生成器绘制x轴,并将数据填充进去。

    废话不多说,我们还是用代码说话:

    /*===========1-必备数据===========*/
    /*categories 类目数据*/
    const categories = ['html', 'css', 'js'];
    
    /*===========2-建立容器对象===========*/
    /*获取main 容器*/
    const main = d3.select('#main')
    
    /*声明绘图框尺寸
        width 宽度,600
        height 高度,600
    */
    const width = 600
    const height = 600
    
    /*建立svg 对象
     *   svg 画布尺寸100%充满容器对象
     *   绘图框尺寸按照600设置
     * */
    const svg = main.append('svg')
        .attr('version', 1.2)
        .attr('xmlns', 'http://www.w3.org/2000/svg')
        .attr('width', '100%')
        .attr('height', '100%')
        .attr('viewBox', `0 0 ${width} ${height}`)
    
    /*===========3-建立基础数据===========*/
    /*计算类目数量 len*/
    const len = categories.length
    
    /*用range()方法,基于类目数量,获取x轴的在图表坐标系中的数据 xChartData,如[0,1,2]*/
    const xChartData = d3.range(len)
    console.log('xChartData', xChartData);
    
    /*x轴在像素坐标内的起始点和结束点 xPixelRange,左右各偏移50*/
    const xPixelRange = [50, width - 50]
    
    /*===========4-建立x 轴比例尺 xScale===========*/
    /*
     * 用scaleBand()方法建立分段比例尺 xScale
     * 用domain()方法在比例尺中写入图表数据xChartData
     * 用rangeRound()方法在比例尺中写入像素数据,即像素的起始位和结束位xPixelRange
     * */
    const xScale = d3.scaleBand()
        .domain(xChartData)
        .rangeRound(xPixelRange)
    console.log('xScale', xScale)
    /*===========5-建立x 轴对象===========*/
    /*基于比例尺xScale,用axisBottom()方法创建刻度朝下的坐标轴生成器 xAxisGenerator*/
    const xAxisGenerator = d3.axisBottom(xScale)
    
    /*利用坐标轴生成器绘制坐标轴
     *   在svg中append 加入g 对象
     *   用transform 属性中的translate设置x轴的y位置
     *   用call()方法调用xAxisGenerator轴生成器,生成坐标轴
     *   用selectAll()方法选择所有的text文本
     *   用text()方法将图表数据设置为类目数据
     *   用attr()方法设置字体大小
     * */
    svg.append('g')
        .attr('transform', `translate(0,${height-50})`)
        .call(xAxisGenerator)
        .selectAll('text')
        .text(d => categories[d])
        .style('font-size', '12px')
    

    利用比例尺建立y坐标轴

    虽然y轴是数值型,但是整体思路与x轴的绘制一致,唯一需要注意的一点是:像素坐标轴的y轴方向和我们绘制的y轴方向相反,因此在建立比例尺时要注意对应关系。

    D3基础03 - 比例尺与坐标轴

    /*===========1-必备数据===========*/
    /*数据源source:两个系列的数据*/
    const source = [
        //html css js
        [30, 20, 40], //学习人数
        [40, 30, 50] //就业人数
    ]
    
    /*===========1-建立容器对象===========*/
    /*获取main 容器*/
    const main = d3.select('#main')
    
    /*声明绘图框尺寸
        width 宽度,600
        height 高度,600
    */
    const width = 600
    const height = 600
    
    /*建立svg 对象
     *   svg 画布尺寸100%充满容器对象
     *   绘图框尺寸按照600设置
     * */
    const svg = main.append('svg')
        .attr('version', 1.2)
        .attr('xmlns', 'http://www.w3.org/2000/svg')
        .attr('width', '100%')
        .attr('height', '100%')
        .attr('viewBox', `0 0 ${width} ${height}`)
    
    /*===========3-建立基础数据===========*/
    /*计算数据源中所有数据的极值 maxY
     *   用js原生方法flat()展开数据源,再通过max()方法取极值
     * */
    const maxY = Math.max(...source.flat())
    console.log('maxY', maxY);
    
    /*声明y轴在图表坐标系中的数据起点和结束点 yChartRange*/
    const yChartRange = [0, maxY]
    
    /*声明y轴在像素坐标系中的数据起点和结束点 yPixelRange*/
    const yPixelRange = [height - 50, 50]
    
    /*===========4-建立y 轴比例尺 yScale===========*/
    /*
     * 用scaleLinear()方法建立线性比例尺 yScale
     * 用domain()方法在比例尺中写入图表数据yChartRange
     * range()方法在比例尺中写入像素数据,即像素的起始位和结束位yPixelRange
     * */
    const yScale = d3.scaleLinear()
        .domain(yChartRange)
        .range(yPixelRange)
    
    /*===========5-建立y 轴对象===========*/
    /*基于比例尺yScale,用axisLeft()方法创建刻度朝左的坐标轴生成器 yAxisGenerator*/
    const yAxisGenerator = d3.axisLeft(yScale)
    
    /*利用坐标轴生成器生成坐标轴
     *   在svg中append 加入g 对象
     *   用transform 属性中的translate设置y轴的x位置
     *   用call()方法调用xAxisGenerator轴生成器,生成坐标轴
     *   用style()方法设置字体大小
     * */
    svg.append('g')
        .attr('transform', 'translate(50 0)')
        .call(yAxisGenerator)
        .style('font-size', '12px')
    

    绘制图表

    上面我们已经成功建立起了坐标系,接下来离成功就只有一步了:绘图。

    • 初始化绘图相关数据
      • 获取到x轴每个类目的像素宽度(HTML、CSS、JS)
      • 获取到系列的长度(就业人数、学习人数)
      • 两个相除,得到每个类目下每个系列所占的x轴像素宽度。
    • 构建绘图区域 g ——只是搭建了绘图区域框架,到这一步是还没有图形绘制出来
      • 创建好绘图区域集合,并将类目数据绑定到每个集合
      • 设置未来会填充到 g 内的每一个柱状体x轴坐标起始像素位置
      • 设置填充颜色
    • 构建矩形集合 rect ——只是创建了柱状体集合和对象,但是没有设置属性
      • 创建好柱状体集合,并将系列数据绑定到每个合集
      • 在每个 g 元素内批量穿件 rect 元素
    • 设置每个柱状体的属性
    /*===========6-建立绘图区相关的基础数据===========*/
    /*-----绘图区相关的基础数据-----*/
    /*用x轴比例尺xScale的bandwidth()方法获取x轴上一个类目的像素宽xBandW*/
    const xBandW = xScale.bandwidth()
    console.log('xBandW', xBandW);
    /*获取系列的数量n*/
    const n = source.length
    
    /*用类目宽除以系列数,得到一个类目中每个系列元素的宽,即列宽colW*/
    const colW = xBandW / n
    console.log('colW', colW);
    
    /*计算调色盘颜色数量colorLen*/
    const colorLen = color.length
    
    /*===========7-架构绘图区===========*/
    /*在svg中建立系列集合seriesObjs,在系列集合中建立系列对象
     *   在svg中append 加入g 对象
     *   selectAll() 选择所有g元素,此处重点不在选择,而是建立一个选择集对象
     *   用data() 方法将具备系列信息的数据源source绑定到系列集合中
     *   用join() 基于数据源批量创建g元素,一个g代表一个系列,之后每个g元素里都会放入三个不同类目的柱状体
     *   用transform 属性中的translate设置系列的x像素位——列宽乘以系列索引
     *   基于系列索引,从调色盘中取色,然后将其作为一个系列中所有图形的填充色
     * */
    const seriesObjs = svg.append('g')
        .selectAll('g')
        .data(source)
        .join('g')
        .attr('transform', (seriesData, seriesInd) => {
            const seriesX = colW * seriesInd
            return `translate(${seriesX},0)`
        })
        .attr('fill', (seriesData, seriesInd) => color[seriesInd % colorLen])
    
    /*在系列集合中建立柱状体集合rects
     *   用系列集合seriesObjs 的selectAll()方法选择所有的rect元素,用于建立选择集对象
     *   用data()方法将之前绑定在每个系列集合中的数据绑定到柱状体集合中
     *   用join()基于每个系列的数据数据批量创建rect元素
     *   用classed() 方法为其添加item属性
     * */
    const rects = seriesObjs.selectAll('rect')
        .data(seriesData => seriesData)
        .join('rect')
        .classed('item', true)
    
    console.log('rects', rects);
    /*=8-用attr()方法设置每个柱状体的x、y位置和width、height 尺寸=*/
    /*
     * 设置柱状体的x像素位
     *   从回调参数中获取柱状体在当前系列中的索引rectInd,系列索引 seriesInd
     *   基于柱状体在当前系列中的索引rectInd,用x轴比例尺xScale()获取柱状体在当前系列中的x像素位
     * 设置柱状体像素宽width为列宽colW
     * 设置柱状体的y像素位
     *   从回调参数中解构柱状体数据rectData
     *   基于柱状体数据rectData,用y轴比例尺yScale()获取柱状体的y像素位
     * 设置柱状体的像素像素高
     *   从回调参数中解构柱状体数据rectData
     *   让y轴上刻度为0的像素位,减去刻度为柱状图实际数据的像素位,即为柱状图的像素高
     * */
    rects.attr('x', (rectData, rectInd) => xScale(rectInd))
        .attr('width', colW)
        .attr('y', rectData => yScale(rectData))
        .attr('height', rectData => yScale(0) - yScale(rectData))
    

    到这里,就成功建立起一个直观的柱状图,后续还可以用过添加transition动画、缓动动画、鼠标事件让这个柱状图用户体验更好、更炫酷(这个留到出差回来之后再写)


    起源地下载网 » D3基础03 - 比例尺与坐标轴

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元