zoukankan      html  css  js  c++  java
  • Vue整合d3.v5.js制作--折线图(line)

    先上效果图(x轴固定为时间轴):

    图中出现的悬浮框是鼠标悬停效果

    1、环境说明:

    vue版本:"vue": "^2.5.2"
    d3版本:"d3": "^5.9.1"

    2、Line.vue源码

      1 <template>
      2   <div class="d3line" :id="id">
      3   </div>
      4 </template>
      5 
      6 <script>
      7   import * as d3 from 'd3'
      8   export default {
      9     name: 'd3line',
     10     props: {
     11       id: String,
     12        Number,
     13       height: Number,
     14       dataset: Array
     15     },
     16     mounted() {
     17       this.init();
     18     },
     19     methods: {
     20       init() {
     21         d3.select("#svg" + this.id).remove();
     22         let width = this.width ? this.width : 600;
     23         let height = this.height ? this.height : 600;
     24         let padding = {
     25           left: 80,
     26           right: 50,
     27           top: 50,
     28           bottom: 50
     29         }
     30         let colorZ = d3.scaleOrdinal(d3.schemeDark2)
     31         let parseTime = d3.timeParse("%Y-%m-%d")
     32         let xScale = d3.scaleTime().range([0, width - padding.left - padding.right])
     33         let dates = this.dataset.flatMap((d) => d.value.map(v => parseTime(v.key)))
     34         xScale.domain([d3.min(dates), d3.max(dates)])
     35         let yScale = d3.scaleLinear().range([height - padding.top - padding.bottom, 0])
     36         yScale.domain([0, d3.max(this.dataset.flatMap((d) =>  d.value.map( v => v.value) )) + 2])
     37         let xAxis = d3.axisBottom(xScale).tickFormat(d => d.getFullYear() + '-' + (d.getMonth() + 1) + '-' + d.getDate())
     38         let yAxis = d3.axisLeft(yScale)
     39         let svg = d3.select("#" + this.id).append("svg").attr("width", width).attr("height", height).attr("id", "svg" + this.id);
     40         svg.append('g')
     41           .attr('transform', 'translate(' + padding.left + ',' + (height - padding.bottom) + ')')
     42           .call(xAxis)
     43           .selectAll('text')
     44           .attr('dx', -20)
     45           .attr('dy', 10)
     46           .attr('transform', 'rotate(-20)')
     47           .style('font-weight', 'bold')
     48         svg.append('g')
     49           .attr('transform', 'translate(' + padding.left + ',' + padding.top + ')')
     50           .call(yAxis)
     51           .selectAll('text')
     52           .style('font-weight', 'bold')
     53         let line = d3.line().x(d => xScale(parseTime(d.key))).y(d => yScale(d.value))
     54         this.dataset.forEach((v, vi) => {
     55           let tp_x = 0,
     56             tp_y =0;
     57           svg.append("path")
     58             .attr('d' , line(v.value))
     59             .attr('transform', 'translate(' + padding.left + ',' + padding.top + ')')
     60             .attr('fill', 'none')
     61             .attr('stroke', (d, i) => colorZ(vi))
     62             .attr("stroke-width", 2)
     63             .style('stroke-dasharray', function(d, i) {
     64               return d3.select(this).node().getTotalLength();
     65             })
     66             .style('stroke-dashoffset', function(d, i) {
     67               return d3.select(this).node().getTotalLength();
     68             })
     69             .transition()
     70             .duration(2000)
     71             .ease(d3.easePolyOut)
     72             .delay((d, i) => i * 200)
     73             .style('stroke-dashoffset', 0)
     74           svg.selectAll('circle1')
     75             .data(v.value)
     76             .enter()
     77             .append('circle')
     78             .attr('cx', (d, i) => {
     79               let x = xScale(parseTime(d.key))
     80               if (i === v.value.length - 1) tp_x = x - 40
     81               return x
     82             })
     83             .attr('cy', (d, i) => {
     84               let y = yScale(d.value)
     85               if (i === v.value.length - 1) tp_y = y - 10
     86               return y
     87             })
     88             .attr('r', 2)
     89             .attr('transform', 'translate(' + padding.left + ',' + padding.top + ')')
     90             .style("fill", (d, i) => colorZ(vi))
     91             .on("mouseover", (d, i) => {
     92               let g = svg.append('g')
     93                 .attr('id', `hoverg${vi}${d.key}${d.value}`)
     94                 .attr("transform", "translate(" + (xScale(parseTime(d.key)) - 20) + "," + (yScale(d.value) + 30)  + ")" )
     95               g.append("rect")
     96                 .attr("x", function(d){ return this.parentNode.getBBox().x - 3;})
     97                 .attr("y", function(d, i){ return  this.parentNode.getBBox().y - 20})
     98                 .attr("width", 110)
     99                 .attr("height", 25)
    100                 .style("fill", "#fffbf0")
    101               g.append('text')
    102                 .text(`${d.key}:${d.value}`)
    103                 .style("fill", colorZ(vi))
    104             })
    105             .on("mouseout", (d) => d3.select(`#hoverg${vi}${d.key}${d.value}`).remove())
    106             .transition()
    107             .duration(1500)
    108             .ease(d3.easePolyIn)
    109             .delay((d, i) => i * 200)
    110             .attr('r', 5)
    111           // svg.selectAll('text1')
    112           //   .data([v.name])
    113           //   .enter()
    114           //   .append('text')
    115           //   .attr('dx', (d, i) => tp_x)
    116           //   .attr('dy', (d, i) => tp_y)
    117           //   .attr('transform', 'translate(' + padding.left + ',' + padding.top + ')')
    118           //   .text((d) => d)
    119           //   .style("fill", (d, i) => colorZ(vi))
    120           //   .style('font-weight', 'bold')
    121           svg.append('text')
    122             .attr('dx', tp_x)
    123             .attr('dy', tp_y)
    124             .attr('transform', 'translate(' + padding.left + ',' + padding.top + ')')
    125             .text(v.name)
    126             .style("fill", colorZ(vi))
    127             .style('font-weight', 'bold')
    128         })
    129       }
    130     },
    131     watch: {
    132       dataset() {
    133         this.init();
    134       }
    135     }
    136   }
    137 </script>
    138 
    139 <style>
    140 
    141 </style>

    3、使用示例

     1 <template>
     2   <div id="test">
     3     <!-- 一定要传进去一个id,随便传一个 -->
     4     <d3line id="line" :dataset="data1"></d3line>
     5   </div>
     6 </template>
     7 
     8 <script>
     9   import d3line from '@/components/d3/Line'
    10   export default {
    11     name: 'test',
    12     data() {
    13       return {
    14         data1: [
    15           {
    16             'name': '哈尔滨',
    17             'value': [{key: '2015-1-1', value: 10}, {key: '2015-1-2', value: 12}, {key: '2015-1-3', value: 13}, {key: '2015-1-17', value: 17}]
    18           },
    19           {
    20             'name': '海南',
    21             'value': [{key: '2015-1-1', value: 9}, {key: '2015-1-2', value: 48}, {key: '2015-1-3', value: 5}, {key: '2015-1-17', value: 49}]
    22           },
    23           {
    24             'name': '天津',
    25             'value': [{key: '2015-1-2', value: 30}, {key: '2015-1-3', value: 1}, {key: '2015-1-4', value: 32}, {key: '2015-1-5', value: 10}]
    26           }
    27         ]
    28       }
    29     },
    30     components: {
    31       d3line
    32     },
    33     methods: {
    34 
    35     }
    36   }
    37 </script>
    38 
    39 <style scoped>
    40 </style>

    4、参考资料

    https://github.com/d3/d3-scale-chromatic/blob/master/README.md#schemeCategory10

    https://github.com/d3/d3-time-format#format

    https://jakearchibald.com/2013/animated-line-drawing-svg/

  • 相关阅读:
    webNav
    keyBoardValue
    认证,权限,频率
    路由组件与视图集中附加action的声明
    视图组件
    请求与响应
    DRF序列化组件
    DRF入门及安装
    后台管理
    auth认证模块
  • 原文地址:https://www.cnblogs.com/floud/p/10684839.html
Copyright © 2011-2022 走看看