用D3js的區域生成器實現簡單波浪圖


最近做控件遇到含有波浪圖的圖表,一開始用Echarts雖然很快完成了,但Echarts的波浪圖與其他圖表的響應式不同步,於是學習了D3js,D3js寫起來確實復雜一些,但能夠實現的效果也更豐富,做的時候查了不少資源,講真的,網上教程挺少的,很多都重復,我分享下我的方法。

先看一下效果:
water

我只做了簡單的效果,想控制波浪的流速、高度就跟據應用場景自己設計,我在控件中是用比例尺。
D3中有一種叫區域生成器的東西,可以生成一個上方是不規則形狀,其余三邊都是直線的區域,主要就圍繞這個來做。
先定義一個畫布

    var width = 200;           
    var height = 500;          

    
    var svg = d3.select("#body")
        .append("svg")
        .attr("width", width)
        .attr("height", height)

然后用數組控制波浪的形狀

var values = 0
var dataList0 = [values - 2, values - 3, values - 4, values - 3, values - 2, values - 1, values, values - 1]

網上的50行代碼的版本大家應試都看到過,是將數組的每一個數組放到最后,循環這個操作就可以了,本人比較小白,有幾個地方看不懂,所以用了比較直觀的方法,多定義些數組

var values = 0
var dataList0 = [values - 2, values - 3, values - 4, values - 3, values - 2, values - 1, values, values - 1]
var dataList1 = [values - 3, values - 4, values - 3, values - 2, values - 1, values, values - 1, values - 2]
var dataList2 = [values - 4, values - 3, values - 2, values - 1, values, values - 1, values - 2, values - 3]
var dataList3 = [values - 3, values - 2, values - 1, values, values - 1, values - 2, values - 3, values - 4]
var dataList4 = [values - 2, values - 1, values, values - 1, values - 2, values - 3, values - 4, values - 3]
var dataList5 = [values - 1, values, values - 1, values - 2, values - 3, values - 4, values - 3, values - 2]
var dataList6 = [values, values - 1, values - 2, values - 3, values - 4, values - 3, values - 2, values - 1]
var dataList7 = [values - 1, values - 2, values - 3, values - 4, values - 3, values - 2, values - 1, values]

現在我們把區域生成器放上去,網上很多教程都是v3的,生成時用的 d3.svg.area() ,新版本是 d3.area() 曲線用的是 .interpolate("basis") ,新的版本是 .curve(d3.curveBasis)

var areaPath = d3.area()
        .x(function (d, i) { return i * 20 })
        .y0(function (d, i) { return height / 2 })
        .y1(function (d, i) { return - d  })
        .curve(d3.curveBasis)

最后加屬性,並讓數組波浪起來

function run() {
        svg.append("path")
            .attr("d", areaPath(dataList0))
            .attr("fill", "rgba(0,118,184,.4)")

            .transition().duration(100).delay(0).ease(d3.easeLinear)
            .attr("d", areaPath(dataList1))

            .transition().duration(100).delay(0).ease(d3.easeLinear)
            .attr("d", areaPath(dataList2))

            .transition().duration(100).delay(0).ease(d3.easeLinear)
            .attr("d", areaPath(dataList3))

            .transition().duration(100).delay(0).ease(d3.easeLinear)
            .attr("d", areaPath(dataList4))

            .transition().duration(100).delay(0).ease(d3.easeLinear)
            .attr("d", areaPath(dataList5))

            .transition().duration(100).delay(0).ease(d3.easeLinear)
            .attr("d", areaPath(dataList6))

            .transition().duration(100).delay(0).ease(d3.easeLinear)
            .attr("d", areaPath(dataList7))

            .transition().duration(100).delay(0).ease(d3.easeLinear)
            .attr("d", areaPath(dataList0))

            .remove()
            .on('end', run)

    }
    requestAnimationFrame(run);

不建議用計時器, requestAnimationFrame(run) 配合 on('end', run) 的效果更好,.remove() 是讓刪除之前的動畫,ease(d3.easeLinear) 一定要加,會讓動畫看上去更流暢,不加就是幻燈片-_-b

用同樣的方式再做一個,設置不同透明度即可完效果,如果讓液位高度變化,可在y1()中加入三元運算,不過這個方法有三個缺點,一是會有2次明顯的跳動,二是如果上升或下降的速度太快,過程中液面是傾斜的,三是雙層液面時同樣的值會有不一樣的速度,需要自己調試。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM