[js] D3 drawing parallel coordinates

Keywords: Google Firefox xml encoding

Parallel coordinate system (parallel) is a kind of commonly used chart to visualize high-dimensional data. Parallel coordinate system has a good mathematical basis, and its projective geometry interpretation and dual characteristics make it suitable for visual data analysis.

Article catalog

1. Drawing with D3.js

1.1 logic code

index.html:

<!DOCTYPE html>
<meta charset="utf-8">
<style>

svg {
  font: 10px sans-serif;
}

.background path {
  fill: none;
  stroke: #ccc;
  stroke-opacity: .4;
  shape-rendering: crispEdges;
}

.foreground path {
  fill: none;
  stroke: steelblue;
  stroke-opacity: .7;
}

.brush .extent {
  fill-opacity: .3;
  stroke: #fff;
  shape-rendering: crispEdges;
}

.axis line, .axis path {
  fill: none;
  stroke: #000;
  shape-rendering: crispEdges;
}

.axis text {
  text-shadow: 0 1px 0 #fff;
}

</style>
<body>
<div id="graph-container"></div>

<a id="btnSaveSVG" href="#">preservationSVG</a>
<a id="btnSavePNG" href="#">preservationPNG</a>

<script src="https://d3js.org/d3.v3.min.js"></script>
<script>

var m = [30, 10, 10, 10],
    w = 1400 - m[1] - m[3],
    h = 500 - m[0] - m[2];

var x = d3.scale.ordinal().rangePoints([0, w], .5),
    y = {};

var line = d3.svg.line(),
    axis = d3.svg.axis().orient("left"),
    background,
    foreground;

var svg = d3.select("#graph-container").append("svg")
    .attr("width", w + m[1] + m[3])
    .attr("height", h + m[0] + m[2])
	.append("g")
    .attr("transform", "translate(" + m[3] + "," + m[0] + ")");

d3.csv("cost-of-living.csv", function(error, cities) {
  if (error) throw error;

  // Extract the list of dimensions and create a scale for each.
  x.domain(dimensions = d3.keys(cities[0]).filter(function(d) {
    return d != "City" && (y[d] = d3.scale.linear()
        .domain(d3.extent(cities, function(p) { return +p[d]; }))
        .range([h, 0]));
  }));

  // Add grey background lines for context.
  background = svg.append("g")
      .attr("class", "background")
    .selectAll("path")
      .data(cities)
    .enter().append("path")
      .attr("d", path);

  // Add blue foreground lines for focus.
  foreground = svg.append("g")
      .attr("class", "foreground")
    .selectAll("path")
      .data(cities)
    .enter().append("path")
      .attr("d", path);

  // Add a group element for each dimension.
  var g = svg.selectAll(".dimension")
      .data(dimensions)
    .enter().append("g")
      .attr("class", "dimension")
      .attr("transform", function(d) { return "translate(" + x(d) + ")"; });

  // Add an axis and title.
  g.append("g")
      .attr("class", "axis")
      .each(function(d) { d3.select(this).call(axis.scale(y[d])); })
    .append("text")
      .attr("text-anchor", "middle")
      .attr("y", -9)
      .text(String);

  // Add and store a brush for each axis.
  g.append("g")
      .attr("class", "brush")
      .each(function(d) { d3.select(this).call(y[d].brush = d3.svg.brush().y(y[d]).on("brush", brush)); })
    .selectAll("rect")
      .attr("x", -8)
      .attr("width", 16);
});

// Returns the path for a given data point.
function path(d) {
  return line(dimensions.map(function(p) { return [x(p), y[p](d[p])]; }));
}

// Handles a brush event, toggling the display of foreground lines.
function brush() {
  var actives = dimensions.filter(function(p) { return !y[p].brush.empty(); }),
      extents = actives.map(function(p) { return y[p].brush.extent(); });
  foreground.style("display", function(d) {
    return actives.every(function(p, i) {
      return extents[i][0] <= d[p] && d[p] <= extents[i][1];
    }) ? null : "none";
  });
}

// Download SVG
d3.select("#btnSaveSVG").on("click", function() {

    var svgHeadInfo = '<?xml version="1.0" encoding="UTF-8"?>\n\r';
	var svgSource = d3.select("svg")
                .attr("version", 1.1)
                .attr("xmlns", "http://www.w3.org/2000/svg")
                .node().parentNode.innerHTML;
 
	console.log(svgSource);
	console.log(btoa(svgHeadInfo + svgSource));
    d3.select(this)
        .attr("href-lang", "image/svg+xml")
        .attr("href", "data:image/svg+xml;base64," + btoa(svgHeadInfo + svgSource))
        .attr("download", "file.svg");
});

// Download PNG
 d3.select("#btnSavePNG").on("click", function() {
	var svgHeadInfo = '<?xml version="1.0" encoding="UTF-8"?>\n\r';
	var svgSource = d3.select("svg")
                .attr("version", 1.1)
                .attr("xmlns", "http://www.w3.org/2000/svg")
                .node().parentNode.innerHTML;
            var serializer = new XMLSerializer();
        var source = svgHeadInfo + svgSource;
        var image = new Image;
        image.src = "data:image/svg+xml;charset=utf-8," + encodeURIComponent(source);
        var canvas = document.createElement("canvas");
        canvas.width = 1200;
        canvas.height = 800;
        var context = canvas.getContext("2d");
        context.fillStyle = '#fff';//#The PNG after fff setting is saved is white  
        context.fillRect(0, 0, 10000, 10000);
        image.onload = function() {  
          context.drawImage(image, 0, 0);  
          var a = document.createElement("a");  
          a.download = "name.png";  
          a.href = canvas.toDataURL("image/png");  
          a.click();  
      }; 
});

</script>
</body>

cost-of-living.csv data file

City,Consumer Price,Rent,Consumer Price+Rent,Groceries,Restaurant Price,Local Purch. Power
"Trondheim, Norway",188.91,59.16,142.21,193.94,160.23,67.01
"Stavanger, Norway",171.32,78.08,137.76,147.74,201.16,78.50
"Zurich, Switzerland",152.84,74.58,124.67,143.70,138.79,142.77
"Oslo, Norway",152.03,57.40,117.97,139.22,155.75,99.31
"Geneva, Switzerland",146.24,79.05,122.06,138.95,135.25,115.54
"Bern, Switzerland",142.44,57.44,111.85,126.78,103.59,149.28
"Lucerne, Switzerland",139.94,72.45,115.65,146.52,95.72,105.65
"Perth, Australia",139.63,43.76,105.13,113.13,131.61,125.08
"Bergen, Norway",138.79,55.98,108.98,135.46,130.23,97.02
"Tokyo, Japan",135.23,95.43,120.91,120.42,91.68,90.14
"Sydney, Australia",132.39,86.25,115.79,121.11,110.98,97.23
"Adelaide, Australia",129.60,47.30,99.98,120.68,121.44,112.19
"Monaco, Monaco",128.15,173.08,144.32,89.80,138.14,62.30
"Copenhagen, Denmark",123.82,48.65,96.77,104.25,139.11,97.43
"Edinburgh, United Kingdom",122.52,38.21,92.18,92.92,143.02,95.08
"Melbourne, Australia",121.53,64.37,100.96,112.50,102.37,87.81
"Dublin, Ireland",119.56,48.30,93.91,109.96,113.19,93.54
"London, United Kingdom",118.52,87.34,107.30,92.59,117.54,88.58
"Arhus, Denmark",115.96,65.90,97.94,94.68,132.05,73.97
"Canberra, Australia",115.89,53.55,93.45,106.77,94.30,115.91
"Brisbane, Australia",114.70,57.19,94.00,113.64,101.33,100.49
"Paris, France",113.88,63.47,95.73,95.93,112.89,82.49
"Malmo, Sweden",112.89,38.45,86.10,92.55,129.79,96.70
"Toulouse, France",112.28,29.90,82.63,89.10,105.33,82.70
"Riyadh, Saudi Arabia",112.03,19.91,78.87,138.45,41.65,70.51
"Amsterdam, Netherlands",110.78,64.61,94.16,69.93,114.88,88.83
"Darwin, Australia",110.41,56.44,90.98,92.67,111.09,121.91
"Auckland, New Zealand",110.36,36.80,83.89,98.74,88.77,97.68
"Gent, Belgium",109.27,36.38,83.04,81.58,109.49,83.02
"Stockholm, Sweden",109.14,37.75,83.45,87.42,117.66,85.65
"Brussels, Belgium",109.10,40.63,84.46,91.44,109.75,85.76
"Aberdeen, United Kingdom",109.08,42.04,84.95,103.80,110.60,119.20
"Boston, MA, United States",106.80,69.66,93.43,113.24,86.06,109.87
"Dusseldorf, Germany",106.51,25.77,77.45,77.03,119.73,157.89
"Wellington, New Zealand",106.02,37.02,81.19,104.20,93.89,90.61
"Turin, Italy",105.68,40.22,82.12,86.86,107.47,46.42
"Rome, Italy",105.60,60.03,89.20,87.02,113.68,57.49
"Vancouver, Canada",105.29,60.49,89.17,103.55,92.54,98.12
"Edmonton, Canada",105.28,38.95,81.40,104.56,86.97,86.09
"Brighton, United Kingdom",104.73,54.42,86.62,80.84,87.34,128.05
"Birmingham, United Kingdom",104.57,42.93,82.39,94.22,90.62,71.95
"Toronto, Canada",104.53,52.42,85.77,96.13,86.13,104.11
"Helsinki, Finland",104.08,56.58,86.98,81.00,101.69,96.15
"Venice, Italy",103.56,31.33,77.56,70.18,89.87,76.23
"Honolulu, HI, United States",103.46,59.01,87.47,103.67,78.28,90.60
"Calgary, Canada",103.38,40.93,80.91,99.95,81.08,124.17
"Sao Paolo, Brazil",102.96,35.60,78.72,62.93,73.58,46.26
"Tampere, Finland",102.68,30.37,76.65,100.74,98.33,93.84
"San Francisco, CA, United States",102.52,90.04,98.03,97.84,83.21,89.35
"Cagliari, Italy",101.88,29.29,75.76,72.93,114.90,66.47
"Hanover, Germany",101.82,28.11,75.29,82.62,79.95,90.76
"Belfast, United Kingdom",101.74,22.58,73.25,88.98,113.28,69.18
"Vienna, Austria",101.47,46.87,81.82,82.49,80.97,99.19
"Seattle, WA, United States",101.04,48.15,82.01,100.90,82.89,107.23
"Strasbourg, France",100.86,32.03,76.09,76.03,126.38,79.49
"Florence, Italy",100.43,41.39,79.18,72.16,94.28,66.66
"Thessaloniki, Greece",100.39,18.96,71.08,69.76,95.91,42.30
"Erlangen, Germany",100.39,33.07,76.16,92.92,80.27,28.69
"Hamburg, Germany",100.18,37.35,77.57,92.62,76.50,90.42
"Haifa, Israel",100.12,26.52,73.63,78.81,94.18,74.63
"Reykjavik, Iceland",100.11,31.82,75.53,95.54,90.64,81.22
"New York, NY, United States",100.00,100.00,100.00,100.00,100.00,100.00
"Leeds, United Kingdom",98.85,34.95,75.85,81.88,107.45,85.65
"Phoenix, AZ, United States",98.57,32.76,74.88,85.05,72.83,97.47
"Washington, DC, United States",98.19,69.37,87.81,89.39,81.26,97.37
"Linkoping, Sweden",98.06,26.92,72.46,90.51,102.37,114.78
"Montreal, Canada",97.86,37.57,76.16,94.88,92.23,109.41
"Bologna, Italy",97.82,38.03,76.31,92.02,89.53,84.84
"Nice, France",96.89,34.95,74.60,81.58,85.89,85.58
"Milan, Italy",96.88,49.22,79.73,74.25,106.38,74.06
"Winnipeg, Canada",96.64,32.72,73.63,96.90,74.52,97.96
"Athens, Greece",96.49,20.82,69.25,71.85,97.63,48.42
"Singapore, Singapore",96.08,90.69,94.14,82.76,65.10,93.29
"Munich, Germany",95.95,46.08,78.00,82.22,87.02,112.58
"Bordeaux, France",95.92,27.63,71.34,78.45,93.93,67.43
"Genoa, Italy",95.06,35.04,73.46,82.91,98.27,115.78
"Manchester, United Kingdom",94.96,36.44,73.90,79.54,90.48,95.97
"Christchurch, New Zealand",94.35,28.00,70.47,88.50,77.65,82.57
"Halifax, Canada",94.30,34.13,72.64,95.04,79.02,119.94
"San Jose, CA, United States",94.11,73.36,86.64,82.33,82.04,113.13
"Columbus, OH, United States",94.03,20.43,67.54,86.75,75.11,112.75
"Stuttgart, Germany",94.01,33.18,72.12,68.14,81.10,119.70
"Marbella, Spain",93.95,30.68,71.18,69.65,99.73,107.63
"Chania, Greece",93.77,18.01,66.50,69.52,88.97,46.87
"Ottawa, Canada",93.76,36.87,73.29,96.84,83.34,116.01
"Brasilia, Brazil",93.08,33.99,71.81,65.89,69.44,32.70
"Hartford, CT, United States",92.90,47.57,76.59,108.41,72.13,109.10
"Indianapolis, IN, United States",92.50,31.99,70.72,72.01,69.91,281.77
"Marseille, France",92.13,31.44,70.28,88.65,82.98,102.35
"Frankfurt, Germany",92.02,34.75,71.41,65.96,80.00,115.22
"Rio De Janeiro, Brazil",91.85,39.61,73.05,59.80,69.92,42.76
"Nicosia, Cyprus",91.80,25.66,68.00,76.36,100.08,65.24
"London, Canada",91.51,34.41,70.96,78.95,80.36,94.75
"Lyon, France",91.14,34.41,70.73,82.18,92.00,83.91
"San Diego, CA, United States",91.05,57.88,79.11,81.09,84.34,109.84
"Los Angeles, CA, United States",90.87,63.97,81.19,73.58,70.46,122.29
"San Juan, Puerto Rico",90.78,31.15,69.32,69.25,73.68,30.49
"Cologne, Germany",90.73,29.58,68.72,74.64,82.78,114.48
"Minneapolis, MN, United States",90.26,34.78,70.29,72.84,77.16,108.19
"Tampa, FL, United States",89.97,32.39,69.25,64.01,62.16,90.85
"Sliema, Malta",89.88,26.35,67.02,70.55,89.05,80.50
"Berlin, Germany",89.09,35.80,69.91,75.36,71.71,133.19
"Waterloo, Canada",89.02,29.71,67.67,87.06,67.85,101.67
"Baltimore, MD, United States",88.99,54.12,76.44,101.95,78.13,118.83
"Sevilla, Spain",88.96,18.79,63.70,64.69,81.85,73.40
"Beirut, Lebanon",88.92,37.05,70.25,44.54,76.19,25.73
"Barcelona, Spain",88.82,33.92,69.06,65.26,88.14,86.59
"Philadelphia, PA, United States",88.36,58.85,77.74,83.39,78.50,98.96
"Hong Kong, Hong Kong",88.13,106.22,94.64,85.25,79.06,91.77
"Madrid, Spain",87.93,39.57,70.52,60.85,88.31,93.96
"Graz, Austria",87.76,35.14,68.82,77.79,72.87,101.91
"Dallas, TX, United States",87.62,38.51,69.95,67.93,72.85,113.86
"Nuremberg, Germany",87.54,30.04,66.84,69.56,78.79,107.62
"Jerusalem, Israel",87.54,35.97,68.98,70.06,77.82,68.10
"Houston, TX, United States",86.97,39.70,69.96,74.96,68.89,137.32
"Bilbao, Spain",86.62,37.70,69.01,60.47,93.40,94.48
"Leicester, United Kingdom",86.15,27.80,65.15,82.09,67.83,103.13
"Campinas, Brazil",85.98,23.70,63.56,54.81,66.22,75.34
"Abu Dhabi, United Arab Emirates",85.84,80.82,84.04,72.59,92.39,134.56
"Chicago, IL, United States",85.41,49.96,72.65,72.28,74.80,119.92
"Saint Louis, MO, United States",84.91,23.22,62.71,84.75,64.89,140.12
"Doha, Qatar",84.73,63.50,77.09,81.63,70.84,153.01
"Florianopolis, Brazil",83.88,27.46,63.58,69.26,48.84,37.89
"Pittsburgh, PA, United States",83.72,22.56,61.71,69.83,56.65,135.19
"Montevideo, Uruguay",83.56,26.22,62.93,66.73,68.83,30.20
"Dubai, United Arab Emirates",83.39,67.87,77.80,66.31,78.57,149.89
"Bremen, Germany",82.85,22.77,61.23,70.65,65.58,88.11
"Porto Alegre, Brazil",82.33,23.75,61.25,50.02,51.01,50.42
"Cincinnati, OH, United States",82.18,29.11,63.08,72.09,61.97,103.60
"Valencia, Spain",81.87,19.60,59.46,57.18,73.68,84.53
"Patras, Greece",81.84,17.58,58.71,63.73,76.59,45.64
"Curitiba, Brazil",81.10,22.60,60.05,57.17,45.90,48.94
"Detroit, MI, United States",79.72,30.54,62.02,75.82,67.24,92.61
"Denver, CO, United States",79.39,48.43,68.25,69.23,64.57,126.10
"Austin, TX, United States",78.92,45.55,66.91,80.38,64.96,131.95
"Portland, OR, United States",77.22,33.80,61.59,67.34,68.36,123.02
"Londrina, Brazil",76.68,23.42,57.51,49.26,54.52,30.91
"Lisbon, Portugal",76.33,29.49,59.47,58.65,62.75,62.83
"Coimbra, Portugal",75.74,15.84,54.18,68.50,48.93,53.72
"Split, Croatia",75.60,15.73,54.05,59.97,59.67,51.15
"Salvador, Brazil",75.53,19.72,55.44,49.95,45.98,33.97
"Casablanca, Morocco",75.49,36.51,61.46,74.49,54.77,15.00
"Des Moines, IA, United States",75.45,29.18,58.80,68.64,54.51,104.04
"Ljubljana, Slovenia",75.42,28.59,58.56,62.73,61.98,56.95
"Maribor, Slovenia",75.17,28.11,58.23,55.86,56.85,52.19
"Istanbul, Turkey",74.89,23.21,56.29,55.95,55.29,57.60
"Astana, Kazakhstan",74.58,36.29,60.80,50.62,38.83,32.01
"Johannesburg, South Africa",74.23,38.34,61.31,59.72,55.42,89.43
"Balneario Camboriu, Brazil",74.02,18.98,54.21,48.29,52.10,25.21
"Las Vegas, NV, United States",73.98,36.00,60.31,66.83,70.80,138.32
"Manama, Bahrain",71.86,47.24,63.00,63.60,80.96,64.67
"Zagreb, Croatia",71.49,21.12,53.36,57.85,60.09,54.58
"Baku, Azerbaijan",71.24,41.03,60.37,53.20,68.17,26.38
"San Jose, Costa Rica",71.17,25.95,54.90,78.60,52.85,38.83
"Riga, Latvia",70.75,15.16,50.74,52.59,66.61,34.70
"Seoul, South Korea",70.53,37.10,58.50,71.05,50.57,121.54
"Fortaleza, Brazil",70.30,20.94,52.54,51.92,47.81,59.92
"Bratislava, Slovakia",69.94,29.17,55.27,55.22,50.61,48.64
"Santiago, Chile",69.89,20.62,52.16,53.54,58.73,44.98
"Bogota, Colombia",69.50,21.86,52.36,64.95,41.91,26.24
"Belo Horizonte, Brazil",69.08,21.66,52.01,46.67,60.15,55.99
"Porto, Portugal",69.05,20.32,51.51,52.65,47.06,52.55
"Santa Cruz De Tenerife, Spain",68.98,22.67,52.31,54.01,56.80,71.41
"Novosibirsk, Russia",67.96,26.92,53.19,46.04,77.27,38.33
"Saint Petersburg, Russia",67.58,31.20,54.49,49.09,73.42,40.98
"Kaunas, Lithuania",67.44,16.93,49.26,52.66,65.17,31.72
"Tallinn, Estonia",66.95,15.82,48.55,52.25,60.70,49.68
"Perm, Russia",66.64,18.04,49.15,59.01,56.54,30.50
"Budva, Montenegro",66.16,19.29,49.29,53.35,57.43,33.57
"Amman, Jordan",65.95,14.51,47.44,60.72,51.73,37.85
"Buenos Aires, Argentina",65.93,21.58,49.97,55.69,57.34,40.33
"Taipei, Taiwan",65.66,23.16,50.36,82.38,33.92,75.97
"Jakarta, Indonesia",64.11,28.25,51.21,69.89,39.67,25.60
"Vilnius, Lithuania",63.84,15.58,46.47,52.08,40.18,34.61
"Budapest, Hungary",63.41,14.03,45.64,46.92,46.75,37.44
"Yerevan, Armenia",63.39,25.89,49.89,37.69,57.59,19.61
"Yekaterinburg, Russia",63.22,21.27,48.12,51.07,72.49,45.59
"Prague, Czech Republic",62.91,27.59,50.20,49.50,43.30,58.44
"Debrecen, Hungary",62.47,12.52,44.49,51.07,48.93,43.11
"Tehran, Iran",62.43,30.99,51.11,56.64,49.01,45.70
"Brno, Czech Republic",62.35,20.49,47.28,48.46,43.52,68.36
"Izmir, Turkey",62.12,14.54,45.00,51.08,42.39,46.25
"Podgorica, Montenegro",61.72,17.49,45.80,44.70,62.72,42.01
"Medellin, Colombia",61.43,15.28,44.82,45.49,42.01,18.61
"Antalya, Turkey",61.00,10.27,42.74,44.91,42.74,39.81
"Kosice, Slovakia",60.86,21.19,46.58,47.90,42.65,54.82
"Ankara, Turkey",60.73,14.95,44.25,43.66,46.31,58.15
"Kiev, Ukraine",59.87,31.70,49.73,41.78,61.94,27.80
"Mexico City, Mexico",59.68,23.22,46.56,53.86,47.77,42.69
"Lima, Peru",59.52,19.90,45.26,51.37,43.29,34.80
"Osijek, Croatia",59.50,13.07,42.79,52.02,39.77,45.81
"Sarajevo, Bosnia And Herzegovina",58.59,13.01,42.19,43.89,44.13,35.81
"Cordoba, Argentina",57.81,19.29,43.94,52.43,51.76,42.17
"Tula, Russia",57.72,15.46,42.51,48.96,44.94,51.89
"Guadalajara, Mexico",57.67,10.28,40.61,47.54,44.78,69.13
"Tbilisi, Georgia",57.32,15.77,42.37,40.89,52.50,28.71
"Monterrey, Mexico",56.60,23.53,44.70,49.88,53.05,65.26
"Belgrade, Serbia",56.21,17.13,42.15,39.73,45.39,30.66
"Sofia, Bulgaria",55.62,16.24,41.44,45.83,37.78,36.55
"Kuala Lumpur, Malaysia",55.55,17.71,41.93,55.09,32.09,77.70
"Damascus, Syria",55.50,14.22,40.65,41.91,41.08,20.52
"Johor Baharu, Malaysia",55.32,7.56,38.13,47.53,33.04,38.85
"Wroclaw, Poland",54.85,19.34,42.07,42.05,42.99,58.27
"Guayaquil, Ecuador",54.76,10.14,38.70,44.89,40.14,25.86
"Beijing, China",54.38,28.71,45.14,61.66,37.49,36.42
"Shanghai, China",54.20,29.86,45.44,51.64,42.60,47.04
"Ulaanbaatar, Mongolia",53.86,24.01,43.12,57.94,37.81,22.57
"Quito, Ecuador",53.69,11.66,38.56,47.42,39.26,23.85
"Warsaw, Poland",53.64,22.81,42.55,42.07,45.74,64.83
"Cairo, Egypt",53.40,17.34,40.42,45.39,48.99,20.64
"Poznan, Poland",53.20,13.93,39.07,42.48,41.12,58.48
"Novi Sad, Serbia",52.70,10.53,37.52,36.62,50.99,35.95
"Iasi, Romania",52.66,13.28,38.48,43.50,34.27,31.37
"Bangkok, Thailand",52.61,26.42,43.18,63.49,29.65,29.50
"Guangzhou, China",52.44,17.25,39.77,70.42,30.76,25.60
"Varna, Bulgaria",52.13,11.51,37.51,45.17,38.79,34.13
"Katowice, Poland",51.87,19.49,40.21,43.11,41.41,57.95
"Gdansk, Poland",51.64,20.34,40.37,40.86,43.63,64.99
"Cluj-napoca, Romania",51.35,10.94,36.81,45.02,36.15,38.79
"Bucharest, Romania",50.97,15.28,38.12,39.77,41.79,36.15
"Banja Luka, Bosnia And Herzegovina",50.12,11.38,36.18,40.89,45.75,43.60
"Brasov, Romania",50.05,9.04,35.29,39.77,35.41,33.48
"Constanta, Romania",49.97,14.32,37.14,36.51,36.55,37.55
"Timisoara, Romania",49.90,10.66,35.78,44.77,32.78,38.57
"Plovdiv, Bulgaria",49.05,10.38,35.13,39.39,32.68,31.18
"Quezon City, Philippines",48.83,13.86,36.24,50.04,28.11,28.25
"Krakow, Poland",48.63,19.48,38.14,38.02,34.91,61.36
"Szczecin, Poland",48.59,12.85,35.73,38.88,41.24,53.60
"Hanoi, Vietnam",47.83,40.93,45.34,50.12,31.48,20.82
"Chisinau, Moldova",47.81,12.35,35.05,38.59,40.27,27.56
"Cebu, Philippines",47.61,8.16,33.41,47.26,21.60,35.28
"Minsk, Belarus",47.40,15.41,35.89,35.32,53.72,22.16
"Manila, Philippines",47.34,13.47,35.15,48.24,23.02,27.02
"Makati, Philippines",47.17,28.45,40.43,40.15,34.74,20.06
"Managua, Nicaragua",46.57,11.08,33.80,45.10,31.34,41.13
"Skopje, Macedonia",46.51,11.74,33.99,35.19,35.78,34.39
"Esfahan, Iran",45.56,19.60,36.22,47.53,34.47,49.90
"Nis, Serbia",44.85,11.02,32.68,31.88,37.15,28.62
"Lublin, Poland",42.40,13.98,32.17,34.50,32.67,60.48
"Gurgaon, India",41.64,12.26,31.07,36.11,26.13,63.86
"Ho Chi Minh City, Vietnam",41.09,29.65,36.97,48.66,24.37,45.15
"Algiers, Algeria",40.60,13.23,30.75,42.50,31.32,23.70
"Lahore, Pakistan",40.09,7.75,28.45,37.26,31.69,23.46
"Delhi, India",37.93,12.08,28.63,35.23,26.57,62.71
"Davao, Philippines",37.59,11.36,28.15,39.78,21.57,44.20
"Mumbai, India",36.62,21.51,31.18,35.97,26.86,57.91
"Bangalore, India",34.92,9.80,25.87,35.32,19.80,65.65
"Indore, India",34.85,5.75,24.38,32.90,16.09,89.92
"Chandigarh, India",33.95,6.98,24.24,31.63,21.68,52.41
"Ahmedabad, India",33.12,6.47,23.53,29.26,24.03,50.67
"Hyderabad, India",32.67,7.26,23.52,32.57,20.06,72.32
"Madurai, India",32.05,5.65,22.55,29.99,13.11,25.02
"Kolkata, India",31.97,8.81,23.63,35.06,21.02,49.26
"Pune, India",31.90,9.34,23.78,32.74,20.62,55.50
"Chennai, India",31.09,9.19,23.21,32.57,17.17,59.10
"Kochi, India",31.07,5.28,21.79,34.43,16.52,44.85
"Thiruvananthapuram, India",30.30,5.09,21.23,35.64,17.20,56.05
"Ludhiana, India",30.20,7.89,22.17,31.27,21.88,55.74

1.2 cross domain concept

When Ajax accesses local files, cross domain problems occur.

1.2.1 how do cross domain problems arise?

Homology policy: the browser itself has homology policy. Protocol, domain name and port are the same, which are regarded as the same domain. A script in a domain only has permissions in its own domain. It can be understood that a script in its own domain can only read and write resources in its own domain, but cannot access resources in other domains. This security restriction is known as the same origin policy.

The same origin strategy ensures the isolation of resources. The script of a website can only access its own resources, just like the process in the operating system cannot access the resources of another process. If there is no homology policy, you can browse in the website, jump to other pages, and then this page can read the information in your website across domains, so there is no privacy in the whole Web world. This is the importance of homology, which limits these behaviors. Of course, in the same domain, client script can read and write resources in the same source at will, provided that the resource itself is readable and writable.

Generally speaking, the browser has a very important security mechanism, which is the same origin policy: the client script without domain cannot read the other resource without explicit authorization, and cross domain is also different source.

Cross domain: as long as there is a difference between protocol, domain name and port, it is cross domain. ajax requests a web resource whose target address is not local domain (protocol, domain name and port are any different), it is cross domain.

1.2.2 why is there a cross domain problem in Google browser, but not in Firefox?

Since cross domain failure, we need to find the reason. This is very simple, cross domain three elements, protocol, domain name, port. There must be a difference that leads to cross domain problems. Read the local JSON code. Firefox can normally read the local JSON file,

The reason is: although it is not safe to allow cross domain, it will bring a lot of inconvenience if not. So Firefox is allowed to cross domains.

So what's the matter with Google? Why can't Google get it? There will be cross domain problems?
It should be mentioned here that the file protocol is used to access files in the local computer. The file protocol is mainly used to access files in the local computer, just like opening files in Windows Explorer. Note that it is for the local (local) computer. In short, the file protocol is used to access the file resources of your local computer. So, the reason for Google's error is very clear. The console can clearly see it
Cross origin requests are only supported for protocol schemes: http, data, chrome, chrome-extension, https.

For security reasons, the browser does not allow cross domain access. The security mechanism considers that loading other local files is a cross domain behavior. Google's browser will fail across domains because the browser security mechanism does not allow it, while Firefox allows cross domains for convenience (although this is very insecure). And in other browsers, cross domain problem is also the reason, which is the reason of browser security mechanism.

1.2.3 solutions to cross domain problems

1. The front-end staff usually use JSONP for cross domain.
2. nginx reverse proxy is used in the project.
3. Modify the configuration of Google browser.
4. Open in webstrom.

2. Install HTTP server

This paper solves the cross domain problem through http server.
Here, if you haven't installed node, please install it by Baidu.

2.1 global installation of HTTP server

Here, use the - g option to install globally, so that you can also use the HTTP server command in cmd command line mode.

npm install http-server -g

2.2 start and configure HTTP server

Specify the port of the http server as 80, and do not use the cache. After the code is updated, the page will be updated synchronously.

http-server -p 80 -c-1

Finally, when using d3.js to load the csv file, please add: http://localhost/

3.svg visualization

svg can be converted to canvas, and then right click the canvas to have the option of "save picture", Original entry.

Converting svg to canvas requires a google plug-in, canvg.

<script  src="https://is.muni.cz/do/rect/el/storage/utils/svgedit/canvg/canvg.js?lang=en"></script> 

<!DOCTYPE html>
<html>
<head>
<script src="https://apps.bdimg.com/libs/jquery/2.1.4/jquery.min.js"></script>
<script  src="https://is.muni.cz/do/rect/el/storage/utils/svgedit/canvg/canvg.js?lang=en"></script> 
<script  src="test.js" type="text/javascript"></script>
</head>
<body>
<textarea id="container" style="min-width:300px;height:100px"></textarea>
<input type="button" value="Turn picture" onClick="convert()" />
<canvas id="canvasId" ></canvas>
<image id="image"/>
<script type="text/javascript">
function convert(){
    var svgHtml=$("#container").val();
    var canvasId=document.getElementById("canvasId");
    canvg(canvasId,svgHtml);
 }
</script>

Posted by henrygao on Wed, 10 Jun 2020 22:25:46 -0700