草庐IT

javascript - 在折线图+条形图中使用 d3 画笔时出现问题(放大折线图+条形图)

coder 2024-07-20 原文

我正在尝试使用画笔在 d3.js 中缩放我的自定义图表,但它没有按应有的方式运行。知道可能出了什么问题 这是 js fiddle http://fiddle.jshell.net/saurabh_nitc10/od8gfsd3/9/

就像这个 fiddle http://fiddle.jshell.net/CjaD3/1/刷完之后,bars 就从 yaxis 出来了。任何想法

现有的 fiddle 有什么问题。缩放后它的行为不正常。请帮忙。我刚刚更新了 fiddle

这是我创建的插件。

(function($) {
$.dualAxis = {};
var xMapObject=[];
var svg = '';
var focus = '';
var tip = '';
function DualAxis(element, options) {
    this.$element = $(element);
    this.options = options;
    this.margin = {top: 20, right: 80, bottom: 30, left: 40},
    width = $(this.$element.selector).width() - this.margin.left - this.margin.right,
    height = $(this.$element.selector).height() - this.margin.top - this.margin.bottom;
    this.options.height = (this.options.height == null? height: this.options.height);
    this.options.width = (this.options.width == null? width: this.options.width);
    this.rangeMax = this.getMaxX().length*100;
    if (this.rangeMax > 14000) this.rangeMax = 14000;
    this.enabled = true;
}

DualAxis.prototype = {
    draw: function(){
        this.options.data.bar.forEach(function(d) {
            d.value = +d.value;
        });
        this.options.data.line.forEach(function(d) {
            d.value = +d.value;
        });
        tip = d3.tip()
          .attr('class', 'd3-tip')
          .html(function(d) { 
            var name= xMapObject[d.date];if(name == undefined){name=d.date;}
            var table = '<table class="table table-condensed">'
                        + '<thead>'
                        + '<tr><th colspan="2" style="text-align:center"class="city">'+name+'</th></tr>'
                        + '</thead>'
                        + '<tbody>'
                        + '<tr><td>Total Sales</td><td class="visits">'+d.value+'</td></tr>'
                        + '</tbody>'
                        + '</table>';
            return table; 
          })
          .style({border: '1px solid #fff', 'box-shadow': '1px 1px 4px rgba(0,0,0,0.5)', 'border-radius': 'none','background':'#fff','color':'#555'})
          .offset([-12, 0]);
        // if(this.options.data.events.length > 1){
            // xOffset = (this.options.width/this.options.data.events.length) + 40;
        // } else {
            // xOffset = this.options.width/2;
        // }
        xOffset = 62;
        svg = this.getSvg();
        svg == null ? svg = d3.select(this.$element.selector).append("svg"): svg;
        svg = svg
        .attr("height", this.options.height+this.margin.bottom+this.margin.top)
        .attr("width",this.options.width+this.margin.right+this.margin.left)
        .attr('class',this.options.svgClassName);
        svg.append("defs").append("clipPath")
            .attr("id", "clip")
            .append("rect")
            .attr("width", this.options.width)
            .attr("height", this.options.height);
        focus = svg.append("g").attr("class", "focus").attr("transform", "translate(" + xOffset + "," + 40 + ")");
        svg.call(tip);
        //this.drawBackground(focus);

        this.drawRect(focus,tip);
        this.drawXAxis(focus);
        this.drawY1Axis(focus);
        this.drawY2Axis(focus);
        this.drawLine(focus);
        this.drawLineLow(focus);
        this.drawLineMedium(focus);
        this.drawLineHigh(focus);
        if (this.options.showLegend)this.drawLegend(focus);
        this.zoomBehaviour(focus);
    },
    drawRect: function(svg,tip){
        x = this.getX();
        x2 = this.getX();
        y1 = this.getY1();
        y2 = this.getY2();
        height = this.options.height - (this.options.height / 3);
        transTime = 0;
        if(this.options.animate) transTime = 1000;

        svg.selectAll("rect.bar").data(this.options.data.bar).enter().append("rect").attr("class","bar").attr("width", this.options.width/this.options.data.bar.length).attr("x", function (d) {
            return x(d.date);
        }).attr("y", height).attr("height", 0).style("fill", function (d,i) {
            return "#89A54E";
        }).on('mouseover', tip.show)
        .on('mouseout', tip.hide).transition().duration(transTime).attr("y", function (d) {
            if(isNaN(y1(d.value))) return 0;return y1(d.value);
        }).attr("height", function (d) {
             if(isNaN(y1(d.value))) return 0; return (height - y1(d.value));
        }).style("fill", function(d) { return "#89A54E";}).attr("rx","1.5").attr("ry","1.5");
    },

    drawXAxis:function(svg){
        svg.append("g").attr("class", "x axis").attr("transform", "translate(0," + height + ")").call(this.getXAxis()).append("text").attr("transform", "translate(" + xOffset + "," + 40 + ")").style("text-anchor", "end").text(this.options.xAxisText).style("font-weight", "bold");
    },
    drawY1Axis:function(svg){

        svg.append("g").attr("class", "y axis").call(this.getY1Axis()).append("text").attr('id','y1AxisText').attr("transform", "rotate(-90)").attr("y",-36 ).attr("x", -(this.options.height/5)).style("text-anchor", "end").style("fill", "#266866").style("font-weight", "bold").style("letter-spacing", "1px").text(this.options.y1AxisText);
    },
    drawY2Axis:function(svg){
        svg.append("g").attr("class", "y axis").call(this.getY2Axis()).attr("transform", "translate(" + this.options.width + " ,0)")    .append("text").attr('id','y2AxisText').attr("transform", "rotate(-90)").attr("y",47 ).attr("x", -(this.options.height/5)).style("text-anchor", "end").style("fill", "#266866").style("font-weight", "bold").style("letter-spacing", "1px").text(this.options.y2AxisText);
    },
    drawLegend: function(svg){
        legend = svg.append("g").attr("class", "legend").attr('transform', 'translate(-30,'+(height+50)+')');
        max = d3.max(this.options.values,function(d){return d.length;});
        legend.selectAll('rect').data(this.options.values).enter().append("rect").attr("x", function(d,i){return (i*149);}).attr("y", "0").attr("width", 12).attr("height", 12).style("fill", function(d,i){return color(i);});
        legend.selectAll('text').data(this.options.values).enter().append("text").attr("x", function (d, i) {return (i*149+15);}).attr("y", "10").text(function (d) {return d;});
    },
    getSvg: function(){
        return this.options.svg;
    },
    getXAxis:function(){
        //var x = d3.scale.ordinal().rangeRoundBands([0, this.options.width], 0);
        return  d3.svg.axis().scale(x).tickFormat(d3.time.format("%b'%y")).orient("bottom");
        //return d3.svg.axis().scale(x).tickValues(x.domain().filter(function(d, i) {return !(i % 10); })).orient("bottom");
    },
    getY1Axis:function(){
        return d3.svg.axis().scale(y1).orient("left").tickFormat(d3.format(".2s"));
    },
    getY2Axis:function(){
        return d3.svg.axis().scale(y2).orient("right").tickFormat(d3.format(".2s"));
    },
    getMaxX: function(){ //for ordinal we dont know what to scale 

        return  this.options.data.dateForxAxis.map(function (d) {
            return d.date;});
    },
    getMaxY1: function(){
        return d3.max(this.options.data.bar, function (d) {return d.value;});
    },
    getMaxY2: function(){
        return d3.max(this.options.data.line, function (d) {return d.value;});
    },
    getX: function(){
        return d3.time.scale().range([0, this.options.width]).domain(d3.extent(this.options.data.dateForxAxis, function(d) { return d.date; }));
    },
    getY1: function(){
        return d3.scale.linear().range([this.options.height - (this.options.height / 3), 0]).domain([0, this.getMaxY1()]);
    },
    getY2: function(){
        return d3.scale.linear().range([this.options.height - (this.options.height / 3), 0]).domain([0, this.getMaxY2()]);
    },
    drawBackground: function(vis){
        vis.append("rect").attr("x", 0).attr("y", 0).attr("width", this.options.width ).attr("height", this.options.height - 50).style("fill", "grey").attr("transform", "translate(0,0)").style("opacity", "0").attr("class","background").attr("id", "background");
    },
    zoomBehaviour: function(vis){
        var that = this;
        //zoomBehaviour = d3.behavior.zoom().scaleExtent([1, 1]).on("zoom", zoom);
        brush = d3.svg.brush().x(x2).on("brush", brushed);
        width = this.options.width;
        vis.append("g").attr("class","x brush").call(brush).selectAll("rect").attr("y",-6).attr("height",this.options.height+7);
        function brushed(){
            x.domain(brush.empty() ? x2.domain() : brush.extent());
            vis.selectAll("rect.bar")
            .attr("transform", function(d) { return "translate(" + x(d.date) + ",0)"; })
             vis.select(".x.axis").call(that.getXAxis());
             //vis.select(".line").attr("d", that.getLine());
        }
    },
    drawLine:function(svg){
        svg.append('path').datum(this.options.data.line).attr("class", "line").attr("d", this.getLine());
    },
    getLine:function(){
        return d3.svg.line().interpolate("basis") .x(function(d) {return x(d.date); }).y(function(d) { return y2(d.value); });
    },
    drawLineLow:function(svg){
        svg.append('path').datum(this.options.data.future).attr("class", "lineLow").attr("d", this.getLineLow()).style("stroke-dasharray", ("3, 3"));
    },
    getLineLow:function(){
        return d3.svg.line().interpolate("basis") .x(function(d) {return x(d.date); }).y(function(d) { return y2(d.low); });
    },
    drawLineMedium:function(svg){
        svg.append('path').datum(this.options.data.future).attr("class", "lineMedium").attr("d", this.getLineMedium());
    },
    getLineMedium:function(){
        return d3.svg.line().interpolate("basis") .x(function(d) {return x(d.date); }).y(function(d) { return y2(d.medium); });
    },
    drawLineHigh:function(svg){
        svg.append('path').datum(this.options.data.future).attr("class", "lineHigh").attr("d", this.getLineHigh()).style("stroke-dasharray", ("3, 3"));
    },
    getLineHigh:function(){
        return d3.svg.line().interpolate("basis") .x(function(d) {return x(d.date); }).y(function(d) { return y2(d.high); });
    },

};
$.fn.dualAxis = function(options){

    options = $.extend({}, $.fn.dualAxis.defaults, options);
    if(options.data === '' || options.data === null){
        var err = 'dualAxis Error: Data Attribute Cannot be Empty or Null.';
        (typeof(console) != 'undefined' && console.error) ? 
            console.error(err) : 
            alert(err);
    }
    function elementOptions(ele, options) {
        return $.metadata ? $.extend({}, options, $(ele).metadata()) : options;
    };
    function get(ele) {
        var gb = $.data(ele, 'gb');
        if (!gb) {
            gb = new DualAxis(ele,elementOptions(ele, options));
            $.data(ele, 'gb', gb);
        }
        return gb;
    }
    var gb = get(this);
    gb.draw();
};

$.fn.dualAxis.defaults = {
        svgClassName: "dualAxis",
        svg: null,
        xAxisText: 'x-axis',
        y1AxisText: 'y1-axis',
        y2AxisText: 'y2-axis',
        maxX: null,
        maxyY: null,
        height:null,
        width:null,
        animate: true,
        color: ["#3366cc", "#dc3912", "#ff9900", "#109618"],
        showLegend:true,
        data: '',
    };
})(jQuery);

数据格式

{
"bar": [
    {
        "date": "50_2012",
        "value": "88787"
    },
    {
        "date": "155_2012",
        "value": "50573"
    },
     {
        "date": "155_2013",
        "value": "5057"
    }
],
"dateForxAxis": [
    {
        "date": "45_2012"
    },
    {
        "date": "155_2012"
    },
    {
        "date": "260_2013"
    }
],
"future": [
    {
        "high": "87878",
        "medium": "55535",
        "low": "1212"
    },
    {
        "high": "187878",
        "medium": "255535",
        "low": "14212"
    }
],
"line": [
    {
        "date": "50_2012",
        "value": "8787"
    },
    {
        "date": "60_2012",
        "value": "47474"
    },
     {
        "date": "168_2012",
        "value": "49474"
    }
]
};

调用插件

$('#dualAxis').dualAxis({
            data: viewData1,
            xAxisText: 'Time',
            y1AxisText:'Transactions',
            y2AxisText:'Sales',
            animate:true,
            showLegend:false
        });

请提出我做错了什么。当它缩放时,它甚至应该缩放线条和其他三行。

最佳答案

在 brushed 方法中,您正在平移条形图而不是设置新的 x 位置(使它们根据图形外的原始 x 位置进行平移)。在 brushed 方法中重新设置 x 位置将在缩放时正确放置条:

vis.selectAll("rect.bar").attr("x", function (d) {
  return x(d.date);
});

http://fiddle.jshell.net/brendaz/zr6kkgaa/ 处进行此更改的 jsfiddle 分支

关于javascript - 在折线图+条形图中使用 d3 画笔时出现问题(放大折线图+条形图),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29538926/

有关javascript - 在折线图+条形图中使用 d3 画笔时出现问题(放大折线图+条形图)的更多相关文章

  1. ruby - 如何使用 Nokogiri 的 xpath 和 at_xpath 方法 - 2

    我正在学习如何使用Nokogiri,根据这段代码我遇到了一些问题:require'rubygems'require'mechanize'post_agent=WWW::Mechanize.newpost_page=post_agent.get('http://www.vbulletin.org/forum/showthread.php?t=230708')puts"\nabsolutepathwithtbodygivesnil"putspost_page.parser.xpath('/html/body/div/div/div/div/div/table/tbody/tr/td/div

  2. ruby - 使用 RubyZip 生成 ZIP 文件时设置压缩级别 - 2

    我有一个Ruby程序,它使用rubyzip压缩XML文件的目录树。gem。我的问题是文件开始变得很重,我想提高压缩级别,因为压缩时间不是问题。我在rubyzipdocumentation中找不到一种为创建的ZIP文件指定压缩级别的方法。有人知道如何更改此设置吗?是否有另一个允许指定压缩级别的Ruby库? 最佳答案 这是我通过查看ruby​​zip内部创建的代码。level=Zlib::BEST_COMPRESSIONZip::ZipOutputStream.open(zip_file)do|zip|Dir.glob("**/*")d

  3. ruby - 为什么我可以在 Ruby 中使用 Object#send 访问私有(private)/ protected 方法? - 2

    类classAprivatedeffooputs:fooendpublicdefbarputs:barendprivatedefzimputs:zimendprotecteddefdibputs:dibendendA的实例a=A.new测试a.foorescueputs:faila.barrescueputs:faila.zimrescueputs:faila.dibrescueputs:faila.gazrescueputs:fail测试输出failbarfailfailfail.发送测试[:foo,:bar,:zim,:dib,:gaz].each{|m|a.send(m)resc

  4. ruby-on-rails - 使用 Ruby on Rails 进行自动化测试 - 最佳实践 - 2

    很好奇,就使用ruby​​onrails自动化单元测试而言,你们正在做什么?您是否创建了一个脚本来在cron中运行rake作业并将结果邮寄给您?git中的预提交Hook?只是手动调用?我完全理解测试,但想知道在错误发生之前捕获错误的最佳实践是什么。让我们理所当然地认为测试本身是完美无缺的,并且可以正常工作。下一步是什么以确保他们在正确的时间将可能有害的结果传达给您? 最佳答案 不确定您到底想听什么,但是有几个级别的自动代码库控制:在处理某项功能时,您可以使用类似autotest的内容获得关于哪些有效,哪些无效的即时反馈。要确保您的提

  5. ruby - 在 Ruby 中使用匿名模块 - 2

    假设我做了一个模块如下:m=Module.newdoclassCendend三个问题:除了对m的引用之外,还有什么方法可以访问C和m中的其他内容?我可以在创建匿名模块后为其命名吗(就像我输入“module...”一样)?如何在使用完匿名模块后将其删除,使其定义的常量不再存在? 最佳答案 三个答案:是的,使用ObjectSpace.此代码使c引用你的类(class)C不引用m:c=nilObjectSpace.each_object{|obj|c=objif(Class===objandobj.name=~/::C$/)}当然这取决于

  6. ruby - 使用 ruby​​ 和 savon 的 SOAP 服务 - 2

    我正在尝试使用ruby​​和Savon来使用网络服务。测试服务为http://www.webservicex.net/WS/WSDetails.aspx?WSID=9&CATID=2require'rubygems'require'savon'client=Savon::Client.new"http://www.webservicex.net/stockquote.asmx?WSDL"client.get_quotedo|soap|soap.body={:symbol=>"AAPL"}end返回SOAP异常。检查soap信封,在我看来soap请求没有正确的命名空间。任何人都可以建议我

  7. python - 如何使用 Ruby 或 Python 创建一系列高音调和低音调的蜂鸣声? - 2

    关闭。这个问题是opinion-based.它目前不接受答案。想要改进这个问题?更新问题,以便editingthispost可以用事实和引用来回答它.关闭4年前。Improvethisquestion我想在固定时间创建一系列低音和高音调的哔哔声。例如:在150毫秒时发出高音调的蜂鸣声在151毫秒时发出低音调的蜂鸣声200毫秒时发出低音调的蜂鸣声250毫秒的高音调蜂鸣声有没有办法在Ruby或Python中做到这一点?我真的不在乎输出编码是什么(.wav、.mp3、.ogg等等),但我确实想创建一个输出文件。

  8. ruby-on-rails - 'compass watch' 是如何工作的/它是如何与 rails 一起使用的 - 2

    我在我的项目目录中完成了compasscreate.和compassinitrails。几个问题:我已将我的.sass文件放在public/stylesheets中。这是放置它们的正确位置吗?当我运行compasswatch时,它不会自动编译这些.sass文件。我必须手动指定文件:compasswatchpublic/stylesheets/myfile.sass等。如何让它自动运行?文件ie.css、print.css和screen.css已放在stylesheets/compiled。如何在编译后不让它们重新出现的情况下删除它们?我自己编译的.sass文件编译成compiled/t

  9. ruby - ECONNRESET (Whois::ConnectionError) - 尝试在 Ruby 中查询 Whois 时出错 - 2

    我正在用Ruby编写一个简单的程序来检查域列表是否被占用。基本上它循环遍历列表,并使用以下函数进行检查。require'rubygems'require'whois'defcheck_domain(domain)c=Whois::Client.newc.query("google.com").available?end程序不断出错(即使我在google.com中进行硬编码),并打印以下消息。鉴于该程序非常简单,我已经没有什么想法了-有什么建议吗?/Library/Ruby/Gems/1.8/gems/whois-2.0.2/lib/whois/server/adapters/base.

  10. ruby - 使用 ruby​​ 将 HTML 转换为纯文本并维护结构/格式 - 2

    我想将html转换为纯文本。不过,我不想只删除标签,我想智能地保留尽可能多的格式。为插入换行符标签,检测段落并格式化它们等。输入非常简单,通常是格式良好的html(不是整个文档,只是一堆内容,通常没有anchor或图像)。我可以将几个正则表达式放在一起,让我达到80%,但我认为可能有一些现有的解决方案更智能。 最佳答案 首先,不要尝试为此使用正则表达式。很有可能你会想出一个脆弱/脆弱的解决方案,它会随着HTML的变化而崩溃,或者很难管理和维护。您可以使用Nokogiri快速解析HTML并提取文本:require'nokogiri'h

随机推荐