canvas画频谱瀑布图的问题

QQ许多年以后QQ 发布于 2017/08/29 10:52
阅读 401
收藏 1

请问如何实现频率频谱图,随着时间的推移,不断的从商往下落得效果?如下图:

并且刷新频率很快,数据量大,X轴数据至少在2000以上,每隔0.25秒下落一次。可以参见:http://blog.csdn.net/sangsa/article/details/50585472

加载中
0
QQ许多年以后QQ
QQ许多年以后QQ

我粗略实现了一下,但是再循环了100多次后开始变慢,查看内存也没有暴增的,情况,请大神指导。插件源码如下:

var hd_waterfall = {
    canvas : null,
    ctx:null,
    grad:null,
    data:[],
    colorData:[],
    colors:[],
    option:{
        width:1600,
        height:10,
        min:0,
        max:0,
        maxHeight:100,
        data:[],
        colors:["#4876ff","#00ff50","#eeee00","ff0000"],
        gamma:0
    },
    // convert #hex notation to rgb array
    parseColor:function (hexStr) {
        return hexStr.length === 4 ? hexStr.substr(1).split('').map(function (s) { return 0x11 * parseInt(s, 16); }) : [hexStr.substr(1, 2), hexStr.substr(3, 2), hexStr.substr(5, 2)].map(function (s) { return parseInt(s, 16); })
    },
    // zero-pad 1 digit to 2
    pad : function (s) {
        return (s.length === 1) ? '0' + s : s;
    },
    gradientColors : function (start, end, steps, gamma) {
        var i, j, ms, me, output = [], so = [];
        gamma = gamma || 1;
        var normalize = function (channel) {
            return Math.pow(channel / 255, gamma);
        };
        start = this.parseColor(start).map(normalize);
        end = this.parseColor(end).map(normalize);
        for (i = 0; i < steps; i++) {
            ms = i / (steps - 1);
            me = 1 - ms;
            for (j = 0; j < 3; j++) {
                so[j] = this.pad(Math.round(Math.pow(start[j] * me + end[j] * ms, 1 / gamma) * 255).toString(16));
            }
            output.push('#' + so.join(''));
        }
        return output;
    },
    init:function(DOMElement){
        this.canvas = document.createElement("canvas");
        this.canvas.id = "hd_waterfall_canvas";
        this.canvas.style.width = "100%";
        this.canvas.style.height = "100%";
        DOMElement.appendChild(this.canvas);
        return hd_waterfall;
    },
    setOption:function(opt){
        if(opt){
            this.option = opt;
        }
        this.option.gamma = Math.ceil(this.option.data.length / this.option.colors.length);
        this.setColors(this.option.startColor,this.option.middleColor,this.option.endColor,this.option.gamma)
        this.valueToColor(this.option.data);
    },
    setColors:function(start,middle,end,gamma){
        var $this  = this;
        for(var i=0;i< $this.option.colors.length-1;i++){
            var tmp = $this.option.colors[i];
            var tmp_1 = $this.option.colors[i+1]
            $this.colors = $this.colors.concat(this.gradientColors(tmp,tmp_1, gamma));
        }
        /*var colors_1 = this.gradientColors(start,middle, gamma);
        var colors_2 = this.gradientColors(middle,end, gamma);
        this.colors = colors_1.concat(colors_2);*/
    },
    valueToColor:function(data){
        var $this = this;
        var tempColor = [];
        //计算间隔
        var length = $this.option.max - $this.option.min;
        //计算每等分的值
        var argvValue = length / data.length;
        for(var i=0;i<data.length;i++){
            //tempColor.push($this.)
            data[i] = data[i];
            //计算当前所占比例
            if(data[i] < $this.option.min)
                data[i] = $this.option.min;
            if(data[i] > $this.option.max)
                data[i] = $this.option.max;
            //console.log(data[i])
            //console.log(data[i]+"-"+Math.ceil((data[i] - $this.option.min)/argvValue))
            tempColor.push($this.colors[Math.ceil((data[i] - $this.option.min)/argvValue)]);
        }
        $this.colorData.push( tempColor);
        /*if($this.colorData.length > 20)
            $this.colorData.pop();*/
        this.show();
    },
    show:function(){
        var $this = this;
        for(var i=0;i<$this.colorData.length;i++){
            if(!$this.ctx){
                $this.ctx = this.canvas.getContext("2d");
                $this.ctx.beginPath();
            }
            else {
                $this.ctx.clearRect(0, 0, 0, 0);
            }
                var grad = $this.ctx.createLinearGradient(0, 0, 300, 0);
                var temp = $this.colorData[i];
                for (var j = 0; j < temp.length; j++) {
                    grad.addColorStop(j / temp.length, temp[j]);
                    /* 将这个渐变设置为fillStyle */
                }
                $this.ctx.fillStyle = grad;
                /* 绘制矩形 */
                $this.ctx.rect(0, (i * $this.option.height), $this.canvas.width, $this.option.height);
                $this.ctx.fill();
                $this.ctx.closePath();
                delete grad;
                delete $this.ctx;
        }
        //如果超过了显示的区域,则删除
        if($this.colorData.length/3*2 > Math.ceil($this.option.maxHeight/$this.option.height) ){
            $this.colorData.shift();
        }
    }
}

在开始init一次,然后通过setInterval不断从数据池中取数据(数据池由另外的定时器取添加),将数据转换成color值,然后show出来,效果实现了,唯一就是后面会变慢。跪求……

kyubi
kyubi
可以分享一下完整代码吗?
返回顶部
顶部