d3-動畫

1.效果圖

小球會從(0,0)位置過渡到最終的位置,顯示動畫效果,點擊更新、增加、減少按鈕能看到具體呈現的動畫效果!

2. 代碼

<template lang='pug'>
    div.histogram-pane(:id='id')
        <div class="btn-pane">
            <button @click="update">更新</button>
            <button @click="add">增加</button>
            <button @click="sub">減少</button>
        </div>
        svg.histogram-container
            g.viewport
</template>
 
<script>
import * as d3 from 'd3'
import { Uuid } from '@/util/common'
export default {
    name: 'anmition',
    data () {
        return {
            id: '',
            width: 0,
            height: 0,
            padding: null,
            gCircle: null,
            xScale: null,
            yScale: null,
            dataSet: [[0.5, 0.5], [0.7, 0.8], [0.4, 0.9], [0.11, 0.32], [0.88, 0.25], [0.75, 0.12], [0.5, 0.1], [0.2, 0.3], [0.4, 0.1], [0.6, 0.7]]
        }
    },
    created () {
        this.id = Uuid()
    },
    mounted () {
        this.width = document.getElementById(this.id).clientWidth
        this.height = document.getElementById(this.id).clientHeight
        this.padding = { top: 30, bottom: 30, left: 30, right: 30 }
        d3.select('svg').attr('width', this.width).attr('height', this.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()
    },
    methods: {
        draw () {
            let g = d3.select('g.viewport')
            // 比例尺
            let xAxisWidth = 500, yAxisWidth = 450
            let xScale = d3.scaleLinear().domain([0, 1]).range([0, xAxisWidth])
            let yScale = d3.scaleLinear().domain([0, 1]).range([yAxisWidth, 0])
            this.xScale = xScale
            this.yScale = yScale
            // 繪製比例尺
            let xAxis = d3.axisBottom(xScale)
            g.append('g')
                .attr('transform', 'translate(' + this.padding.left + ',' + (this.height - this.padding.bottom) + ')')
                .call(xAxis)
            let yAxis = d3.axisLeft(yScale)
            g.append('g')
                .attr('transform', 'translate(' + this.padding.left + ',' + (this.height - this.padding.bottom - yAxisWidth) + ')')
                .call(yAxis)
            
            this.gCircle = g.append('g').attr('class', 'circle')
            this.drawCircle()
        },
        drawCircle () {
            // 綁定數據,獲取update
            let circleUpdate = this.gCircle.selectAll('circle').data(this.dataSet)
            // 獲取enter部分
            let circleEnter = circleUpdate.enter()
            // 獲取exit部分
            let circleExit = circleUpdate.exit()
            // 1. update 處理(啓動過渡)
            circleUpdate.transition()
                .duration(500)
                .attr('cx', d => this.padding.left + this.xScale(d[0]))
                .attr('cy', d => this.height - this.padding.bottom - this.yScale(d[1]))

            // 2. enter 處理
            circleEnter.append('circle')
                .attr('fill', 'black')
                .attr('cx', this.padding.left)
                .attr('cy', this.height - this.padding.bottom)
                .attr('r', 7)
                .transition()
                .duration(500)
                .attr('cx', d => this.padding.left + this.xScale(d[0]))
                .attr('cy', d => this.height - this.padding.bottom - this.yScale(d[1]))

            // 3. exit 處理
            circleExit.transition()
                .duration(500)
                .attr('fill', 'white')
                .remove()
        },
        update () {
            for (let i = 0; i < this.dataSet.length; i++) {
                this.dataSet[i][0] = Math.random()
                this.dataSet[i][1] = Math.random()
            }
            this.drawCircle()
        },
        add () {
            this.dataSet.push([Math.random(), Math.random()])
            this.drawCircle()
        },
        sub () {
            this.dataSet.pop()
            this.drawCircle()
        }  
    }
}
</script>
 
<style lang='scss' scoped>
.histogram-pane {
  width: 100%;
  height: 100%;
}
.histogram-container {
  width: 100%;
  height: 100%;
}
.btn-pane {
    position: absolute;
    left: 20px;
    top: 20px;
}
</style>

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章