(d3.js强制有向图)无法创建属性' vx',但这只发生在localhost中

时间:2017-11-10 05:04:33

标签: javascript d3.js d3-force-directed

当我突然发生时,我正在整理文件夹结构(将JS移动到.js文件而不是内联,并将其放入自己的文件夹中)。我的力导向图突然出现了这个奇怪的问题。所有节点和链接都移动到屏幕的左上角。它看起来像这样:

enter image description here

Javascript控制台显示Cannot create property 'vx' on string 'dki'

当我尝试将整个代码粘贴到jsfiddle中时,奇怪的是,它正常工作。你可以在这里找到小提琴:https://jsfiddle.net/k6pf1hfw/1/

这是JS代码:



var nodes = [
  {  id: "pusat",  group: 0,  label: "Pusat",  level: 0 },

  {  id: "dki",  group: 1,  label: "Prov. DKI",  level: 1 },
      {  id: "jaksel",  group: 1,  label: "Kota Jakarta Selatan",  level: 2 },
      {  id: "jakpus",  group: 1,  label: "Kota Jakarta Pusat",  level: 2},
  {  id: "jabar",  group: 2,  label: "Prov. Jawa Barat",  level: 1 },
      {  id: "sumedang",  group: 2,  label: "Kab. Sumedang",  level: 2 },
      {  id: "bekasi",  group: 2,  label: "Kota Bekasi",  level: 2 },
      {  id: "bandung",  group: 2,  label: "Kota Bandung",  level: 2 },
  {  id: "jatim",  group: 3,  label: "Prov. Jawa Timur",  level: 1 },
      {  id: "malang",  group: 3,  label: "Kota Malang",  level: 2 },
      {  id: "lamongan",  group: 3,  label: "Kota Lamongan",  level: 2 },
  {  id: "diy",  group: 4,  label: "Prov. DIY",  level: 1 },
      {  id: "sleman",  group: 4,  label: "Kab. Sleman",  level: 2 },
      {  id: "jogja",  group: 4,  label: "Kota Yogyakarta",  level: 2 },
  {  id: "bali",  group: 5,  label: "Prov. Bali",  level: 1 },
      {  id: "bali1",  group: 5,  label: "Kota Denpasar",  level: 2 },
      {  id: "bali2",  group: 5,  label: "Kab. Buleleng",  level: 2 },
  {  id: "ntt",  group: 6,  label: "Prov. NTT",  level: 1 },
      {  id: "ntt1",  group: 6,  label: "Kab. Alor",  level: 2 },
      {  id: "ntt2",  group: 6,  label: "Kab. Manggarai Timur",  level: 2},
  {  id: "ntb",  group: 7,  label: "Prov. NTB",  level: 1 },
      {  id: "kabima",  group: 7,  label: "Kab. Bima",  level: 2 },
      {  id: "kobima",  group: 7,  label: "Kota Bima",  level: 2 },
  {  id: "kaltara",  group: 8,  label: "Prov. Kaltara",  level: 1 },
      {  id: "kubar",  group: 8,  label: "Kab. Kutai Barat",  level: 2 },
      {  id: "kutim",  group: 8,  label: "Kab. Kutai Timur",  level: 2 },
  {  id: "kaltim",  group: 9,  label: "Prov. Kaltim",  level: 1 },
      {  id: "bpp",  group: 9,  label: "Kota Balikpapan",  level: 2 },
      {  id: "samarinda",  group: 9,  label: "Kota Samarinda",  level: 2 },
  {  id: "kalsel",  group: 10,  label: "Prov. Kalsel",  level: 1 },
      {  id: "banjar",  group: 10,  label: "Kota Banjarmasin",  level: 2 },
      {  id: "tapin",  group: 10,  label: "Kab. Tapin",  level: 2 },
  {  id: "kalbar",  group: 11,  label: "Prov. Kalbar",  level: 1 },
      {  id: "melawi",  group: 11,  label: "Kab. Melawi",  level: 2 },
      {  id: "sambas",  group: 11,  label: "Kab. Sambas",  level: 2}
]

var links = [
  // Pusat-Provinsi
  { source:"pusat", target:"dki", strength:.5, value:100000000000  },
  { source:"pusat", target:"jabar", strength:.5, value:30000000000},
  { source:"pusat", target:"jatim", strength:.5, value:100000000000},
  { source:"pusat", target:"diy", strength:.5, value:1000000000000},
  { source:"pusat", target:"bali", strength:.5, value:10000000000},
  { source:"pusat", target:"ntt", strength:.5, value:1000000000},
  { source:"pusat", target:"ntb", strength:.5, value:1000000000},
  { source:"pusat", target:"kaltim", strength:.5, value:5000000000000},
  { source:"pusat", target:"kaltara", strength:.5, value:5000000000000},
  { source:"pusat", target:"kalsel", strength:.5, value:10000000000000},
  { source:"pusat", target:"kalbar", strength:.5, value:1000000000},

  // Provinsi-Kab/Kota
  { source:"dki", target:"jaksel", strength:.7, value:2000000000},
  { source:"dki", target:"jakpus", strength:.7, value:4000000000000},
  { source:"jabar", target:"sumedang", strength:.7, value:400000000000},
  { source:"jabar", target:"bekasi", strength:.7, value:40000000000},
  { source:"jabar", target:"bandung", strength:.7, value:40000000000},
  { source:"jatim", target:"malang", strength:.7, value:300000000000},
  { source:"jatim", target:"lamongan", strength:.7, value:100000000000},
  { source:"diy", target:"sleman", strength:.7, value:4500000000000},
  { source:"diy", target:"jogja", strength:.7, value:6700000000000},
  { source:"bali", target:"bali1", strength:.7, value:100000000000000},
  { source:"bali", target:"bali2", strength:.7, value:2400000000000},
  { source:"ntt", target:"ntt1", strength:.7, value:60000000000000},
  { source:"ntt", target:"ntt2", strength:.7, value:100000000000},
  { source:"ntb", target:"kabima", strength:.7, value:126000000000},
  { source:"ntb", target:"kobima", strength:.7, value:1000000000000},
  { source:"kaltara", target:"kubar", strength:.7, value:12420000000000},
  { source:"kaltara", target:"kutim", strength:.7, value:14400000000000},
  { source:"kaltim", target:"bpp", strength:.7, value:1470000000000},
  { source:"kaltim", target:"samarinda", strength:.7, value:1000000000000000},
  { source:"kalsel", target:"banjar", strength:.7, value:137000000000},
  { source:"kalsel", target:"tapin", strength:.7, value:5050000000000},
  { source:"kalbar", target:"melawi", strength:.7, value:2400000000000},
  { source:"kalbar", target:"sambas", strength:.7, value:5500000000000}
];

function getNeighbors(node) {
  return links.reduce(function(neighbors, link) {
    if (link.target.id === node.id) {
      neighbors.push(link.source.id)
    } else if (link.source.id === node.id) {
      neighbors.push(link.target.id)
    }
    return neighbors
  }, [node.id])
}

function isNeighborLink(node, link) {
  return link.target.id === node.id || link.source.id === node.id
}


function getNodeColor(node, neighbors) {
  // If is neighbor
  if (Array.isArray(neighbors) && neighbors.indexOf(node.id) > -1) {
    return 'rgba(251, 130, 30, 1)'
    // return node.level === 1 ? '#9C4A9C' : 'rgba(251, 130, 30, 1)'
  } else {
    // Check the node level
      if (node.level === 0) {
        return '#E72148'
      } else if (node.level === 1) {
        return '#9C4A9C'
      } else {
        return '#D8ABD8'
      }
  }
  //return node.level === 0 ? '#91007B' : '#D8ABD8'
}

function getLinkColor(node, link) {
  return isNeighborLink(node, link) ? 'rgba(251, 130, 30, 1)' : 'rgba(251, 130, 30, 0.25)'
}

function getTextColor(node, neighbors) {
  return Array.isArray(neighbors) && neighbors.indexOf(node.id) > -1 ? '#333' : '#bbb'
}

var width = window.innerWidth
var height = window.innerHeight

var svg = d3.select('svg')
// svg.attr('width', width).attr('height', height)
    svg.attr("width", '100%')
    .attr("height", '500px')
    .attr('viewBox', '250 0 800 600')
    //.attr('viewBox','0 0 '+Math.min(width,height)+' '+Math.min(width,height))
    .attr('preserveAspectRatio','xMidYMid')
    .append("g")
    .attr("transform", "translate(" + Math.min(width,height) / 2 + "," + Math.min(width,height) / 2 + ")");

//add zoom capabilities
  var zoom_handler = d3.zoom()
      .scaleExtent([1 / 2, 8])
      .on("zoom", zoom_actions);

  zoom_handler(svg);

  function zoom_actions(){
      g.attr("transform", d3.event.transform)
  }

  function button_zoom_in(){
      zoom_handler.scaleBy(svg, 2);
  }
  function button_zoom_out(){
      zoom_handler.scaleBy(svg, 0.5);
  }

// simulation setup with all forces
var linkForce = d3
  .forceLink()
  .id(function (link) { return link.id })
  // Alternative: using the distance from the data "strength"
  //.distance(50).strength(function (link) { return link.strength })
  // If don't want to use this, use default here:
  .distance(50).strength(.7)

var simulation = d3
  .forceSimulation()
  .force('link', linkForce)
  .force('charge', d3.forceManyBody().strength(-1500))
  .force('radial', d3.forceRadial(function(d) {
    return d.level * 50
  }, width / 2, height / 2))
  .force('center', d3.forceCenter(width / 2, height / 2))

var dragDrop = d3.drag().on('start', function(node) {
  node.fx = node.x
  node.fy = node.y
}).on('drag', function(node) {
  simulation.alphaTarget(0.7).restart()
  node.fx = d3.event.x
  node.fy = d3.event.y
}).on('end', function(node) {
  if (!d3.event.active) {
    simulation.alphaTarget(0)
  }
  node.fx = null
  node.fy = null
})

function selectNode(selectedNode) {
  var neighbors = getNeighbors(selectedNode)

  // we modify the styles to highlight selected nodes
  nodeElements.attr('fill', function(node) {
    return getNodeColor(node, neighbors)
  })
  textElements.attr('fill', function(node) {
    return getTextColor(node, neighbors)
  })
  linkElements.attr('stroke', function(link) {
    return getLinkColor(selectedNode, link)
  })
}



// Enables zooming
var g = svg.append("g")
    .attr("class", "everything");
// Enables zooming end

// Create circling orbit
var circles = g.selectAll(null)   // use g.selectAll instead of svg.selectAll to enable zoom
  .data([200,350])  // sets the circle radius
  .enter()
  .append("circle")
  .attr("cx", width/2)
  .attr("cy", height/2)
  .attr("r", d=>d)
  .style("fill", "none")
  .style("stroke", "#ddd");

var linkElements = g.append("g")    // use g.append instead of svg.append to enable zoom
  .attr("class", "links")
  .selectAll("line")
  .data(links)
  .enter().append("line")
  .attr("id",function(d,i) { return "linkId_" + i; })
  .attr("stroke-width", function(link) {
    var linkWidthNormalize = link.value / 1000000000;       // in milyar
                                                            // under assumption that smallest 10 milyar, largest > 40 triliun
    if (linkWidthNormalize >= 40001) {
      return 12;
    } else if (linkWidthNormalize >= 20001 && linkWidthNormalize <= 40000) {
      return 10;
    } else if (linkWidthNormalize >= 9001 && linkWidthNormalize <= 20000) {
      return 8;
    } else if (linkWidthNormalize >= 4001 && linkWidthNormalize <= 9000) {
      return 6;
    } else if (linkWidthNormalize >= 10 && linkWidthNormalize <= 4000) {
      return 4;
    } else {
      return 2;
    }
    // return linkWidthNormalize;
  })
  .attr("stroke", "rgba(251, 130, 30, 0.5)")

var nodeElements = g.append("g")    // use g.append instead of svg.append to enable zoom
  .attr("class", "nodes")
  .selectAll("circle")
  .data(nodes)
  .enter().append("circle")
  .attr("r", 12)
  .attr("fill", getNodeColor)
  .attr("stroke", "#fff")
  .attr('stroke-width', 2)
  .call(dragDrop)
  //.on('click', selectNode)      // alternative
  .on('mouseover', selectNode)

var textElements = g.append("g")    // use g.append instead of svg.append to enable zoom
  .attr("class", "texts")
  .selectAll("text")
  .data(nodes)
  .enter().append("text")
  .text(function(node) {
    return node.label
  })
  .attr("font-size", 10)
  .attr("font-family", "sans-serif")
  .attr("text-anchor", "middle")
  .attr("fill", "#333")
  .attr("style", "font-weight:bold; -webkit-text-stroke: 1px #fff; text-shadow: 3px 3px 0 #fff, -1px -1px 0 #fff, 1px -1px 0 #fff, -1px 1px 0 #fff, 1px 1px 0 #fff")
  .attr("dx", 0)
  .attr("dy", 20)



simulation.nodes(nodes).on('tick', () => {
  nodeElements
    .attr('cx', function(node) {
      return node.x
    })
    .attr('cy', function(node) {
      return node.y
    })
  textElements
    .attr('x', function(node) {
      return node.x
    })
    .attr('y', function(node) {
      return node.y
    })
  linkElements
    .attr('x1', function(link) {
      return link.source.x
    })
    .attr('y1', function(link) {
      return link.source.y
    })
    .attr('x2', function(link) {
      return link.target.x
    })
    .attr('y2', function(link) {
      return link.target.y
    })
})

simulation.force("link").links(links)
&#13;
&#13;
&#13;

我无法找到代码的任何问题。我已经尝试恢复我的动作(将文件移回其初始位置)但没有任何变化。它还是那样的。

这有什么问题?这让我发疯了。

1 个答案:

答案 0 :(得分:0)

我终于找到了罪魁祸首。

希望这会像对我一样粗心对任何人发出警告: d3.js cannot read iso-8859-1编码。我的HTML文件使用iso-8859-1编码,同时JSFiddle正在使用utf-8。这就是为什么它在JSFiddle中起作用但不在我的最后。

所以改变这个:

<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">

到此:

<meta http-equiv="Content-Type" content="text/html; charset=utf-8">

修复了问题。