javascript 如何在 morris.js 条形图上放置文本

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/23537788/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-28 01:03:21  来源:igfitidea点击:

How to place a text on morris.js bar graph

javascriptjquerymorris.js

提问by AabinGunz

I have a morris.js bar graph. I want to place counton top of this graph. I looked into morris.js bar doc, could not find any.

我有一个 morris.js 条形图。我想放在count这个图表的顶部。我查看了morris.js bar doc,找不到任何内容。

On hover it should display valuebut on top of bar it should display count. Is there a way to do that? something like the given image

在悬停时它应该显示,value但在栏的顶部它应该显示count。有没有办法做到这一点?类似于给定图像的东西

enter image description here

在此处输入图片说明

Here is my code

这是我的代码

Morris.Bar ({
  element: 'bar-example',
  data: [
    {mapname: 's1', value: 10, count: 3},
    {mapname: 's2', value: 4, count: 4},
    {mapname: 's3', value: 12, count: 13}
  ],
  xkey: 'mapname',
  ykeys: ['value'],
  labels: ['No. of days'],
  barRatio: 0.4,
  xLabelAngle: 35,
  hideHover: 'auto',
  barColors: function (row, series, type) {
    console.log("--> "+row.label, series, type);
    if(row.label == "s1") return "#AD1D28";
    else if(row.label == "s2") return "#DEBB27";
    else if(row.label == "s3") return "#fec04c";
  }
});

Here is a linkwhere you can test it.

这是一个链接,您可以在其中进行测试。

回答by Deano

I just found this question whilst looking for the same solution. This is done in javascript / jquery.

我刚刚在寻找相同的解决方案时发现了这个问题。这是在 javascript/jquery 中完成的。

I can share with you the code I am using which I discovered by trial, error and research.

我可以与您分享我通过反复试验和研究发现的我正在使用的代码。

function parseSVG(s) {
        var div= document.createElementNS('http://www.w3.org/1999/xhtml', 'div');
        div.innerHTML= '<svg xmlns="http://www.w3.org/2000/svg">'+s+'</svg>';
        var frag= document.createDocumentFragment();
        while (div.firstChild.firstChild)
            frag.appendChild(div.firstChild.firstChild);
        return frag;
    }

var theData = [
    {mapname: 's1', value: 10, count: 3},
    {mapname: 's2', value: 4, count: 4},
    {mapname: 's3', value: 12, count: 13}
  ]

Morris.Bar ({
element: 'bar-example',
data: theData,
  xkey: 'mapname',
  ykeys: ['value'],
  labels: ['No. of days'],
  barRatio: 0.4,
  xLabelAngle: 35,
  hideHover: 'auto',
  barColors: function (row, series, type) {
    console.log("--> "+row.label, series, type);
    if(row.label == "s1") return "#AD1D28";
    else if(row.label == "s2") return "#DEBB27";
    else if(row.label == "s3") return "#fec04c";
  }
});

var items = $("#bar-example").find( "svg" ).find("rect");
$.each(items,function(index,v){
    var value = theData[index].count;
    var newY = parseFloat( $(this).attr('y') - 20 );
    var halfWidth = parseFloat( $(this).attr('width') / 2 );
    var newX = parseFloat( $(this).attr('x') ) +  halfWidth;
    var output = '<text style="text-anchor: middle; font: 12px sans-serif;" x="'+newX+'" y="'+newY+'" text-anchor="middle" font="10px &quot;Arial&quot;" stroke="none" fill="#000000" font-size="12px" font-family="sans-serif" font-weight="normal" transform="matrix(1,0,0,1,0,6.875)"><tspan dy="3.75">'+value+'</tspan></text>';
    $("#bar-example").find( "svg" ).append(parseSVG(output));
});

The output looks like this.

输出看起来像这样。

enter image description here

在此处输入图片说明

But what you can try, is change the values here

但是你可以尝试的是改变这里的值

var newY = parseFloat( $(this).attr('y') - 20 );

to something like

var halfHeight = parseFloat( $(this).attr('height') / 2 );
var newY = parseFloat( $(this).attr('y') - halfHeight );

This change is untested, but will act as a good starting point.

此更改未经测试,但将作为一个很好的起点。

Regards :)

问候 :)

回答by krlzlx

You can extend Morris to achieve this. Please refer to this answerto see a full working snippet.

您可以扩展 Morris 来实现这一点。请参阅此答案以查看完整的工作片段。

Add a property:

添加属性:

Bar.prototype.defaults["labelTop"] = false;

Add a prototype to draw the label:

添加原型来绘制标签:

Bar.prototype.drawLabelTop = function(xPos, yPos, text) {
    var label;
    return label = this.raphael.text(xPos, yPos, text)
        .attr('font-size', this.options.gridTextSize)
        .attr('font-family', this.options.gridTextFamily)
        .attr('font-weight', this.options.gridTextWeight)
        .attr('fill', this.options.gridTextColor);
};

Modify the Bar.prototype.drawSeriesprotoype, adding these lines (before the last else):

修改Bar.prototype.drawSeries原型,添加这些行(在最后一行之前):

if (this.options.labelTop && !this.options.stacked) {
    label = this.drawLabelTop((left + (barWidth / 2)), top - 10, row.y[sidx]);
    textBox = label.getBBox();
    _results.push(textBox);
}

Then set the labelTopproperty to true in your Morris Bar config:

然后labelTop在您的 Morris Bar 配置中将该属性设置为 true:

labelTop: true

回答by Felipe Lobo

I find better to pass via jQuery to an empty p

我发现通过 jQuery 传递给空 p 更好

This is the final result: Final Result

这是最终结果: 最终结果

This is my code:

这是我的代码:

HTML

HTML

<div class="row">
   <div class="col-lg-3 col-md-3 col-sm-6 col-xs-6 ">
      <p class="numero num1"></p>
   </div>
   <div class="col-lg-3 col-md-3 col-sm-6 col-xs-6 ">
      <p class="numero num2"></p>
   </div>
   <div class="col-lg-3 col-md-3 col-sm-6 col-xs-6 ">
      <p class="numero num3"></p>
   </div>
   <div class="col-lg-3 col-md-3 col-sm-6 col-xs-6 ">
      <p class="numero num4"></p>
   </div>
 </div>

JSBelow the chart code. Remember to change theDatavariable to the one you're using in your code.

JS下面的图表代码。请记住将theData变量更改为您在代码中使用的变量。

 var b=1;
   jQuery('rect').each(function (i) {
      $('p.num'+b).text(theData[i].value); 
      b++;
    });

CSS

CSS

.numero{
  text-align: center;
  font-size: 18px !important;
  font-weight: 600 !important;
}

I also have added a class to each color.

我还为每种颜色添加了一个类。

Hope this helps anybody :) Happy coding!

希望这可以帮助任何人:) 快乐编码!

回答by Steve.kim

enter link description here

在此处输入链接描述

      barColors:function(e){
      if(e.label=="2014"){
                        return "#EA7756";
                }else if(e.label=="2015"){
                        return "#91D180";
                }else{
                        return "#FDAA4C";
                }
  }

回答by Gagan Gami

Try by placing this code in CSS

尝试将此代码放在CSS 中

.morris-hover{position:absolute;z-index:1000;}

回答by chiliNUT

Here is a start, its a bit hacky, but it gets the job done:

这是一个开始,它有点hacky,但它完成了工作:

JS

JS

    var graphData= [
    {mapname: 's1', value: 10, count: 3},
    {mapname: 's2', value: 4, count: 4},
    {mapname: 's3', value: 12, count: 13}
  ]; //store this to its own var so we can access the counts later


var bar=Morris.Bar ({
  element: 'bar-example',
  data:graphData,
  xkey: 'mapname',
  ykeys: ['value'],
  labels: ['No. of days'],
  barSizeRatio:0.4, //I think you meant barSizeRatio, not barSize
  xLabelAngle: 35,
  hideHover: 'auto',
  barColors: function (row, series, type) {
    //console.log("--> "+row.label, series, type);
    if(row.label == "s1") return "#AD1D28";
    else if(row.label == "s2") return "#DEBB27";
    else if(row.label == "s3") return "#fec04c";
  }
});


//first, find the width of a bar
//this is bar-example width, divided by three, times barSizeRatio
var barWidth=($('#bar-example').width()/3)*(0.4);

//now each thru each bar (rect)

jQuery('rect').each(function (i) {
  var pos=$(this).offset();
  var top=pos.top;
  top-=20; //originate at the top of the bar

  //get the height of the bar
  var barHeight=bar.bars[i];
  top+=barHeight/2; //so we can now stick the number in the vertical-center of the bar as desired
  var left=pos.left;
  //move it over a bit
  left+=barWidth/2; 
  //-size of element...
  left-=10;//should approximately be horizontal center

  $div=jQuery('<div class="count" style="top:'+top+'px;left:'+left+'px;" />'); 
  $div.text(graphData[i].count); //get the count
  jQuery('body').append($div); //stick it into the dom
  console.log($div);
});

and some CSS to style the divs

和一些 CSS 来设置 div 的样式

CSS

CSS

.count{
  position:absolute;
  width:10px;
  height:20px;
  line-height:20px;
  color:white;
  font-weight:bold;
  }

hopefully you can run with that to create the exact effect you are looking for

希望您可以使用它来创建您正在寻找的确切效果

enter image description here

在此处输入图片说明

回答by Jonathan

@chiliNUT @abi1964 I placed multiple charts but I am having a problem w/the CSS. The data, bar height etc. all works fine but the #s are being stacked on top. I've tried every iteration of position in the CSS. Ideas or a Fiddle how to fix this?

@chiliNUT @abi1964 我放置了多个图表,但我在使用 CSS 时遇到了问题。数据、条形高度等一切正常,但#s 被堆叠在顶部。我已经尝试了 CSS 中位置的每次迭代。想法或小提琴如何解决这个问题?

image of multiple graphs w/#'s stacking

带有#'s stacking 的多个图形的图像