javascript - 将元素动态移动到视口(viewport)内部

标签 javascript jquery css svg

代码笔:https://codepen.io/anon/pen/LjxNGj

Javascript:

$(document).ready(function() {
    var regions = '../js/json/eveRegions.json';
    var systems = '../js/json/eveSystems.json';

    var constellations = [];

    var displayedSystems = [];
    var arrayX = [];
    var arrayY = [];

    function getRegions() {
        $.getJSON(regions, function(data) {

            data.forEach(function(regionData) {
                $('#regionSelect').append("<option id="+regionData.region_id+">"+regionData.name+"</option>")
            });       
        });
    }

    $('#regionSelect').change(function() {
        var selectedRegion = $(this).val();
        constellations = [];

        displayedSystems = [];
        arrayX = [];
        arrayY = [];

        $('#container').empty();

        $.getJSON(regions, function(data) {

            data.forEach(function(regionData) {

                if (selectedRegion == regionData.name) {
                    console.log(regionData);

                    regionData.constellations.forEach(function(constellation) {
                        constellations.push(constellation);
                    });
                    console.log(constellations);
                    getSystems();
                }
            });
        });
    });

    function getSystems() {
        $.getJSON(systems, function(data) {
            var systemCount = data.length;
            var index = 0;

            data.forEach(function(systemData) {
                index++;

                if(constellations.indexOf(systemData.constellation_id) > -1) {
                    var x = systemData.position.x / 100000000000000;
                    var y = systemData.position.y / 100000000000000;

                    arrayX.push(x);
                    arrayY.push(y);
                    displayedSystems.push(systemData);
                }

                if (index === systemCount) {
                    generateSystems();
                }
            });       
        });
    }

    function generateSystems() {
        var lowestX = Math.min.apply(Math, arrayX);
        var lowestY = Math.min.apply(Math, arrayY);
        var offsetX = Math.abs(lowestX);
        var offsetY = Math.abs(lowestY);

        displayedSystems.forEach(function(data) {
            var x = data.position.x / 100000000000000;
            var y = data.position.y / 100000000000000;
            var coordX = x + offsetX;
            var coordY = y + offsetY;

            var svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
            svg.setAttribute('id', data.name);
            svg.setAttribute('title', data.name);
            svg.setAttribute('class', 'system');
            svg.setAttribute('constellation-id', data.constellation_id);
            svg.setAttribute('style', 'margin-top:'+coordY+'px;margin-left:'+coordX+'px');
            svg.setAttributeNS("http://www.w3.org/2000/xmlns/", "xmlns:xlink", "http://www.w3.org/1999/xlink");
            document.getElementById('container').appendChild(svg);
        });
    }

    getRegions();

    $('#container').panzoom();
});

HTML:

<body>
      <select id="regionSelect"></select>
      <div id="container"></div>
    </body>

CSS:

select {
  position: absolute;
}

#container {

  .system {
    width: 4px;
    height: 4px;
    background: grey;
    border-radius: 12px;
    position: absolute;

    &:hover {
      background: red;
    }
  }

  .label {
    position: absolute;
    font-size: 10px;
  }
}

此脚本在一个 div 中动态创建多个 SVG 元素。这些元素中的每一个都有使用 x 和 y 坐标的不同像素偏移,例如 map 上的位置。

每次通过下拉菜单选择一个新选项时,都会加载一组新的位置。

你可以在这里看到我将原始坐标除以 10 万亿,以使它们在像素方面更易于管理:

var x = systemData.position.x / 100000000000000;
                    var y = systemData.position.y / 100000000000000;

这很好用,但问题是即使仍然在某些选择中,偏移量太大以至于生成的 SVG 元素被推到视口(viewport)之外。我通过采用最负坐标并将这些值添加到偏移量(在大多数情况下)使元素从左上角开始对齐来解决这个问题,如下所示:

var lowestX = Math.min.apply(Math, arrayX);
        var lowestY = Math.min.apply(Math, arrayY);
        var offsetX = Math.abs(lowestX);
        var offsetY = Math.abs(lowestY);

        displayedSystems.forEach(function(data) {
            var x = data.position.x / 100000000000000;
            var y = data.position.y / 100000000000000;
            var coordX = x + offsetX;
            var coordY = y + offsetY;

我正在寻找的是一种不同的方式来绘制这些位置/元素,以便它们始终位于主视口(viewport)内。简单来说,现在有些元素的顶部边距为 1000 像素或更多,我正在寻找一种奇特的方法来解决这个问题。

最佳答案

首先,我建议您只获取一次您的区域和系统数据......这会让您的用户更开心。

但是,为了回答您的查询,如果您将最小的 X 和 Y 值乘以 -1(以有效地使它们成为 0,0 原点),那么您将确保为一个区域显示的每个系统都从最小位置开始。 x 在 0px 和最小的 position.y 在 0px。

希望这对您有所帮助!

$(document).ready(function() {
    var regions = '../js/json/eveRegions.json';
    var systems = '../js/json/eveSystems.json';

    var regionData = [];
    var systemData = [];

    var constellations = [];

    var displayedSystems = [];
    var arrayX = [];
    var arrayY = [];

    $('#regionSelect').change(function() {
        var selectedRegion = $(this).val();
        constellations = [];    
        displayedSystems = [];

        arrayX = [];
        arrayY = [];

        $('#container').empty();

        var filteredRegions = regionData.filter((r) => selectedRegion == r.name);
        filteredRegions.forEach((r) => {
            console.log(r);
            r.constellations.forEach((c) => constellations.push(c));
            console.log(constellations);
            getRegionSystems();
        });
    });

    function getRegionSystems() {
        // Clear out the previously displayed systems so we don't keep building the list
        displayedSystems = systemData.filter((s) => constellations.indexOf(s.constellation_id) > -1);
        displayedSystems.forEach((s) => {
            var x = s.position.x / 100000000000000;
            var y = s.position.y / 100000000000000;
            arrayX.push(x);
            arrayY.push(y);
        });
        generateSystems();
    }

    function generateSystems() {
        var lowestX = Math.min.apply(Math, arrayX);
        var lowestY = Math.min.apply(Math, arrayY);
        var offsetX = -1 * lowestX;
        var offsetY = -1 * lowestY;

        displayedSystems.forEach(function(data) {
            var x = data.position.x / 100000000000000;
            var y = data.position.y / 100000000000000;
            var coordX = x + offsetX;
            var coordY = y + offsetY;

            var svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
            svg.setAttribute('id', data.name);
            svg.setAttribute('title', data.name);
            svg.setAttribute('class', 'system');
            svg.setAttribute('constellation-id', data.constellation_id);
            svg.setAttribute('style', 'margin-top:'+coordY+'px;margin-left:'+coordX+'px');
            svg.setAttributeNS("http://www.w3.org/2000/xmlns/", "xmlns:xlink", "http://www.w3.org/1999/xlink");
            document.getElementById('container').appendChild(svg);
        });
    }

    function getRegions() {
        $.getJSON(regions, function(data) {

            data.forEach(function(regionData) {
                $('#regionSelect').append("<option id="+regionData.region_id+">"+regionData.name+"</option>")
            });    
            regionData = data;   
        });
    }

    function getSystems() {
        $.getJSON(systems, function(data) {
            systemData = data;
        });
    }

    getRegions();
    getSystems();

    // $('#container').panzoom();
});

关于javascript - 将元素动态移动到视口(viewport)内部,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45526611/

相关文章:

javascript - 模态窗口不适用于分页数据表

javascript - 我有一个固定的 div,我正在使用 jquery 在滚动时淡出。它工作正常,但如果我半途而废并引用 div 显示的页面

javascript - 谷歌地图下推内容?

javascript - 或者在 2 个文本框中键入验证 - ASP.NET Webforms

javascript - 在 jQuery 中设置无默认排序 ("aaSorting": []) for specific ID or entire project

html - 为什么我不能在按钮下放置下拉菜单?

javascript - 我可以检测用户何时使用后退按钮进入页面吗?

javascript - 如何在 javascript 中显示带有 .html 的链接

javascript - 在提交事件中更新值后未提交隐藏输入

javascript - 不要滚动元素调整大小