在几个html元素的固定位置之间绘制连接元素 [英] Drawing connective elements between fixed positions on several html elements

查看:33
本文介绍了在几个html元素的固定位置之间绘制连接元素的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我对网络编程很陌生,所以如果我遗漏了一些明显的东西,请多多包涵.我正在使用 html、css 和 javascript 来可视化不同的 DNA 序列.每个序列都表示为 html 元素的图形,并且具有与 DNA 序列长度相对应的固定长度.跨度位于每个图中的固定点以表示某些主题.此类图的代码如下所示(使用 django 作为我的 Web 框架):

<hr class="line">{% for key, value2 in value.items %}{% if value2.start_position %}<span class='motif' style="--start: {{ value2.start_position }}; --stop: {{ value2.stop_position }};"></span>{% 万一 %}{% 结束为 %}

像这样,我在我的网页上创建了几个序列的表示,一个在另一个下面.现在这些序列中的一些可能彼此相似.我想以图形方式显示序列与其下方显示的区域相似的区域,如下所示:

在上面的例子中,graph1和2以及graph2和3表示的序列具有相似的区域,但序列的总长度(因此在图上表示的motifs的显示大小)不同,导致更宽图 2 和图 3 之间的蓝色元素.

所以我对每个图所拥有的是每个图应该表示的序列长度,相应图上每个主题的开始和结束位置,以及如果两个图(序列)在每个图上相似区域的开始和结束位置) 包含一个相似的区域(图中绿色).

所以我的问题是:如何使用 html、css 或 javascript 创建表示两个图形(图中蓝色)之间相似区域的元素?(或者我可以在我已有的东西中实现的任何其他东西)

关于我如何处理这个问题的任何提示都非常感谢,如果您有更多问题,请告诉我!

我实际上更喜欢 svg 中的解决方案,因为我认为它更适合集成到我的应用程序中

解决方案

您可以使用 svg 或 canvas.

这是一个极简主义的画布方法.您可能希望依赖一个非常可能提供与您的图表相近的图表的库.

但抓挠永远不会痛.

下面,每个图形负责正确缩放其轴.

最终,梯形依赖于它们所依赖的图形来缩放相应的顶点.

您可能想要显示文本 更有条件的是,使用 Bar 并可能给它一个布尔值来指示是否应该显示它.

您可以通过调整笔划线的粗细等来进一步设置画布样式,但这只是一个演示,向您展示您可以轻松设置它

const canvas = document.querySelector('canvas')让 ctx = canvas.getContext('2d')让酒吧 = [[巴(200, 300), 巴(1800,2300), 巴(2500, 4500), 巴(5000,5200), 巴(8000,8500)],[巴(1100,1300), 巴(3000, 3800), 巴(4000, 4200), 巴(7000, 7500)],[酒吧(1, 2700)]]function Bar(a,b){return [a, b]}类图{构造函数 ({anchorY, width, min, max}) {this.anchorY = anchorYthis.width = 宽度this.dw = 宽度/(最大 - 最小)this.min = 分钟this.max = 最大值}情节(条){//绘制条形图//调整条形尺寸以适合画布常数 e = 5ctx.fillStyle = '橙色'const scaledBars = bar.map(([a, b]) => [ a, b, a * this.dw, b * this.dw ])scaledBars.forEach(([_, dum, left, right])=>{ctx.fillRect(left, this.anchorY - e, right - left, 2*e)})//情节主线ctx.strokeStyle = '黑色'ctx.beginPath()ctx.moveTo(0, this.anchorY)ctx.lineTo(this.width, this.anchorY)ctx.closePath()ctx.stroke()ctx.strokeStyle = '绿色'ctx.font = '10px 衬线'scaledBars.forEach(([origLeft, origRight, left, right]) => {ctx.strokeText(origLeft, left, this.anchorY - 10)如果(右 - 左> 100){ctx.strokeText(origRight, right, this.anchorY - 10)}})}//x 会自动移动移动到(x){ctx.moveTo(x * this.dw, this.anchorY)}线到(x){ctx.lineTo(x * this.dw, this.anchorY)}}常量图 = [new Graph({anchorY:100, width: canvas.width, min: 1, max: 10000}),new Graph({anchorY:200, width: canvas.width, min: 1, max: 8500}),new Graph({anchorY:300, width: canvas.width, min: 1, max: 4000})]//g 第一个图,(a,b) 第一个图中的左、右锚点//g2 第二个图,c 右锚点,d 左锚点在第二个图中功能梯形(g,a,b,g2,c,d){ctx.beginPath()g.moveTo(a)g.lineTo(b)g2.lineTo(c)g2.lineTo(d)ctx.closePath()ctx.fillStyle = 'rgba(84, 147, 158, 0.5)'ctx.fill()}const [g1, g2, g3] = 图const 梯形 = [[g1, 1800, 4500, g2, 3800, 1100],[g1, 8000, 8500, g2, 7500, 7000],[g2, 1100, 3800, g3, 2700, 1],]飞人.forEach(t => 飞人(...t))graphs.forEach((g, i) => {g.plot(bars[i])})

canvas{background:#eeeeee;}

<canvas width="400" height="400"></canvas>

I am quite new to web programming, so please bear with me if I am missing something obvious. I am using html, css and javascript to visualize different DNA sequences. Each sequence is represented as a graph of html elements and has a fixed length corresponding to the length of the DNA sequence. Spans are positioned at fixed points in each graph to represent certain motifs. The code for one such graph looks like this (using django as my web framework):

<div class="graph" style='--graph-length: {{sequence_length}}'>
        <hr class="line">
      {% for key, value2 in value.items %}
        {% if value2.start_position %}
            <span class='motif' style="--start: {{ value2.start_position }}; --stop: {{ value2.stop_position }};"></span>
        {% endif %}
      {% endfor %}
      </div>

Like this, I create representations of several sequences on my webpage, one below the other. Now some of these sequences may be similar to one another. I want to graphically display the regions over which a sequence is similar to the one displayed below it, like this:

In the above example, the sequences represented by graph1 and 2 and graph2 and 3 have a similar region, but the total length of the sequences (and thus the displayed size of motifs represented on a graph) differs, resulting in the wider blue element between graph2 and 3.

So what I have for each graph are the sequence length each graph should represent, the start and end positions for each motif on the respective graph, and the start and end position for the similar region on each graph if two graphs (sequences) contain a similar region (green in the picture).

So my question is: How can I create the elements representing a similar region between two graphs (blue in the picture) using html, css or javascript? (Or really anything else that I can implement in what I already have)

Any hints on how I could approach this are apprechiated, let me know if you have more questions!

EDIT: I would actually prefer a solution in svg, as I think its more suitable for integration in my application

解决方案

You could use svg, or canvas.

Here is a minimalist approach with canvas. You may want to rely on a library which are very likely to offer diagrams close to your ones.

But scratch never hurts.

Below, each graph is responsible of scaling properly its axis.

Eventually, the trapezes rely on the graph they depend on to scale the corresponding vertices.

You may want to display the text even more conditionnaly so play with Bar and potentially give it a boolean to indicate whether it should be displayed or not.

You can further style the canvas by playing on the weight of the stroke line and all, but it is just a demo to show you you can get it up easily

const canvas = document.querySelector('canvas')
  let ctx = canvas.getContext('2d')
  let bars = [
    [Bar(200, 300), Bar(1800,2300), Bar(2500, 4500), Bar(5000,5200), Bar(8000,8500)],
    [Bar(1100,1300), Bar(3000, 3800), Bar(4000, 4200), Bar(7000, 7500)],
    [Bar(1, 2700)]
  ]
  function Bar(a,b){return [a, b]}
  class Graph{
    constructor ({anchorY, width, min, max}) {
      this.anchorY = anchorY
      this.width = width
      this.dw = width / (max - min )
      this.min = min
      this.max = max
    }

    plot (bars) {
      // plot bars
      // resize bars dimension to fit canvas
      const e = 5
      ctx.fillStyle = 'orange'
      const scaledBars = bars.map(([a, b]) => [ a, b, a * this.dw, b * this.dw ])
      scaledBars.forEach(([_, dum, left, right])=>{
        ctx.fillRect(left, this.anchorY - e, right - left, 2*e)
      })

      // plot line
      ctx.strokeStyle = 'black'
      ctx.beginPath()
      ctx.moveTo(0, this.anchorY)
      ctx.lineTo(this.width, this.anchorY)
      ctx.closePath()
      ctx.stroke()

      ctx.strokeStyle = 'green'
      ctx.font = '10px serif'
      scaledBars.forEach(([origLeft, origRight, left, right]) => {
        ctx.strokeText(origLeft, left, this.anchorY - 10)
        if (right - left > 100 ) {
          ctx.strokeText(origRight, right, this.anchorY - 10)
        }
      })
      
    }

    //x will be shifted automatically
    moveTo (x) {
      ctx.moveTo(x * this.dw, this.anchorY)
    }


    lineTo (x) {
      ctx.lineTo(x * this.dw, this.anchorY)
    }
  }
  const graphs = [
    new Graph({anchorY:100, width: canvas.width, min: 1, max: 10000}),
    new Graph({anchorY:200, width: canvas.width, min: 1, max: 8500}),
    new Graph({anchorY:300, width: canvas.width, min: 1, max: 4000})
  ]
  
  // g first graph, (a,b) left, right anchors in first graph
  // g2 second graph, c right anchor, d left anchor in second graph
  function trapeze(g, a, b, g2, c, d){
    ctx.beginPath()
    g.moveTo(a)
    g.lineTo(b)
    g2.lineTo(c)
    g2.lineTo(d)
    ctx.closePath()
    ctx.fillStyle = 'rgba(84, 147, 158, 0.5)'
    ctx.fill()
  }

  const [g1, g2, g3] = graphs
  const trapezes = [
    [g1, 1800, 4500, g2, 3800, 1100],
    [g1, 8000, 8500, g2, 7500, 7000],
    [g2, 1100, 3800, g3, 2700, 1],
  ]
  trapezes.forEach(t => trapeze(...t))

  graphs.forEach((g, i) => {
    g.plot(bars[i])
  })

canvas{background:#eeeeee;}

<canvas width="400" height="400"></canvas>

这篇关于在几个html元素的固定位置之间绘制连接元素的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆