1. 程式人生 > >D3.js的V5版本-Vue框架中使用(第六章) ---互動式操作

D3.js的V5版本-Vue框架中使用(第六章) ---互動式操作

一. Api使用

on("eventName",function);該函式是新增一個監聽事件,它的第一個引數是事件型別,第二個引數是響應事件的內容

d3.select(this), 選擇當前元素

   常見的事件型別

  • click:滑鼠單擊某元素時觸發,相當於mousedown和mouseup的組合
  • mouseover:滑鼠放在某元素上觸發
  • mouseout:滑鼠移出某元素時觸發
  • mousemove:滑鼠移動時觸發
  • mousedown:滑鼠按鈕被按下時觸發
  • mouseup:滑鼠按鈕被鬆開時觸發
  • dblclick:滑鼠雙擊時觸發

當然還有很多,上面列出來的只是關於滑鼠監聽事件,還有鍵盤等的監聽事件,在這裡就不多講了

二.Vue使用

<template lang='pug'>
    div.interactive-pane(:id="id")
        svg 
</template>

<script>
/**
 * 互動式操作
 */
import * as d3 from 'd3'
export default {
    name: '',
    data () {
        return {
            id: ''
        }
    },
    methods: {
        uuid () {
            function s4 () {
                return Math.floor((1 + Math.random()) * 0x10000)
                    .toString(16)
                    .substring(1)
            }
            return (
                s4() + s4() + '-' + s4() + '-' + s4() +  '-' + s4() + '-' + s4() + s4() + s4()
            )
        },
    },
    created () {
        this.id = this.uuid()
    },
    mounted () {
        //1.建立svg畫布
        let marge = { top: 60, bottom: 60, left: 60, right: 60 }
        let width = document.getElementById(this.id).clientWidth
        let height = document.getElementById(this.id).clientHeight
        const svg = d3.select(this.$el).select('svg').attr('width', width).attr('height', height)
        let g = svg.append('g').attr('transform', 'translate(' + marge.top + ',' + marge.left + ')')
        //2.資料集
        let dataset = [10, 20, 30, 23, 13, 40, 27, 35, 20, 33];
        //3.座標軸
        //x軸序數比例尺(d3.scaleBand()並不是一個連續性的比例尺,domain()中使用一個數組,不過range()需要是一個連續域)
        let ranges = d3.range(dataset.length)
        let xcale = d3.scaleBand().domain(ranges).range([0, width - marge.left - marge.right])
        let xAxis = d3.axisBottom(xcale)
        g.append('g')
            .attr('transform', 'translate(' + 0 + ',' + (height - marge.top - marge.bottom) + ')')
            .call(xAxis)
        //y軸線性比例尺
        let yscale = d3.scaleLinear().domain([0, d3.max(dataset)]).range([height - marge.top - marge.bottom, 0])
        let yAxis = d3.axisLeft(yscale)
        g.append('g')
            .attr('transform', 'translate(0, 0)')
            .call(yAxis)
        //4.為每個矩形和對應的文字建立一個分組<g>
        let gs = g.selectAll('rect')
            .data(dataset)
            .enter()
            .append('g')
        //5.繪製矩形
        //設定矩形之間的間隙
        let rectPadding = 20 
        gs.append('rect')
            .attr('x', function(d, i) {
                //xcale(i): 畫布真實寬度(48)橫座標且從0開始, 0, 48, 96 ... 432
                return xcale(i) + rectPadding/2
            })
            .attr('width', function() {
                //xcale.step() 畫布真實寬度(48):width-marge.left-marge.right/dataset.lenght
                return xcale.step() - rectPadding
            })
            .attr('y', function(d){
                return yscale(d)
            })
            .attr('height', function(d){
                return height - marge.top - marge.bottom - yscale(d)
            })
            .attr('fill', 'blue')
            .on("mouseover",function(){
                let rect = d3.select(this)
                    .transition()
                    .duration(1500)
                    .attr("fill","yellow");
            })
            .on("mouseout",function(){
                let rect = d3.select(this)
                    .transition()
                    .delay(1500)
                    .duration(1500)
                    .attr("fill","blue");
            })
        
        //6.繪製文字
        gs.append('text')
            .attr('x', function(d, i) {
                return xcale(i) + rectPadding/2
            })
            .attr('width', function() {
                return xcale.step() - rectPadding
            })
            .attr('y', function(d) {
                return yscale(d);
            })
    }
}
</script>

<style lang="scss" scoped>
.interactive-pane {
    width: 100%;
    height: 1000px;
}
</style>