Как быстрее увеличить изображение в формате SVG с помощью D3? - PullRequest
0 голосов
/ 27 декабря 2018

Я работаю над проектом с 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>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...