我正在尝试使用画布从MySql表中的数据绘制连接线。表(gene_dna_segments)包含每个线段的长度和段名称。
所需输出是由每个段组成的连续直水平线。每个细分受众群还需要显示相应细分受众群上方的细分受众群名称,如下图所示:
+----------------------+--------------------+------------------+--------------------+
| gene_dna_segments_pk | gene_expression_fk | dna_segment_name | dna_segment_length |
+----------------------+--------------------+------------------+--------------------+
| 1 | 11 | Exon 1 | 50 |
| 2 | 11 | Intron 1 | 75 |
| 3 | 11 | Exon 2 | 20 |
| 4 | 11 | Intron 2 | 90 |
+----------------------+--------------------+------------------+--------------------+
查询(老式没有PDO ......):
$query_dna = "SELECT * FROM gene_dna_segments WHERE gene_expression_fk = '11'";
$result_dna = mysql_query($query_dna, $connection) or die(mysql_error());
显示:
<canvas id="canvas" width="800" height="500"></canvas>
<script type="text/javascript">
var canvas = document.getElementById('canvas');
var context = canvas.getContext('2d');
<?php
while($row_dna = mysql_fetch_assoc($result_dna)) {
echo "context.beginPath();context.moveTo(100, 100);context.lineTo(" . $row_dna['dna_segment_length'] . ", 100);context.lineWidth = 12;context.strokeStyle = '#009543';context.stroke();context.font = 'bold 12pt Calibri';
context.fillStyle = '#009543';
context.fillText('" . $row_dna['dna_segment_name'] . "', 180, 90);";
}
?>
</script>
现在,表格中定义的线段和文本被绘制得很好,但是相互叠加,因为context.moveTo(100, 100)
对于在while循环中输出的每一行都是相同的。应该如何处理这些段以便将它们绘制成一条连续的线?
可能最简单的方法是在表格中添加一个起点列,并根据前一段的长度计算每个段的起点...我已经就这种可能性Calculating new array values based on another numeric array <打开了一个单独的问题/ p>
请注意,绘制线条的“普通”代码类似于以下代码,请注意,moveto部分从上一行的末尾开始。我需要在循环中做同样的事情......
var canvas = document.getElementById('canvas');
var context = canvas.getContext('2d');
context.beginPath();
context.moveTo(100, 100);
context.lineTo(150, 100);
context.lineWidth = 12;
context.strokeStyle = '#009543';
context.stroke();
context.font = 'bold 11pt Calibri';
context.fillStyle = '#009543';
context.fillText('Exon 1', 105, 90);
context.beginPath();
context.moveTo(150, 100);
context.lineTo(225, 100);
context.lineWidth = 12;
context.strokeStyle = '#e97300';
context.stroke();
context.font = 'bold 11pt Calibri';
context.fillStyle = '#e97300';
context.fillText('Intron 1', 165, 90);
context.beginPath();
context.moveTo(225, 100);
context.lineTo(275, 100);
context.lineWidth = 12;
context.strokeStyle = '#009543';
context.stroke();
context.font = 'bold 11pt Calibri';
context.fillStyle = '#009543';
context.fillText('Exon 2', 230, 90);
context.beginPath();
context.moveTo(275, 100);
context.lineTo(375, 100);
context.lineWidth = 12;
context.strokeStyle = '#e97300';
context.stroke();
context.font = 'bold 11pt Calibri';
context.fillStyle = '#e97300';
context.fillText('Intron 2', 300, 90);
答案 0 :(得分:1)
[根据提问者的新信息更新]
您所描述的是水平堆积的条形图
演示:http://jsfiddle.net/m1erickson/RzMWS/
你的条形图非常简单。
小问题:
我们需要在每个栏上方显示segment_name标签。在完美的世界中,我们可以使用segment_length作为条宽。但实际上,有时候条形宽度太窄而不适合上面的文字标签。
因此,我们必须预处理数据并确定条形的适当比例因子。通过按比例缩放条形,每个条形将保持与其segment_length成比例,并且也足够宽以适合segment_name标签。
以下是评论很多的代码。
当然,您将从数据库读取而不是读取rows []数组中的测试数据。
<!doctype html>
<html>
<head>
<link rel="stylesheet" type="text/css" media="all" href="css/reset.css" /> <!-- reset css -->
<script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script>
<style>
body{ background-color: ivory; }
#canvas{border:1px solid red;}
</style>
<script>
$(function(){
// get references to the canvas
var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
ctx.font = 'bold 11pt Calibri';
// define the color of the bar for each segment_name
var colorCodes={
Exon1:"green",
Intron1:"orange",
Exon2:"green",
Intron2:"orange"
};
// create some test data
var rows=[];
rows.push({dna_segment_name:"Exon 1",dna_segment_length:50});
rows.push({dna_segment_name:"Intron 1",dna_segment_length:75});
rows.push({dna_segment_name:"Exon 2",dna_segment_length:20});
rows.push({dna_segment_name:"Intron 2",dna_segment_length:90});
// some variables
// segments[]: pre-processed data will be saved into segments[]
// scaleFactor: scales every bar if any text label fails to fit
// padding: allow minimum padding between text labels
var segments=[];
var scaleFactor=1;
var padding=5;
// pre-process
// Of course, you will be reading from your database Fetch
// instead of this test data in rows[]
for(var i=0;i<rows.length;i++){
var $row_dna=rows[i];
// make variables for the segment_name & segment_length
// being read from the data fetch
var name=$row_dna['dna_segment_name'];
var length=$row_dna['dna_segment_length'];
// lookup the color for this segment_name
var color=colorCodes[name.replace(/\s+/g, '')];
// rescale the bars if any text won't fit
var textWidth=ctx.measureText(name).width+padding;
var textRatio=textWidth/length;
if (textRatio>scaleFactor){ scaleFactor=textRatio; }
// save the pre-processed info in a javascript object
// for later processing
segments.push({
name:name,
length:length*scaleFactor,
color:color
});
}
// draw the stacked bar-chart
// based on the preprocessed JS objects in segments[]
var accumLength=0;
var y=100; // the Y-coordinate of the barchart
for(var i=0;i<segments.length;i++){
// load the object for the current bar
var segment=segments[i];
// set the bar color
ctx.fillStyle=segment.color;
// draw the bar
ctx.fillRect(accumLength,y,segment.length,12);
// draw the text label
ctx.fillText(segment.name,accumLength,y-10);
// accumulate where the next bar will begin
accumLength+=segment.length;
}
}); // end $(function(){});
</script>
</head>
<body>
<canvas id="canvas" width=400 height=300></canvas>
</body>
</html>