d3-折線圖-中日GDP

1. 效果圖

2. code

<template lang='pug'>
    div.histogram-pane(:id='id')
        svg.histogram-container
            g.viewport
                
</template>
 
<script>
import * as d3 from 'd3'
import { Uuid } from '@/util/common'
export default {
    name: 'learn',
    data () {
        return {
            id: '',
            width: 0,
            height: 0,
            padding: null,
            dataSet: [
                { 
                    country: 'China',
                    gdp: [[2000, 11920], [2001, 13170], [2002, 14550], [2003, 16650], [2004, 19440], [2005, 22840], [2006, 27880],
                          [2007, 35040], [2008, 45470], [2009, 51050], [2010, 59540], [2011, 73140], [2012, 83860], [2013, 103550]]
                },
                { 
                    country: 'Japan',
                    gdp: [[2000, 47310], [2001, 41590], [2002, 43020], [2003, 46330], [2004, 46550], [2005, 45710], [2006, 43560],
                          [2007, 43560], [2008, 48490], [2009, 50350], [2010, 54950], [2011, 59050], [2012, 59370], [2013, 48980]]
                }
            ]
        }
    },
    created () {
        this.id = Uuid()
    },
    mounted () {
        let width = document.getElementById(this.id).clientWidth
        let height = document.getElementById(this.id).clientHeight
        this.padding = { top: 60, bottom: 60, left: 60, right: 60 }
        d3.select('svg').attr('width', width).attr('height', height)

        // 縮放
        const zoomed = function () {
            d3.select('svg')
                .select('g.viewport')
                .attr('transform', d3.event.transform)
        }
        const zoom = d3.zoom().on('zoom', zoomed)
        d3.select('svg')
        .call(zoom)
        .on('dblclick.zoom', null)
        // 繪畫
        this.draw(width, height)
    },
    methods: {
        draw (width, height) {
            let g = d3.select('g.viewport')
            // x 軸
            let xScale = d3.scaleLinear().domain([2000, 2013]).range([0, width - this.padding.left - this.padding.right])
            // tickFormat(d3.format('d')) 去掉字符串中的,
            let xAxis = d3.axisBottom(xScale).ticks(5).tickFormat(d3.format('d'))
            g.append('g')
                .attr('transform', 'translate(' + this.padding.left + ',' + (height - this.padding.bottom) + ')')
                .call(xAxis)
            // y 軸
            let maxGdp = this.getGdpMax()
            let yScale = d3.scaleLinear().domain([0, maxGdp * 1.1]).range([height - this.padding.top - this.padding.bottom, 0])
            let yAxis = d3.axisLeft(yScale)
            g.append('g')
                .attr('transform', 'translate(' + this.padding.left + ',' + this.padding.top + ')')
                .call(yAxis)

            // 線段生成器實現折線
            let colors = [d3.rgb(0, 0, 255), d3.rgb(0, 255, 0)]
            let linePaths = d3.line()
                .x(d => xScale(d[0]))
                .y(d => yScale(d[1]))
            g.append('g')
                .selectAll('path')
                .data(this.dataSet)
                .enter()
                .append('path')
                .attr('transform', 'translate(' + this.padding.left + ',' + this.padding.top + ')')
                .attr('d', d => linePaths(d.gdp))
                .attr('fill', 'none')
                .attr('stroke-width', 3)
                .attr('stroke', (d, i) => colors[i])

            // 底部按鈕
            let gs = g.append('g')
                .selectAll('rect')
                .data(this.dataSet)
                .enter()
            gs.append('text')
                .attr('transform', 'translate(' + this.padding.left + ',' + (height - this.padding.bottom + 35) + ')')
                .text(() => 'GDP:')
            gs.append('rect')
                .attr('transform', 'translate(' + (this.padding.left + 50) + ',' + (height - this.padding.bottom + 20) + ')')
                .attr('width', '20')
                .attr('height', '20')
                .attr('fill', (d, i) => colors[i])
                .attr('x', (d, i) => {
                    return i === 0 ? '0' : '100'
                })
            gs.append('text')
                .attr('transform', 'translate(' + (this.padding.left + 50) + ',' + (height - this.padding.bottom + 35) + ')')
                .attr('fill', (d, i) => colors[i])
                .text((d, i) => this.dataSet[i].country)
                 .attr('x', (d, i) => {
                    return i === 0 ? '25' : '125'
                })
        },
        getGdpMax () {
            let gdpMax = 0
            for (let index = 0; index < this.dataSet.length; index++) {
                const item = this.dataSet[index]
                let currentGdp = d3.max(item.gdp, d => d[1])
                if (currentGdp > gdpMax)
                    gdpMax = currentGdp
            }

            return gdpMax
        }
    }
}
</script>
 
<style lang='scss' scoped>
.histogram-pane {
  width: 100%;
  height: 100%;
}
.histogram-container {
  width: 100%;
  height: 100%;
}
</style>

 

 

發佈了71 篇原創文章 · 獲贊 28 · 訪問量 3萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章