第七色在线视频,2021少妇久久久久久久久久,亚洲欧洲精品成人久久av18,亚洲国产精品特色大片观看完整版,孙宇晨将参加特朗普的晚宴

為了賬號(hào)安全,請(qǐng)及時(shí)綁定郵箱和手機(jī)立即綁定
已解決430363個(gè)問(wèn)題,去搜搜看,總會(huì)有你想問(wèn)的

根據(jù)網(wǎng)頁(yè)和 SQL 數(shù)據(jù)庫(kù)中的坐標(biāo)創(chuàng)建 svg 元素

根據(jù)網(wǎng)頁(yè)和 SQL 數(shù)據(jù)庫(kù)中的坐標(biāo)創(chuàng)建 svg 元素

交互式愛(ài)情 2023-08-10 10:54:31
我有一個(gè)類似于在幾個(gè)html元素上的固定位置之間繪制連接元素的問(wèn)題,但我正在尋找適用于svg的解決方案(不幸的是,自從我發(fā)布問(wèn)題到現(xiàn)在為止,我沒(méi)有時(shí)間處理這個(gè)項(xiàng)目,所以我仍然是網(wǎng)絡(luò)開(kāi)發(fā)的初學(xué)者)。我試圖在我的 Web 應(yīng)用程序中可視化不同 DNA 序列的對(duì)齊情況(django 是我的 Web 框架)。每個(gè) DNA 序列都以圖表形式顯示在<div>. 每個(gè)圖都包含代表 DNA 序列中子序列的子元素(黃色框)。我通過(guò)循環(huán)遍歷包含從數(shù)據(jù)庫(kù)獲取的原始值的字典來(lái)創(chuàng)建圖表。字典是這樣構(gòu)建的:{'1': {'organism': 'sequence 1', 'env_length': 10000, 'frame': '+', 'alns': {'aln_1': {'s_id': 2, 'q_id': 1, 'aln_len': 2700, 'q_start': 1800, 'q_end': 4500, 's_start': 1100, 's_end': 3800}, 'aln_2': {'s_id': 2, 'q_id': 1, 'aln_len': 500, 'q_start': '8000', 'q_end': 8500, 's_start': 7000, 's_end': 7500}}, 'env_genes': {'g1': {'env_name': 'gene_1', 'env_start': 1850, 'env_end': 4700, 'env_strand': '+', 'gene_class': 'normal'}, 'g2': {'env_name': 'gene_2', 'env_start': 8000, 'env_end': 8500, 'env_strand': '+', 'gene_class': 'normal'}}}, '2': {'organism': 'sequence 2', 'env_length': 8500, 'frame': '+', 'alns': {'aln_1': {'s_id': 3, 'q_id': 2, 'aln_len': 2700, 'q_start': 1100, 'q_end': 3800, 's_start': 1, 元素在 html 中是這樣創(chuàng)建的:<div class="graph" style='--graph-length: {{value.env_length}}'>          <hr class="line seq">          {% for key2, value2 in value.items %}            {% for key3, value3 in value2.items %}              {% if value3.env_start %}                {% if value3.env_strand == '+' %}                  <span class='env_gene_right {{ value3.gene_class }}' style="--start: {{ value3.env_start }}; --stop: {{ value3.env_end }};"></span>                {% else %}                  <span class='env_gene_left {{ value3.gene_class }}' style="--start: {{ value3.env_start }}; --stop: {{ value3.env_end }};"></span>                {% endif %}              {% endif %}            {% endfor %}          {% endfor %}</div>并使用 css 進(jìn)行樣式設(shè)置,如下所示:
查看完整描述

1 回答

?
森欄

TA貢獻(xiàn)1810條經(jīng)驗(yàn) 獲得超5個(gè)贊

DIV我強(qiáng)烈建議使用單個(gè)庫(kù)來(lái)繪制整個(gè)圖像,而不僅僅是嘗試組合s 和圖像(這意味著要面對(duì)幾個(gè)對(duì)齊和縮放問(wèn)題)。

我的示例使用 JS 畫布庫(kù)(內(nèi)置在所有較新的瀏覽器中),它需要提供將圖像繪制到頁(yè)面中的 JavaScript 所需的所有原始數(shù)據(jù):在我的示例中,我使用了單個(gè) JSON?input。

在開(kāi)始我的例子之前:

  • 我不得不承認(rèn)我不明白黃色矩形的含義,我稱它們?yōu)?code>evidences;

  • 我認(rèn)為在 graph3 中存在一個(gè)拼寫錯(cuò)誤:相似的結(jié)束邊緣位于 2700,而長(zhǎng)度為 2000,在我的示例中,我將長(zhǎng)度更改為 4000

  • 我自由地從 graph1 和 graph3 添加了另一對(duì)類似的夫婦

const input = {

? graphs: [{

? ? ? name: "graph1",

? ? ? length: 10000,

? ? ? evidences: [{

? ? ? ? ? from: 100,

? ? ? ? ? length: 1000

? ? ? ? },

? ? ? ? {

? ? ? ? ? from: 1800,

? ? ? ? ? length: 1000

? ? ? ? },

? ? ? ? {

? ? ? ? ? from: 3000,

? ? ? ? ? length: 1000

? ? ? ? },

? ? ? ? {

? ? ? ? ? from: 6000,

? ? ? ? ? length: 1000

? ? ? ? },

? ? ? ? {

? ? ? ? ? from: 8000,

? ? ? ? ? length: 500

? ? ? ? },

? ? ? ? {

? ? ? ? ? from: 9300,

? ? ? ? ? length: 500

? ? ? ? },

? ? ? ],

? ? },

? ? {

? ? ? name: "graph2",

? ? ? length: 8500,

? ? ? evidences: [{

? ? ? ? ? from: 1100,

? ? ? ? ? length: 1000

? ? ? ? },

? ? ? ? {

? ? ? ? ? from: 2500,

? ? ? ? ? length: 1000

? ? ? ? },

? ? ? ? {

? ? ? ? ? from: 5000,

? ? ? ? ? length: 1000

? ? ? ? },

? ? ? ? {

? ? ? ? ? from: 7000,

? ? ? ? ? length: 500

? ? ? ? },

? ? ? ],

? ? },

? ? {

? ? ? name: "graph3",

? ? ? length: 4000,

? ? ? evidences: [{

? ? ? ? ? from: 1,

? ? ? ? ? length: 2700

? ? ? ? },

? ? ? ? {

? ? ? ? ? from: 3200,

? ? ? ? ? length: 500

? ? ? ? },

? ? ? ],

? ? },

? ],

? similar: [{

? ? ? first: 0,

? ? ? second: 1,

? ? ? from: [1800, 1100],

? ? ? length: 2700,

? ? ? color: "#8080ff",

? ? },

? ? {

? ? ? first: 1,

? ? ? second: 2,

? ? ? from: [1100, 1],

? ? ? length: 2700,

? ? ? color: "#8080ff",

? ? },

? ? {

? ? ? first: 0,

? ? ? second: 1,

? ? ? from: [8000, 7000],

? ? ? length: 500,

? ? ? color: "#8080ff",

? ? },

? ? {

? ? ? first: 0,

? ? ? second: 2,

? ? ? from: [9300, 3200],

? ? ? length: 500,

? ? ? color: "#ff8080",

? ? },

? ],

};


const imgScale = window.devicePixelRatio;


function main() {

? // init

? const nameWidth = 100;

? const lengthWidth = 70;

? const graphHight = 50;

? const canvas = document.getElementById("canvas");

? canvas.style.height = graphHight * input.graphs.length + "px";

? const {

? ? clientWidth,

? ? clientHeight

? } = canvas;

? const width = (canvas.width = clientWidth * imgScale);

? const height = (canvas.height = clientHeight * imgScale);

? const graphWidth = width - (nameWidth + lengthWidth) * imgScale;

? var ctx = canvas.getContext("2d");

? // white fill canvas

? ctx.fillStyle = "#ffffff";

? ctx.fillRect(0, 0, clientWidth, clientHeight);

? // draw each similar

? for (let i = 0; i < input.similar.length; ++i) {

? ? const {

? ? ? first,

? ? ? second,

? ? ? from,

? ? ? length,

? ? ? color

? ? } = input.similar[i];

? ? const middleFirst = graphHight * (first + 0.5) * imgScale;

? ? const middleSecond = graphHight * (second + 0.5) * imgScale;

? ? const fromScaleFirst =

? ? ? (from[0] * graphWidth) / input.graphs[first].length;

? ? const lengthScaleFirst =

? ? ? (length * graphWidth) / input.graphs[first].length;

? ? const fromScaleSecond =

? ? ? (from[1] * graphWidth) / input.graphs[second].length;

? ? const lengthScaleSecond =

? ? ? (length * graphWidth) / input.graphs[second].length;

? ? ctx.fillStyle = color;

? ? ctx.beginPath();

? ? ctx.moveTo(nameWidth * imgScale + fromScaleFirst, middleFirst);

? ? ctx.lineTo(

? ? ? nameWidth * imgScale + fromScaleFirst + lengthScaleFirst,

? ? ? middleFirst

? ? );

? ? ctx.lineTo(

? ? ? nameWidth * imgScale + fromScaleSecond + lengthScaleSecond,

? ? ? middleSecond

? ? );

? ? ctx.lineTo(nameWidth * imgScale + fromScaleSecond, middleSecond);

? ? ctx.closePath();

? ? ctx.fill();

? ? populatePolygons({

? ? ? points: [

? ? ? ? [nameWidth * imgScale + fromScaleFirst, middleFirst],

? ? ? ? [

? ? ? ? ? nameWidth * imgScale + fromScaleFirst + lengthScaleFirst,

? ? ? ? ? middleFirst,

? ? ? ? ],

? ? ? ? [

? ? ? ? ? nameWidth * imgScale + fromScaleSecond + lengthScaleSecond,

? ? ? ? ? middleSecond,

? ? ? ? ],

? ? ? ? [nameWidth * imgScale + fromScaleSecond, middleSecond],

? ? ? ],

? ? ? object: {

? ? ? ? type: "similar",

? ? ? ? first,

? ? ? ? second,

? ? ? ? from,

? ? ? ? length

? ? ? },

? ? });

? }

? // write each similar edge

? ctx.fillStyle = "#008000";

? ctx.font = "20px Arial";

? ctx.textBaseline = "middle";

? ctx.textAlign = "center";

? for (let i = 0; i < input.similar.length; ++i) {

? ? const {

? ? ? first,

? ? ? second,

? ? ? from,

? ? ? length,

? ? ? color

? ? } = input.similar[i];

? ? const middleFirst = graphHight * (first + 0.5) * imgScale;

? ? const middleSecond = graphHight * (second + 0.5) * imgScale;

? ? const fromScaleFirst =

? ? ? (from[0] * graphWidth) / input.graphs[first].length;

? ? const lengthScaleFirst =

? ? ? (length * graphWidth) / input.graphs[first].length;

? ? const fromScaleSecond =

? ? ? (from[1] * graphWidth) / input.graphs[second].length;

? ? const lengthScaleSecond =

? ? ? (length * graphWidth) / input.graphs[second].length;

? ? ctx.fillText(

? ? ? from[0],

? ? ? nameWidth * imgScale + fromScaleFirst,

? ? ? middleFirst - 20

? ? );

? ? ctx.fillText(

? ? ? from[0] + length,

? ? ? nameWidth * imgScale + fromScaleFirst + lengthScaleFirst,

? ? ? middleFirst - 20

? ? );

? ? ctx.fillText(

? ? ? from[1],

? ? ? nameWidth * imgScale + fromScaleSecond,

? ? ? middleSecond - 20

? ? );

? ? ctx.fillText(

? ? ? from[1] + length,

? ? ? nameWidth * imgScale + fromScaleSecond + lengthScaleSecond,

? ? ? middleSecond - 20

? ? );

? }

? //draw each graph

? ctx.strokeStyle = "#000000";

? for (let i = 0; i < input.graphs.length; ++i) {

? ? const graph = input.graphs[i];

? ? const middle = graphHight * (i + 0.5) * imgScale;

? ? ctx.beginPath();

? ? ctx.moveTo(nameWidth * imgScale, middle);

? ? ctx.lineTo(nameWidth * imgScale + graphWidth, middle);

? ? ctx.stroke();

? ? ctx.fillStyle = "#000000";

? ? ctx.textAlign = "left";

? ? ctx.fillText(graph.name, 10, middle);

? ? ctx.textAlign = "right";

? ? ctx.fillText("1", (nameWidth - 10) * imgScale, middle);

? ? ctx.fillText(graph.length, width - 10, middle);

? ? // draw each evidence

? ? ctx.fillStyle = "#ffff80";

? ? for (let l = 0; l < graph.evidences.length; ++l) {

? ? ? const {

? ? ? ? from,

? ? ? ? length

? ? ? } = graph.evidences[l];

? ? ? const fromScale = (from * graphWidth) / graph.length;

? ? ? const lengthScale = (length * graphWidth) / graph.length;

? ? ? ctx.fillRect(

? ? ? ? fromScale + nameWidth * imgScale,

? ? ? ? middle - 10,

? ? ? ? lengthScale,

? ? ? ? 20

? ? ? );

? ? ? ctx.beginPath();

? ? ? ctx.rect(

? ? ? ? fromScale + nameWidth * imgScale,

? ? ? ? middle - 10,

? ? ? ? lengthScale,

? ? ? ? 20

? ? ? );

? ? ? ctx.stroke();

? ? ? populatePolygons({

? ? ? ? points: [

? ? ? ? ? [fromScale + nameWidth * imgScale, middle - 10],

? ? ? ? ? [fromScale + nameWidth * imgScale + lengthScale, middle - 10],

? ? ? ? ? [fromScale + nameWidth * imgScale + lengthScale, middle + 10],

? ? ? ? ? [fromScale + nameWidth * imgScale, middle + 10],

? ? ? ? ],

? ? ? ? object: {

? ? ? ? ? type: "evidence",

? ? ? ? ? graph: i,

? ? ? ? ? evidence: l,

? ? ? ? },

? ? ? });

? ? }

? }

}


const polygons = [];


function populatePolygons(polygon) {

? polygons.push(polygon);

}


function inside(point, vs) {

? var x = point[0],

? ? y = point[1];


? var inside = false;

? for (var i = 0, j = vs.length - 1; i < vs.length; j = i++) {

? ? var xi = vs[i][0],

? ? ? yi = vs[i][1];

? ? var xj = vs[j][0],

? ? ? yj = vs[j][1];


? ? var intersect =

? ? ? yi > y != yj > y && x < ((xj - xi) * (y - yi)) / (yj - yi) + xi;

? ? if (intersect) inside = !inside;

? }


? return inside;

}


function mouseEvent(kind, event) {

? const {

? ? offsetX,

? ? offsetY

? } = event;


? for (polygon in polygons) {

? ? const {

? ? ? object,

? ? ? points

? ? } = polygons[polygon];

? ? if (inside([offsetX * imgScale, offsetY * imgScale], points))

? ? ? interaction(kind, object);

? }

}


function interaction(kind, object) {

? const {

? ? type,

? ? graph,

? ? evidence,

? ? first,

? ? second,

? ? from,

? ? length

? } = object;


? if (type == "evidence")

? ? console.log(

? ? ? `${kind} on evidence nr ${evidence + 1} of graph nr ${graph + 1}`

? ? );

? else

? ? console.log(

? ? ? `${kind} on similar between graph nr ${first + 1} from ${

? ? ? ? ? ? from[0]

? ? ? ? ? } and graph nr ${second + 1} from ${from[1]} long ${length}`

? ? );

}


main();

<canvas id="canvas" style="width: 100%" onclick="mouseEvent('click', event)" onmousemove="mouseEvent('move', event)" />

這將為您提供一個(gè)也可以復(fù)制到剪貼板的圖像;嘗試:

  1. 左鍵單擊“運(yùn)行代碼片段”按鈕

  2. 右鍵單擊結(jié)果圖像

  3. 選擇“復(fù)制圖像”上下文菜單(Windows chrome)

  4. 粘貼到任何接受剪貼板圖像的程序中

編輯:

根據(jù)新的請(qǐng)求(用戶需要與圖像交互),使用單個(gè)庫(kù)使一切變得更加簡(jiǎn)單這一點(diǎn)并沒(méi)有改變。

使用很棒的多邊形點(diǎn)算法,我們也可以輕松實(shí)現(xiàn)這個(gè)更多目標(biāo)。

我添加了一個(gè)簡(jiǎn)單的控制臺(tái)日志作為概念驗(yàn)證,您可以隨意附加任何其他內(nèi)容。

不幸的是,console.log 幾乎占據(jù)了“運(yùn)行代碼片段”的所有空間,以獲得更好的體驗(yàn):

  1. 編輯這個(gè)答案

  2. 單擊編輯預(yù)覽中代碼段之外的“編輯上述代碼段”鏈接

  3. 按“運(yùn)行”按鈕


查看完整回答
反對(duì) 回復(fù) 2023-08-10
  • 1 回答
  • 0 關(guān)注
  • 146 瀏覽
慕課專欄
更多

添加回答

舉報(bào)

0/150
提交
取消
微信客服

購(gòu)課補(bǔ)貼
聯(lián)系客服咨詢優(yōu)惠詳情

幫助反饋 APP下載

慕課網(wǎng)APP
您的移動(dòng)學(xué)習(xí)伙伴

公眾號(hào)

掃描二維碼
關(guān)注慕課網(wǎng)微信公眾號(hào)