【问题标题】:Applying colors via mousedown can only be overwritten if I choose a color with an index value greater than the current color index只有当我选择索引值大于当前颜色索引的颜色时,才能覆盖通过 mousedown 应用颜色
【发布时间】:2017-03-31 04:42:04
【问题描述】:

我的简单地图软件允许将不同的颜色应用于县。我一直在努力解决一个相当奇怪的错误,它只允许索引值大于当前颜色索引的颜色覆盖颜色。

代码很长,但我不确定是否可以在不粘贴整个内容的情况下提出这一点。我将从主要部分开始:

这是填充十六进制颜色数组的 getColor() 函数,我认为部分问题出在哪里:

function getColor(index) {
        var colorarray = [
            '550000',
            '801515',
            'aa3939',
            'd46a6a',
            'ffaaaa',
            '003333',
            '0d4d4d',
            '226666',
            '407f7f',
            '669999',
            '004400',
            '116611',
            '2d882d',
            '55aa55',
            '88cc88',
            '552700',
            '804515',
            'aa6c39',
            'd49a6a',
            'ffd1aa',
        ];
        return colorarray[index];
    }

这是完整的代码。如果您选择数组中的最后一种颜色(右下角,粉红色),选择一些县,然后尝试覆盖,则会很快注意到该错误。你会看到它失败了。如果您选择右上角的深红色,您可以用任何其他颜色覆盖该颜色,因为所有颜色都位于数组列表的下方。

它使用 colorsjs.js 和 d3.js 库。

    <!DOCTYPE html>
<title>Heartland Remapping Tool</title>
<link rel="shortcut icon" type="image/png" href="/faviconpng.png" />
<style>
    svg {
        width: 100%;
        height: auto;
    }

    input {
        border-width: 0px;
        border: none;
        width: 30px;
        height: 30px;
        cursor: pointer;
        margin: 3px;
    }

    .c550000 {
        fill: #550000;
        stroke-width: .5px;
    }

    .c801515 {
        fill: #801515;
        stroke-width: .5px;
    }

    .caa3939 {
        fill: #aa3939;
        stroke-width: .5px;
    }

    .cd46a6a {
        fill: #d46a6a;
        stroke-width: .5px;
    }

    .cffaaaa {
        fill: #ffaaaa;
        stroke-width: .5px;
    }

    .c003333 {
        fill: #003333;
        stroke-width: .5px;
    }

    .c0d4d4d {
        fill: #0d4d4d;
        stroke-width: .5px;
    }

    .c226666 {
        fill: #226666;
        stroke-width: .5px;
    }

    .c407f7f {
        fill: #407f7f;
        stroke-width: .5px;
    }

    .c669999 {
        fill: #669999;
        stroke-width: .5px;
    }

    .c004400 {
        fill: #004400;
        stroke-width: .5px;
    }

    .c116611 {
        fill: #116611;
        stroke-width: .5px;
    }

    .c2d882d {
        fill: #2d882d;
        stroke-width: .5px;
    }

    .c55aa55 {
        fill: #55aa55;
        stroke-width: .5px;
    }

    .c88cc88 {
        fill: #88cc88;
        stroke-width: .5px;
    }

    .c552700 {
        fill: #552700;
        stroke-width: .5px;
    }

    .c804515 {
        fill: #804515;
        stroke-width: .5px;
    }

    .caa6c39 {
        fill: #aa6c39;
        stroke-width: .5px;
    }

    .cd49a6a {
        fill: #d49a6a;
        stroke-width: .5px;
    }

    .cffd1aa {
        fill: #ffd1aa;
        stroke-width: .5px;
    }

    .counties {
        fill: white;
        stroke: #7887AB;
        stroke-width: .5px;
    }

    .counties .hovered,
    .counties :hover {
        fill: #061539;
        stroke-width: .5px;
    }

    .selected {
        fill: #061539;
    }

    .erase {
        fill: none;
    }

    .deselected {
        fill: white;
        stroke-width: .5px;
    }

    .deselected :hover {
        fill: #061539;
        stroke-width: .5px;
    }

    .county-borders {
        fill: none;
        stroke: #F0F8FF;
        stroke-width: .2px;
        stroke-linejoin: round;
        stroke-linecap: round;
        pointer-events: none;
    }

    .state-borders {
        fill: none;
        stroke: #162955;
        opacity: .8;
        stroke-linejoin: round;
        stroke-linecap: round;
        pointer-events: none;
    }

    .toolTip {
        position: absolute;
        display: none;
        min-width: 80px;
        height: auto;
        background: none repeat scroll 0 0 #ffffff;
        border: 1px solid #6F257F;
        padding: 14px;
        text-align: center;
    }
</style>
<script>
    var selcolor;
    window.onload = function() {
        var defaultcolor = document.getElementById("first");
        getSeletedColor(defaultcolor);
    };

    //this may be the cause of the fact that I can only overwrite colors with a color farther down the list.
    function getColor(index) {
        var colorarray = [
            '550000',
            '801515',
            'aa3939',
            'd46a6a',
            'ffaaaa',
            '003333',
            '0d4d4d',
            '226666',
            '407f7f',
            '669999',
            '004400',
            '116611',
            '2d882d',
            '55aa55',
            '88cc88',
            '552700',
            '804515',
            'aa6c39',
            'd49a6a',
            'ffd1aa',
        ];
        return colorarray[index];
    }

    function getSeletedColor(val) {

        var coloritem = document.getElementById('selcolor');
        coloritem.value = val.value;
        var dispitem = document.getElementById('current_color');
        dispitem.style.background = val.style.backgroundColor;
        dispitem.value = val.value;
    }
</script>
<input id="selcolor" hidden="true" value="hhhhhh"></input>
<div id="option">
    <input style="width: 90px; height: 18px;" name="updateButton" type="button" value="Print Regions" onclick="dl_csv()" />
</div>
<div id="option">
    <input style="width: 90px; height: 18px;" name="updateButton" type="button" value="Reset" onclick="window.location.reload()" />
</div>
<br/>
<div>
    <form id="colorlist">
        <input id="first" style="background-color:#550000; color: #550000;" value="550000" onmousedown="getSeletedColor(this)">
        <input spellcheck="false" style="background-color:#801515; color: #801515;" value="801515" onmousedown="getSeletedColor(this)">
        <input spellcheck="false" style="background-color:#aa3939; color: #aa3939;" value="aa3939" onmousedown="getSeletedColor(this)">
        <input spellcheck="false" style="background-color:#d46a6a; color: #d46a6a;" value="d46a6a" onmousedown="getSeletedColor(this)">
        <input spellcheck="false" style="background-color:#ffaaaa; color: #ffaaaa;" value="ffaaaa" onmousedown="getSeletedColor(this)">
        <br/>
        <input spellcheck="false" style="background-color:#003333; color: #003333;" value="003333" onmousedown="getSeletedColor(this)">
        <input spellcheck="false" style="background-color:#0d4d4d; color: #0d4d4d;" value="0d4d4d" onmousedown="getSeletedColor(this)">
        <input spellcheck="false" style="background-color:#226666; color: #226666;" value="226666" onmousedown="getSeletedColor(this)">
        <input spellcheck="false" style="background-color:#407f7f; color: #407f7f;" value="407f7f" onmousedown="getSeletedColor(this)">
        <input spellcheck="false" style="background-color:#669999; color: #669999;" value="669999" onmousedown="getSeletedColor(this)">
        <br/>
        <input spellcheck="false" style="background-color:#004400; color: #004400;" value="004400" onmousedown="getSeletedColor(this)">
        <input spellcheck="false" style="background-color:#116611; color: #116611;" value="116611" onmousedown="getSeletedColor(this)">
        <input spellcheck="false" style="background-color:#2d882d; color: #2d882d;" value="2d882d" onmousedown="getSeletedColor(this)">
        <input spellcheck="false" style="background-color:#55aa55; color: #55aa55;" value="55aa55" onmousedown="getSeletedColor(this)">
        <input spellcheck="false" style="background-color:#88cc88; color: #88cc88;" value="88cc88" onmousedown="getSeletedColor(this)">
        <br/>
        <input spellcheck="false" style="background-color:#552700; color: #552700;" value="552700" onmousedown="getSeletedColor(this)">
        <input spellcheck="false" style="background-color:#804515; color: #804515;" value="804515" onmousedown="getSeletedColor(this)">
        <input spellcheck="false" style="background-color:#aa6c39; color: #aa6c39;" value="aa6c39" onmousedown="getSeletedColor(this)">
        <input spellcheck="false" style="background-color:#d49a6a; color: #d49a6a;" value="d49a6a" onmousedown="getSeletedColor(this)">
        <input spellcheck="false" style="background-color:#ffd1aa; color: #ffd1aa;" value="ffd1aa" onmousedown="getSeletedColor(this)">
    </form>
    <br/>
    <input readonly hidden="true" style="background:white; width: 50px;" id="current_color" value="550000"></input>
    <form action="">
        <input style="margin: default; height: 18px; width: 15px;" type="radio" name="tool" value="zoompan" id="zoompan"> <u>Z</u>oom/Pan
        <input style="margin: default; height: 18px; width: 15px;" type="radio" name="tool" value="select" id="select" checked> <u>S</u>elect
        <input style="margin: default; height: 18px; width: 15px;" type="radio" name="tool" value="erase" id="erase"> <u>E</u>rase
    </form>
    <form action="">
        <input style="margin: default; height: 18px; width: 15px;" type="radio" name="map" value="county" checked> County
        <input style="margin: default; height: 18px; width: 15px;" type="radio" name="map" value="state"> State
        <input style="margin: default; height: 18px; width: 15px;" type="radio" name="map" value="other"> Other
    </form>
</div>

<svg width="960" height="600"></svg>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script src="https://d3js.org/topojson.v2.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jscolor/2.0.4/jscolor.js"></script>
<!--<script src="jscolor.js"></script>-->
<script>
    var svg = d3.select("svg");
    var path = d3.geoPath();
    var tooltip = d3.select("body").append("div").attr("class", "toolTip");

    var clickDown = true;
    var color_selcounties = [];
    for (i = 0; i < 20; i++) {
        color_selcounties[getColor(i)] = [];
    }
    var selectedCounties = [];
    var uniqueCounties = [];
    var selectedCountiesNum = selectedCounties.length;
    var t = [
        ['color', 'fips']
    ];
    var csvRows = [];

    var expArray = [
        ['color', 'fips']
    ];

    var region = function() {
        //Dedupes the list of counties, this ensures no counties are double bucketed.
        uniqueCounties = selectedCounties.filter(function(elem, pos) {
            return selectedCounties.indexOf(elem) == pos;
        });
        console.log("Master: " + uniqueCounties);

        //Dedupes the list of counties by region.
        for (i = 0; i < 20; i++) {
            if (color_selcounties[getColor(i)].length >= 1) {
                var uniqueColorCounties = color_selcounties[getColor(i)].filter(function(elem, pos) {
                    return color_selcounties[getColor(i)].indexOf(elem) == pos;
                });
                console.log(getColor(i) + ": " + uniqueColorCounties);
                t.push([getColor(i), uniqueColorCounties]);
            }
        }
    }

    var tools = function() {
        if (document.getElementById("zoompan").checked) {
            alert("zoompan");
        } else if (document.getElementById("select").checked) {
            alert("select");
        } else if (document.getElementById("erase").checked) {
            document.body.style.cursor = "pointer";
        } else {

        }
    }

    function dl_csv() {
        region();
        var csvString = expArray.join("%0A");
        var a = document.createElement('a');
        a.href = 'data:attachment/csv,' + csvString;
        a.target = '_blank';
        a.download = 'myFile.csv';

        document.body.appendChild(a);
        a.click();
    }

    d3.json("https://d3js.org/us-10m.v1.json", function(error, us) {
        if (error) throw error;

        let hoverEnabled = false;
        var mousedown = function() {
            if (document.getElementById("select").checked) {
                var self = d3.select(this);
                hoverEnabled = !self.classed('hovered');

                if (hoverEnabled) {

                    selectedCounties.push(this.__data__.id);
                    var color = document.getElementById('selcolor').value;
                    self.classed("c" + color, true);

                    color_selcounties[color].push(this.__data__.id);
                    expArray.push([color, this.__data__.id]);

                } else {
                    var ix = selectedCounties.indexOf(this.__data__.id);
                    selectedCounties.splice(ix, 1);
                }

            } else if (document.getElementById("erase").checked) {
                var self = d3.select(this);

                self.classed('deselected', true);

                var ix = selectedCounties.indexOf(this.__data__.id);
                selectedCounties.splice(ix, 1);
            }
        }

        svg.append("g")
            .attr("class", "counties")
            .selectAll("path")
            .data(topojson.feature(us, us.objects.counties).features)
            .enter()
            .append("path")
            .attr("d", path);

        svg.append("g")
            .attr("class", "state-borders")
            .selectAll("path")
            .data(topojson.feature(us, us.objects.nation).features)
            .enter()
            .append("path")
            .attr("d", path);
        svg.append("path")
            .attr("class", "state-borders")
            .attr("d", path(topojson.mesh(us, us.objects.nation, function(a, b) {
                return a !== b;
            })));
        svg.append("path")
            .attr("class", "state-borders")
            .attr("d", path(topojson.mesh(us, us.objects.states, function(a, b) {
                return a !== b;
            })));
        svg.append("path")
            .attr("class", "county-borders")
            .attr("d", path(topojson.mesh(us, us.objects.counties, function(a, b) {
                return a !== b;
            })));


        svg.selectAll('.counties path')
            .on('mousedown', mousedown)
            .on('mouseup', function() {
                hoverEnabled = false;
            })
            .on('mouseover', function() {

                tooltip
                    .style("left", 500 + "px")
                    .style("top", 70 + "px")
                    .style("display", "inline-block")
                    .html(this.__data__.id);

                var color = document.getElementById('selcolor').value;
                var self = d3.select(this);

                if (hoverEnabled) {

                    self.classed("deselected", false);
                    self.classed("c" + color, true);

                    selectedCounties.push(this.__data__.id);
                    color_selcounties[color].push(this.__data__.id);
                    expArray.push([color, this.__data__.id]);
                }
            })
            .on('mouseout', function(d) {
                tooltip.style("display", "none");
            });
    });
</script>

【问题讨论】:

  • 您有两个选择:要么提供MCVE,这在您的情况下似乎不是一个选项,要么提供整个代码,只要它是工作代码。现在这是一个巨大的代码,我们甚至无法测试(因为我们没有 topoJSON)。所以,把所有这些都放在 Plunker 或类似的东西里,对每个人来说都会更容易。
  • 您好 Gerardo,完整代码在原帖中。它是在谈论它使用的库的句子下面的代码 sn-p。
  • 我知道,这正是我的意思:这是完整的代码,但不是工作代码。
  • 我编辑了 jscolor.js 源代码。该代码现在应该可以运行,而无需您下载库。
  • 喜欢哇。这不是我编写此解决方案的方式。似乎对color_selcounties[ 'aabbcc' ] 有很大的依赖,其中aabbcc 来自a) 调用getColor() 20 次,b) #selcolor。为什么不将#selcolor 重写为#selcounty 并使用getColor(county)。它可能会解决你的很多问题(以及一般的代码)

标签: javascript html css arrays d3.js


【解决方案1】:

当你这样做时......

self.classed("c" + color, true);

您只是添加类(以“十六进制顺序”),而不是删除现有的类。

因此,您的元素将有多个类...

class = "foo bar baz"

...流行的颜色将是样式表中last class设置的颜色,它解释了您现在看到的行为。

解决方案:一个简单的解决方案就是将其更改为:

self.attr("class", "c" + color);

这会覆盖任何以前存在的类。对其他 classed 函数执行相同操作。

这是您的工作代码:https://jsfiddle.net/zbvxk4xv/

【讨论】:

  • PS:请记住,我正在回答您的问题,并且仅回答您的问题。现在,你的代码有问题,这意味着它还有很大的改进空间:你可以简化很多。
  • 另外,erase 函数应用了一个 deselected 类,它可以防止应用新颜色。这个可以改成self.attr("class", '');
  • 很好,@Gnippots,刚刚也改了。
猜你喜欢
  • 1970-01-01
  • 2020-11-28
  • 2015-12-15
  • 1970-01-01
  • 1970-01-01
  • 2020-02-12
  • 2022-12-01
  • 2019-10-22
  • 2015-01-25
相关资源
最近更新 更多