Lentivirus Genome
Schematic of lentivirus genome used for deep mutational scanning
Code
vue
<template>
<svg ref="svgContainer"></svg>
</template>
<script setup>
import { ref, onMounted } from 'vue';
import * as d3 from 'd3';
const svgContainer = ref(null);
let dataSet = [
{ start: 1, stop: 634, name: 'LTR' },
{ start: 681, stop: 806, name: 'Psi' },
{ start: 1301, stop: 1536, name: 'RRE' },
{ start: 2225, stop: 2592, name: 'rTRE3GS' },
{ start: 2644, stop: 4214, name: 'Nipah F' },
{ start: 4300, stop: 4806, name: 'CMV' },
{ start: 4912, stop: 5600, name: 'ZsGreen' },
{ start: 5601, stop: 6240, name: 'PuroR' },
{ start: 6242, stop: 6833, name: 'WPRE' },
{ start: 6834, stop: 7536, name: 'LTR' },
];
const width = 600;
const height = 400;
const margin = { top: 20, right: 20, bottom: 40, left: 20 };
const x = d3.scaleLinear()
.domain([0, d3.max(dataSet, d => d.stop)])
.range([margin.left, width - margin.right])
.nice();
const color = d3.scaleOrdinal(d3.schemeTableau10);
function startAnimation(svg, gRects, gLabels, gx, xTitle, backboneText) {
gRects.attr("x", width + 50);
gLabels.attr("x", width + 50);
gx.attr('transform', `translate(0,${height + 50})`);
xTitle.attr('y', height + 50);
backboneText.attr('opacity', 1);
gRects.transition()
.duration(3000)
.ease(d3.easeCubicInOut)
.attr("x", d => x(d.start));
gLabels.transition()
.duration(3000)
.ease(d3.easeCubicInOut)
.attr("x", d => (x(d.start) + x(d.stop)) / 2);
gx.transition()
.duration(3000)
.ease(d3.easeCubicInOut)
.attr('transform', `translate(0,${height / 2 + 15})`);
xTitle.transition()
.duration(3000)
.ease(d3.easeCubicInOut)
.attr('y', height - 125)
backboneText.transition()
.duration(3000)
.attr('opacity', 0);
setTimeout(() => {
startAnimation(svg, gRects, gLabels, gx, xTitle, backboneText);
}, 6000);
}
onMounted(() => {
const svg = d3.select(svgContainer.value)
//.attr('preserveAspectRatio', "xMinYMin meet")
.attr('viewBox', `0 0 ${width} ${height}`)
svg.append("g")
.append("rect")
.attr("fill", "currentColor")
.attr("x", margin.left)
.attr("y", height / 2)
.attr("height", 10)
.attr("width", width - margin.right - margin.left);
const backboneText = svg.append('text')
.attr('class', 'backbone-text')
.attr('x', width / 2)
.attr('y', height / 2 - 20)
.attr('text-anchor', 'middle')
.attr('font-size', '20px')
.attr('fill', 'currentColor')
.text('Lentivirus Backbone');
const gRects = svg.selectAll("rect.data")
.data(dataSet)
.enter()
.append("rect")
.attr("class", "data")
.attr("fill", (d, i) => color(i))
.attr("x", 1000)
.attr("y", height / 2 - 2)
.attr("height", 14)
.attr("width", d => x(d.stop) - x(d.start));
const gLabels = svg.selectAll("text.label")
.data(dataSet)
.enter()
.append("text")
//.attr("class", "label")
.attr("x", 1000)
.attr("y", height / 2 - 6)
.attr("text-anchor", "middle")
.attr("font-size", "12px")
.attr("font-weight", "bold")
.attr("fill", (d, i) => color(i))
.text(d => d.name);
const gx = svg.append('g')
.call(d3.axisBottom(x).ticks(10).tickSizeInner(4))
.call(g => g.select(".domain").remove())
.attr('font-size', '12px')
.attr('color', 'currentColor');
const xTitle = svg.append('text')
//.attr('class', 'axis-title')
.attr('x', width / 2)
.attr('y', -height )
.attr('text-anchor', 'middle')
.attr('font-size', '12px')
.attr('fill', 'currentColor')
.text('Position (bp)');
startAnimation(svg, gRects, gLabels, gx, xTitle, backboneText);
});
</script>