在任何图表点上获取坐标 [英] Get coords on any chart point

查看:163
本文介绍了在任何图表点上获取坐标的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想创建一个函数,
返回配置文件的高度鼠标悬停



当我在我的.json中有信息时,很容易,例如这里指的是{d:1508,a :77}。我使用这个函数:

  function mousemove(){
var x0 = x.invert (d3.mouse(this)[0]),
i = bisectDist(data,x0,1),
d0 = data [i-1],
d1 = data [i]
d = x0 - d0.distance> d1.distance - x0?d1:d0;
focus.attr(transform,translate(+ x(d.distance)+ y(d.altitude)+));
focus.select(text)text(d.altitude);
}
pre>

但是,如果可能的话,我也希望在两点相隔太远时计算高度。例如,我有此个人资料{d:1539,a:58},{d:1550,a: 158} 。所以,我返回d = 1539和d = 1550的高度,但是,我可以返回的高度为d = 1546感谢我的个人资料吗?



最好的问候,布拉茨Damien。



codepen.io/Onchman/pen/dNpeaP这里是codepen的代码,我不知道如何从外部ressource添加json,所以,尝试将其直接添加到JavaScript部分。

解决方案

引用此answer 并将其应用于代码,您的 mousemove 函数将重写为:

  function mousemove(){

var mouse = d3.mouse

var beginning = 0,
end = areaPath.getTotalLength(),
target = null;

while(true){
target = Math.floor((beginning + end)/ 2);
pos = areaPath.getPointAtLength(target);
if((target === end || target === beginning)&& pos.x!== mouse [0]){
break;
}
if(pos.x> mouse [0])end = target;
else if(pos.x< mouse [0])begin = target;
else break; // position found
}

focus.attr(transform,translate(+ mouse [0] +,+ pos.y +)
focus.select(text)。text(y.invert(pos.y).toFixed(2));
}

完整运行代码:



<!DOCTYPE html>< html>< head> < script data-require =d3@4.0.0data-semver =4.0.0src =https://d3js.org/d3.v4.min.js>< / script> < style> body {font:10px sans-serif; } .axis path,.axis line {fill:none; stroke:#000; shape-rendering:crispEdges; } .axis text {font-family:Lato; font-size:13px;填充:黑色; } .grid path,.grid line {fill:none; stroke:rgba(0,0,0,0.25); shape-rendering:crispEdges; } .area {fill:darkorange; stroke:rgba(0,0,0,1); } .marker.client .marker-bg,.marker.client path {fill:rgba(255,127,0,0.8); stroke:rgba(255,127,0,0.8); stroke-width:3; } .marker.server .marker-bg,.marker.server path {fill:rgba(0,153,51,0.8);中风:rgba(0,153,51,0.8); stroke-width:3; } .marker path {fill:none; } .legend text,.marker text {fill:black; font-weight:bold; } .marker text {text-anchor:middle; } .overlay {fill:none; pointer-events:all; } .focus circle {fill:none;中风:钢蓝}< / style>< / head>< body> < script>函数配置文件(rawData){var margin = {top:20,right:20,bottom:60,left:50},width = 960 - margin.left - margin.right,height = 500 - margin.top - margin.bottom ,innerwidth = width - margin.left - margin.right,innerheight = height - margin.top - margin.bottom; var bisectDist = d3.bisector(function(d){return d.distance;})。 var x = d3.scaleLinear()。range([0,width]); var y = d3.scaleLinear()。range([height,0]); var xAxis = d3.axisBottom()。scale(x); var yAxis = d3.axisLeft()。scale(y); var area = d3.area()。x(function(d){return x(d.distance);})y0(height).y1(function(d){return y(d.altitude);})var svg = d3.select(body)。append(svg).attr(width,width + margin.left + margin.right).attr(height,height + margin.top + margin.bottom ).append(g).attr(transform,translate(+ margin.left +,+ margin.top +)); //// d3.json('data.json' ,function(error,rawData){// if(error){// console.error(error); // return; //} var data = rawData.map(function(d){return {altitude:da,distance :dd};}); // data.sort(function(a,b){// return a.distance - b.distance; //}); x.domain(d3.extent {return d.distance;})); y.domain([0,d3.max(data,function(d){return d.altitude;})]); var x_grid = d3.axisBottom ).tickSize(-height).tickFormat(); var y_grid = d3.axisLeft()。scale(y).tickSize(-width).tickFormat(); var areaPath = svg.append('svg:path').datum(data).attr(class,area).attr(d,area).node svg.append(svg:g).attr(class,x axis).attr(transform,translate(0,+ height +)).call(xAxis).append text).attr(transform,translate(0,+ margin.top * 2 +)).attr(x,width - (margin.right + margin.left)).text Distance(km)); svg.append(svg:g).attr(class,y axis).call(yAxis).append(text).attr(transform,translate(70,0) .attr(transform,rotate(-90)).attr(y,-45).attr(dy,.71em).style(text-anchor,end) .text(Altitude(m)); svg.append(g).attr(class,x grid).attr(transform,translate(0,+ height +)).call(x_grid); svg.append(g).attr(class,y grid).call(y_grid); var focus = svg.append(g).attr(class,focus).style(display,none); focus.append(circle).attr(r,4.5); focus.append(text).attr(x,9).attr(dy,.35em); svg.append(rect).attr(class,overlay).attr(width,width).attr(height,height).on(mouseover,function style(display,null);}).on(mouseout,function(){focus.style(display,none);}).on(mousemove,mousemove);函数mousemove(){/ * var x0 = x.invert(d3.mouse(this)[0]),i = bisectDist(data,x0,1),d0 = data [i-1],d1 = data [i ],d = x0-d0.distance> d1.distance - x0? d1:d0; focus.attr(transform,translate(+ x(d.distance)+,+ y(d.altitude)+)); focus.select(text)。text(d.altitude); * / var mouse = d3.mouse(this); var beginning = 0,end = areaPath.getTotalLength(),target = null; while(true){target = Math.floor((beginning + end)/ 2); pos = areaPath.getPointAtLength(target); if((target === end || target === beginning)&& pos.x!== mouse [0]){break; } if(pos.x> mouse [0])end = target; else if(pos.x< mouse [0])begin = target; else break; // position found} focus.attr(transform,translate(+ mouse [0] +,+ pos.y +)); focus.select(text)。text(y.invert(pos.y).toFixed(2)); } var markerjson = [{id:1,name:Depart - Vielle-Aure,type:CP,description:Départ,icon:../ item_icons / iconCust / map-marker-checkpoint.svg,distance:1488,altitude:145},{id:2,name:CP1 - Col de Portet ,type:CP,description:1er CP,icon:../item_icons/iconCust/map-marker-checkpoint.svg,distance:1496 :37},{id:3,name:CP2-Artigues,type:CP,description:2èmeCP item4,name:CP3-Col De Sencours,item_icons / iconCust / map-marker-checkpoint.svg,distance:1504,altitude: ,type:CP,description:3èmeCP,icon:../item_icons/iconCust/map-marker-checkpoint.svg,distance:1512 :137},{id:5,name:CP4-Hautacam,type:CP,description:4èmeCP,icon:../ item_icons / iconCust / map-marker-checkpoint.svg,distance:1521,altitude:45}]; / * d3.json('markersjson',function(error,markerData){if(error){console.error(error); return;} * / / * markerData = markerjson; var markers = markerData.map ){return {id:marker.id,name:marker.name,type:marker.type,description:marker.description,icon:marker.icon,distance:marker.distance,};}); markers.forEach (marker,i){setTimeout(function(){setItem(marker,data,svg,innerheight,x,y);},1000 + 500 * i);}); * / //}); //}); } function setItem(marker,data,svg,innerheight,x,y){altitude = getAltitude(data,marker); var radius = 20,xPos = x(marker.distance) - radius - 3,yPosStart = innerheight - radius -3,yPosEnd = y(altitude) - radius * 2; var markerG = svg.append('g').attr('class','marker'+ marker.type.toLowerCase()).attr('transform','translate('+ xPos +','+ yPosStart + ')').attr('opacity',0); markerG.transition().duration(1000).attr('transform','translate('+ xPos +','+ yPosEnd +')'attr('opacity',1); markG.append(svg:image).attr('class','marker-bg').attr(xlink:href,cp-x_15_31.png).attr(x,2 ).attr(width,40).attr(height,40); markG.append('text').attr('x',radius).attr('y',radius * 0.9)markerG.append('text').attr('x',radius).attr ',radius * 1.5).attr(transform,translate(0,15)).text(marker.name); } function getAltitude(data,marker){var i = 0; while(i p>


I wanted to create a function who return the altitude of the profile with a mouseover

When I have the informations in my .json, it's easy, here for exemple, the point refer to {"d": 1508, "a": 77"}. I use this function:

function mousemove() {
        var x0 = x.invert(d3.mouse(this)[0]),
            i = bisectDist(data, x0, 1),
            d0 = data[i - 1],
            d1 = data[i],
            d = x0 - d0.distance > d1.distance - x0 ? d1 : d0;
        focus.attr("transform", "translate(" + x(d.distance) + "," + y(d.altitude) + ")");
        focus.select("text").text(d.altitude);
      }

But, I also would like, if possible, to calculate the altitude when I have 2 point too far apart. For exemple, I have this profile for {"d": 1539, "a": 58}, {"d": 1550, "a": 158}. So, I return the altitude for d=1539 and d=1550, but, can I return the altitude for d=1546 thanks to my profile?

Best Regards, Braz Damien.

codepen.io/Onchman/pen/dNpeaP Here is the code on codepen, I don't know how to add json from an external ressource, so, i tried to add it directly in the JavaScript part.

解决方案

Referring to my code in this answer and applying it to your code, your mousemove function would be re-written like this:

function mousemove() {

    var mouse = d3.mouse(this);

    var beginning = 0,
        end = areaPath.getTotalLength(),
        target = null;

    while (true){
      target = Math.floor((beginning + end) / 2);
      pos = areaPath.getPointAtLength(target);
      if ((target === end || target === beginning) && pos.x !== mouse[0]) {
          break;
      }
      if (pos.x > mouse[0])      end = target;
      else if (pos.x < mouse[0]) beginning = target;
      else break; //position found
    }

    focus.attr("transform","translate(" + mouse[0] + "," + pos.y +")");
    focus.select("text").text(y.invert(pos.y).toFixed(2));
}

Full running code:

<!DOCTYPE html>
<html>

<head>
  <script data-require="d3@4.0.0" data-semver="4.0.0" src="https://d3js.org/d3.v4.min.js"></script>
  <style>
    body {
      font: 10px sans-serif;
    }
    
    .axis path,
    .axis line {
      fill: none;
      stroke: #000;
      shape-rendering: crispEdges;
    }
    
    .axis text {
      font-family: Lato;
      font-size: 13px;
      fill: black;
    }
    
    .grid path,
    .grid line {
      fill: none;
      stroke: rgba(0, 0, 0, 0.25);
      shape-rendering: crispEdges;
    }
    
    .area {
      fill: darkorange;
      stroke: rgba(0, 0, 0, 1);
    }
    
    .marker.client .marker-bg,
    .marker.client path {
      fill: rgba(255, 127, 0, 0.8);
      stroke: rgba(255, 127, 0, 0.8);
      stroke-width: 3;
    }
    
    .marker.server .marker-bg,
    .marker.server path {
      fill: rgba(0, 153, 51, 0.8);
      stroke: rgba(0, 153, 51, 0.8);
      stroke-width: 3;
    }
    
    .marker path {
      fill: none;
    }
    
    .legend text,
    .marker text {
      fill: black;
      font-weight: bold;
    }
    
    .marker text {
      text-anchor: middle;
    }
    
    .overlay {
      fill: none;
      pointer-events: all;
    }
    
    .focus circle {
      fill: none;
      stroke: steelblue;
    }
  </style>
</head>

<body>
  <script>
    function profile(rawData) {
      
      var margin = {
          top: 20,
          right: 20,
          bottom: 60,
          left: 50
        },
        width = 960 - margin.left - margin.right,
        height = 500 - margin.top - margin.bottom,
        innerwidth = width - margin.left - margin.right,
        innerheight = height - margin.top - margin.bottom;

      var bisectDist = d3.bisector(function(d) {
        return d.distance;
      }).left;

      var x = d3.scaleLinear().range([0, width]);

      var y = d3.scaleLinear().range([height, 0]);

      var xAxis = d3.axisBottom().scale(x);

      var yAxis = d3.axisLeft().scale(y);


      var area = d3.area().x(function(d) {
        return x(d.distance);
      }).y0(height).y1(function(d) {
        return y(d.altitude);
      })


      var svg = d3.select("body").append("svg")
        .attr("width", width + margin.left + margin.right)
        .attr("height", height + margin.top + margin.bottom)
        .append("g")
        .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

//
//      d3.json('data.json', function(error, rawData) {
//        if (error) {
//          console.error(error);
//          return;
//        }

        var data = rawData.map(function(d) {
          return {
            altitude: d.a,
            distance: d.d
          };
        });

        //             data.sort(function(a, b) {
        //                return a.distance - b.distance;
        //                });


        x.domain(d3.extent(data, function(d) {
          return d.distance;
        }));

        y.domain([0, d3.max(data, function(d) {
          return d.altitude;
        })]);

        var x_grid = d3.axisBottom().scale(x).tickSize(-height).tickFormat("");

        var y_grid = d3.axisLeft().scale(y).tickSize(-width).tickFormat("");


        var areaPath = svg.append('svg:path')
          .datum(data)
          .attr("class", "area")
          .attr("d", area)
          .node();

        svg.append("svg:g")
          .attr("class", "x axis")
          .attr("transform", "translate(0," + height + ")")
          .call(xAxis)
          .append("text")
          .attr("transform", "translate(0," + margin.top * 2 + ")")
          .attr("x", width - (margin.right + margin.left))
          .text("Distance (km)");

        svg.append("svg:g")
          .attr("class", "y axis")
          .call(yAxis)
          .append("text")
          .attr("transform", "translate(70,0)")
          .attr("transform", "rotate(-90)")
          .attr("y", -45).attr("dy", ".71em")
          .style("text-anchor", "end")
          .text("Altitude (m)");

        svg.append("g")
          .attr("class", "x grid")
          .attr("transform", "translate(0," + height + ")")
          .call(x_grid);

        svg.append("g")
          .attr("class", "y grid")
          .call(y_grid);


        var focus = svg.append("g")
          .attr("class", "focus")
          .style("display", "none");

        focus.append("circle")
          .attr("r", 4.5);

        focus.append("text")
          .attr("x", 9)
          .attr("dy", ".35em");

        svg.append("rect")
          .attr("class", "overlay")
          .attr("width", width)
          .attr("height", height)
          .on("mouseover", function() {
            focus.style("display", null);
          })
          .on("mouseout", function() {
            focus.style("display", "none");
          })
          .on("mousemove", mousemove);


        function mousemove() {
          /*
          var x0 = x.invert(d3.mouse(this)[0]),
            i = bisectDist(data, x0, 1),
            d0 = data[i - 1],
            d1 = data[i],
            d = x0 - d0.distance > d1.distance - x0 ? d1 : d0;
          focus.attr("transform", "translate(" + x(d.distance) + "," + y(d.altitude) + ")");
          focus.select("text").text(d.altitude);
          */
          
          var mouse = d3.mouse(this);
          
          var beginning = 0,
                end = areaPath.getTotalLength(),
                target = null;

            while (true){
              target = Math.floor((beginning + end) / 2);
              pos = areaPath.getPointAtLength(target);
              if ((target === end || target === beginning) && pos.x !== mouse[0]) {
                  break;
              }
              if (pos.x > mouse[0])      end = target;
              else if (pos.x < mouse[0]) beginning = target;
              else break; //position found
            }
            
            focus.attr("transform","translate(" + mouse[0] + "," + pos.y +")");
            focus.select("text").text(y.invert(pos.y).toFixed(2));
          
        }



        var markerjson = [{
          "id": "1",
          "name": "Depart - Vielle-Aure",
          "type": "CP",
          "description": "Départ",
          "icon": "../item_icons/iconCust/map-marker-checkpoint.svg",
          "distance": "1488",
          "altitude": "145"
        }, {
          "id": "2",
          "name": "CP1 - Col de Portet",
          "type": "CP",
          "description": "1er CP",
          "icon": "../item_icons/iconCust/map-marker-checkpoint.svg",
          "distance": "1496",
          "altitude": "37"
        }, {
          "id": "3",
          "name": "CP2 - Artigues",
          "type": "CP",
          "description": "2ème CP",
          "icon": "../item_icons/iconCust/map-marker-checkpoint.svg",
          "distance": "1504",
          "altitude": "145"
        }, {
          "id": "4",
          "name": "CP3 - Col De Sencours",
          "type": "CP",
          "description": "3ème CP",
          "icon": "../item_icons/iconCust/map-marker-checkpoint.svg",
          "distance": "1512",
          "altitude": "137"
        }, {
          "id": "5",
          "name": "CP4 - Hautacam",
          "type": "CP",
          "description": "4ème CP",
          "icon": "../item_icons/iconCust/map-marker-checkpoint.svg",
          "distance": "1521",
          "altitude": "45"
        }];
        
        /*
        d3.json('markersjson', function(error, markerData) {
          if (error) {
            console.error(error);
            return;
          }
        */
        
        /*
        markerData = markerjson;

          var markers = markerData.map(function(marker) {
            return {
              id: marker.id,
              name: marker.name,
              type: marker.type,
              description: marker.description,
              icon: marker.icon,
              distance: marker.distance,
            };
          });


          markers.forEach(function(marker, i) {
            setTimeout(function() {
              setItem(marker, data, svg, innerheight, x, y);
            }, 1000 + 500 * i);
          });

        */

        // });
        
      //});

    }

    function setItem(marker, data, svg, innerheight, x, y) {
      altitude = getAltitude(data, marker);
      var radius = 20,
        xPos = x(marker.distance) - radius - 3,
        yPosStart = innerheight - radius - 3,
        yPosEnd = y(altitude) - radius * 2;


      var markerG = svg.append('g')
        .attr('class', 'marker ' + marker.type.toLowerCase())
        .attr('transform', 'translate(' + xPos + ', ' + yPosStart + ')')
        .attr('opacity', 0);

      markerG.transition()
        .duration(1000)
        .attr('transform', 'translate(' + xPos + ', ' + yPosEnd + ')')
        .attr('opacity', 1);

      markerG.append("svg:image")
        .attr('class', 'marker-bg')
        .attr("xlink:href", "cp-x_15_31.png")
        .attr("x", "2")
        .attr("width", "40")
        .attr("height", "40");

      markerG.append('text')
        .attr('x', radius)
        .attr('y', radius * 0.9)

      markerG.append('text')
        .attr('x', radius)
        .attr('y', radius * 1.5)
        .attr("transform", "translate(0,15)")
        .text(marker.name);
    }



    function getAltitude(data, marker) {
      var i = 0;
      while (i < data.length) {
        if (data[i].distance == marker.distance) {
          return data[i].altitude;
        } else {
          if (i < data.length) {
            if ((data[i].distance < marker.distance) && (marker.distance < data[i + 1].distance)) {
              return ((data[i].altitude + data[i + 1].altitude) / 2)
            }
          } else {
            if ((data[i - 1].distance < marker.distance) && (marker.distance < data[i].distance)) {
              return ((data[i - 1].altitude + data[i].altitude) / 2)
            }
          }
        }
        i++;
      }
    }

    function removeItem(marker, svg, innerheight, x) {
      markerG.clear;
    }
    var profilejson = [{
      "d": 1488,
      "a": 145
    }, {
      "d": 1489,
      "a": 132
    }, {
      "d": 1490,
      "a": 70
    }, {
      "d": 1491,
      "a": 115
    }, {
      "d": 1492,
      "a": 44
    }, {
      "d": 1493,
      "a": 117
    }, {
      "d": 1494,
      "a": 9
    }, {
      "d": 1495,
      "a": 64
    }, {
      "d": 1496,
      "a": 37
    }, {
      "d": 1497,
      "a": 145
    }, {
      "d": 1498,
      "a": 14
    }, {
      "d": 1499,
      "a": 86
    }, {
      "d": 1500,
      "a": 119
    }, {
      "d": 1501,
      "a": 200
    }, {
      "d": 1502,
      "a": 23
    }, {
      "d": 1503,
      "a": 85
    }, {
      "d": 1504,
      "a": 145
    }, {
      "d": 1505,
      "a": 49
    }, {
      "d": 1506,
      "a": 145
    }, {
      "d": 1507,
      "a": 58
    }, {
      "d": 1509,
      "a": 124
    }, {
      "d": 1510,
      "a": 69
    }, {
      "d": 1511,
      "a": 14
    }, {
      "d": 1512,
      "a": 137
    }, {
      "d": 1513,
      "a": 45
    }, {
      "d": 1514,
      "a": 114
    }, {
      "d": 1515,
      "a": 186
    }, {
      "d": 1516,
      "a": 219
    }, {
      "d": 1517,
      "a": 199
    }, {
      "d": 1518,
      "a": 223
    }, {
      "d": 1519,
      "a": 28
    }, {
      "d": 1520,
      "a": 185
    }, {
      "d": 1521,
      "a": 45
    }, {
      "d": 1522,
      "a": 63
    }, {
      "d": 1523,
      "a": 18
    }, {
      "d": 1524,
      "a": 144
    }, {
      "d": 1525,
      "a": 17
    }, {
      "d": 1526,
      "a": 99
    }, {
      "d": 1527,
      "a": 214
    }, {
      "d": 1528,
      "a": 237
    }, {
      "d": 1530,
      "a": 194
    }, {
      "d": 1531,
      "a": 186
    }, {
      "d": 1532,
      "a": 19
    }, {
      "d": 1533,
      "a": 200
    }, {
      "d": 1534,
      "a": 23
    }, {
      "d": 1535,
      "a": 185
    }, {
      "d": 1536,
      "a": 45
    }, {
      "d": 1537,
      "a": 249
    }, {
      "d": 1538,
      "a": 145
    }, {
      "d": 1539,
      "a": 58
    }, {
      "d": 1550,
      "a": 158
    }];
    
    profile(profilejson);

/*
    $.ajax({
      url: 'profilejson',
      method: 'GET',
      success: function(data) {
        console.log("data =", data);
        profile(data);
      },
      error: function(data) {
        console.log("err" + data)
      }
    });
*/
  </script>
</body>

</html>

这篇关于在任何图表点上获取坐标的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆