Я работаю над проектом с D3.js, который отображает области интереса (ROI), которые являются <g>
элементами с одним <polygon>
и одним <text>
.Я заметил, что масштабирование становится очень медленным, когда есть много ROI, и кажется, что это в основном из-за текстов, то есть когда они скрыты с display: none
, масштабирование происходит намного быстрее.Скорость масштабирования в каждом браузере разная: Firefox довольно быстрый, Chrome средний, а Edge медленный.
Я попытался ускорить рендеринг текста с помощью свойства CSS text-rendering: optimizeSpeed;
, но разница незначительна.Я заметил, что некоторые шрифты отображаются быстрее, чем другие.В настоящее время лучшие результаты, которые я получил, это использование font-family: monospace;
.
Итак, мой вопрос: как быстрее увеличить изображение в SVG-чертеже с помощью D3?Есть ли шрифт, который известен быстрее, чем другие?Или может помочь трюк с CSS, SVG или D3?
Вы можете проверить скорость масштабирования с помощью фрагмента.Если вы нажмете на кнопку, текст будет скрыт, а масштабирование будет намного быстрее.
"use strict";
// Create data with this structure:
// DATA = [{ name: "", coords: [x0, y0, x1, y1, x2, y2, x3, y3]}]
var nbPolyX = 100;
var nbPolyY = 50;
var sqSize = 800 / nbPolyX;
var DATA = [];
for (let idY = 0; idY < nbPolyY; idY++) {
for (let idX = 0; idX < nbPolyX; idX++) {
DATA.push({
name: "x" + idX + "y" + idY,
coords: [
idX * sqSize + 1, idY * sqSize + 1,
(idX + 1) * sqSize - 1, idY * sqSize + 1,
(idX + 1) * sqSize - 1, (idY + 1) * sqSize - 1,
idX * sqSize + 1, (idY + 1) * sqSize - 1
]
})
}
}
var SVGELEM = {};
var ZOOMER = {};
var TRNSF = {
k: 1,
x: 0,
y: 0
};
var ZOOMER = {};
var GZOOM = {};
var ROI = {};
var POLY = {};
var TXT = {};
var BUTTON = {};
addButton();
addSVG();
function addSVG() {
ZOOMER = d3
.zoom()
.scaleExtent([0.9, 40])
.on("zoom", function () {
onZoom();
});
SVGELEM = d3.select("body").append("svg")
.attr("width", nbPolyX * sqSize)
.attr("height", nbPolyY * sqSize)
.call(ZOOMER);
GZOOM = SVGELEM.append("g");
ROI = GZOOM.selectAll("g")
.data(DATA)
.enter()
.append("g")
.classed("roi", true);
POLY = ROI.selectAll("polygon")
.data(function (d) {
return [d.coords];
})
.enter()
.append("polygon")
.attr("points", function (d) {
return d;
});
TXT = ROI.selectAll("text")
.data(function (d) {
var nbElem = d.coords.length;
// Polygon mean point X.
var xMean = 0;
for (let index = 0; index < nbElem - 1; index += 2) {
xMean += d.coords[index];
}
xMean /= nbElem / 2;
// Polygon mean point Y.
var yMean = 0;
for (let index = 1; index < nbElem; index += 2) {
yMean += d.coords[index];
}
yMean /= nbElem / 2;
// Return value.
var ret = {
name: d.name,
x: xMean,
y: yMean
};
return [ret];
})
.enter()
.append("text")
.attr("x", function (d) {
return d.x;
})
.attr("y", function (d) {
return d.y;
})
.text(function (d) {
return d.name;
});
}
function addButton() {
BUTTON = d3.select("body").append("button")
.text("HIDE TEXT")
.on("click", function btnOnClick() {
btnOnClick.state = !btnOnClick.state;
d3.selectAll("text").classed("cl_display_none", btnOnClick.state);
if (btnOnClick.state) d3.select(this).text("SHOW TEXT");
else d3.select(this).text("HIDE TEXT");
});
}
function onZoom() {
if (d3.event !== null) TRNSF = d3.event.transform;
GZOOM.attr(
"transform",
"translate(" + TRNSF.x + "," + TRNSF.y + ") scale(" + TRNSF.k + ")"
);
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>SVG ZOOM SPEED</title>
<style>
body {
text-align: center;
font-family: monospace;
display: block;
margin: 0 auto;
}
svg {
margin: 10px auto;
border: 1px solid;
display: block;
}
.roi polygon {
shape-rendering: optimizeSpeed;
vector-effect: non-scaling-stroke;
fill: rgba(0, 255, 0, 0.25);
stroke: rgba(0, 255, 0, 1);
stroke-width: 1px;
}
.roi text {
text-rendering: optimizeSpeed;
font-family: monospace;
font-size: 1px;
text-anchor: middle;
dominant-baseline: middle;
}
.cl_display_none {
display: none;
}
button {
width: 150px;
height: 50px;
font-family: monospace;
font-size: 15pt;
margin: 0;
}
</style>
</head>
<body>
<h3>SVG ZOOM SPEED</h3>
<p>Use the mouse wheel to zoom in and out the SVG drawing then hide the text with the button and observe the speed difference. Test it in different browsers.</p>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
<script src="zoom_speed.js"></script>
</body>
</html>