Как проверить с помощью d3.js, находится ли элемент в точке обзора (в видимой области) - PullRequest
0 голосов
/ 13 октября 2018

Я рисую большое количество элементов, и во многих ситуациях большинство элементов находятся за пределами точки зрения.

Я бы хотел избежать обработки дорогостоящих преобразований вращения на скрытых элементах.

Вот пример:

https://blockchaingraph.org/#ipfs-QmfXtMeUdjWBPQHUNKvF3nkYR57aZz7qarW5qikEUYWJvw

Многие элементы на этом графике скрыты (попробуйте уменьшить масштаб, чтобы увидеть).Но в настоящее время я должен рендерить каждый элемент на каждом тике, и он становится мучительно медленным.

Вот мой код:

function transformLinks(svgLinks, nodeRadius, arrowSize) {
    if (svgLinks) {
        var link = svgLinks.selectAll('.link').filter(needRedraw);
        //console.log("total:", svgLinks.selectAll('.link').size(), ',needRedraw:', link.size());
        transformLinksLines(link);
        transformLinksTexts(link.selectAll('.text'));
        transformLinksOutlines(link, nodeRadius, arrowSize);
        transformLinksOverlays(link.selectAll('.overlay'));
        link.each(function (n) {
            n.source.lx = n.source.x;
            n.source.ly = n.source.y;
            n.target.lx = n.target.x;
            n.target.ly = n.target.y;
        });
    }
}

function needRedraw(link) {
    if (!link.source) {
        link = link.parentNode;
    }
    return nodeMoved(link.source) || nodeMoved(link.target);
}

var minDistToRedraw = 0.8;
function nodeMoved(n) {
    return utils.isNumber(n.x) && utils.isNumber(n.y)
            && !(utils.isNumber(n.lx) && Math.abs(n.x - n.lx) <= minDistToRedraw && Math.abs(n.y - n.ly) <= minDistToRedraw);
}

Я бы хотел расширить функцию needRedraw () для проверки видимости,На данный момент функция просто проверяет, достаточно ли значительно переместился какой-либо из связанных узлов.

1 Ответ

0 голосов
/ 13 октября 2018

Поскольку я не нашел никакого готового решения, мне пришлось заняться этими вещами преобразования координат.

Сначала я создал функцию, которая переводит координаты внешнего контейнера в систему координат внутреннего клиента SVG - containerToSVG ​​()

Затем применил его к .getBoundingClientRect ();чтобы получить видимую область в координатном пространстве SVG.

Затем в фильтре проверяют, не превышают ли оба узла видимую область - не перерисовывать ссылку.

Возможны ситуации, когда оба узла выходят за пределы области., но ссылка все еще может пересекать область.Но это не большая проблема, пока пользователь не видит отрывы ссылок.

Вот код:

function transformLinks(svgLinks, nodeRadius, arrowSize) {
    if (svgLinks) {
        var containerRect = container.node().getBoundingClientRect();
        var p = containerToSVG(-nodeRadius, -nodeRadius);
        var r = containerToSVG(containerRect.width + nodeRadius, containerRect.height + nodeRadius);
        svgVisibleRect = {left: p.x, top: p.y, right: r.x, bottom: r.y};
        minDistToRedraw = (svgVisibleRect.right - svgVisibleRect.left) / (containerRect.width + nodeRadius * 2);
        var link = svgLinks.selectAll('.link').filter(needRedraw);
        transformLinksLines(link);
        transformLinksTexts(link.selectAll('.text'));
        transformLinksOutlines(link, nodeRadius, arrowSize);
        transformLinksOverlays(link.selectAll('.overlay'));
        link.each(function (n) {
            updateLastCoord(n.source);
            updateLastCoord(n.target);
        });
    }
}

function needRedraw(link) {
    if (!nodeMoved(link.source) && !nodeMoved(link.target)) {
        return false;
    }
    return isVisible(link.source) || isVisible(link.target);
}

function nodeMoved(n) {
    return utils.isNumber(n.x) && utils.isNumber(n.y) &&
            !(utils.isNumber(n.lx) && Math.abs(n.x - n.lx) <= minDistToRedraw && Math.abs(n.y - n.ly) <= minDistToRedraw);
}

function isVisible(n) {
    var result = n.x > svgVisibleRect.left && n.x < svgVisibleRect.right &&
            n.y > svgVisibleRect.top && n.y < svgVisibleRect.bottom;
    return result;
}

function updateLastCoord(n) {
    n.lx = n.x;
    n.ly = n.y;
}

function containerToSVG(containerX, containerY) {
    var svgPount = svgNode.createSVGPoint();
    svgPount.x = containerX;
    svgPount.y = containerY;
    return svgPount.matrixTransform(document.getElementById("links-svg").getScreenCTM().inverse());
}

function transformLinksLines(link) {
    link.attr('transform', function (d) {
        var angle = rotation(d.source, d.target);
        return 'translate(' + d.source.x + ', ' + d.source.y + ') rotate(' + angle + ')';
    });

}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...