d3js地图在移动Chrome中显示不正确

格雷格·海狸

我是d3js的新手,并尝试使用地图创建我的四重奏音乐会时间表的可视化。我的第一次尝试在桌面chrome浏览器和safari桌面浏览器中效果很好。

在我使用移动Chrome的android设备上,地图错误地渲染了除美国以外的整个地球。

http://test.chiaraquartet.net/topo/index.html

任何对我做错事的了解/如果d3中存在错误,将不胜感激。

这是有问题的代码:

  var center = [90, -38.7],
     ratio = window.devicePixelRatio || 1,
     graticule = d3.geo.graticule(),
     width = 500,
     height = 500,
     degrees = 180 / Math.PI,
     projection = d3.geo.orthographic()
     .scale(height / 2 - 1)
     .rotate(center)
     .translate([width / 2, height / 2])
     .clipAngle(90)
     .precision(.1)

 var graticule = d3.geo.graticule()()

 // Round to integer pixels for speed, and set pixel ratio.
 function roundRatioContext(context) {
   return {
     moveTo: function(x, y) { context.moveTo(Math.round(x * ratio), Math.round(y * ratio)); },
     lineTo: function(x, y) { context.lineTo(Math.round(x * ratio), Math.round(y * ratio)); },
     closePath: function() { context.closePath(); }
   };
 }

 var canvas = d3.select("body").append("canvas")
     .attr("width", width * ratio)
     .attr("height", height * ratio)
     .style("width", width + "px")
     .style("height", height + "px")

 var c = canvas.node().getContext("2d");

 var path = d3.geo.path()
     .projection(projection)
     .context(roundRatioContext(c));

 var svg = d3.select("body").append("svg")
     .attr("width", width)
     .attr("height", height)
     .append('g')

 var textbox = d3.select("body").append("div")
     .style('position', 'absolute')
     .attr('class', 'popup')
     .classed('hidden', true)

 var sphere = svg.append("path")
     .datum({type: "Sphere"})
     .attr("id", "sphere")
     .attr("d", path)

 var runner = queue()
   .defer(d3.json, 'world.json')
   .defer(d3.xhr('/concertrpc.php')
           .header('content-type', 'application/json')
           .post, JSON.stringify({
         params: [],
         id: 1
     }))
   .await(function(error, world, info) {
    if (error) return console.error(error);
    var features = topojson.feature(world, world.objects.states)
    var countries = topojson.feature(world, world.objects.countries)
    console.log(world)
    var concerts = JSON.parse(info.responseText)
    if (concerts.error) {
     console.log(concerts.error)
     return
    }
    concerts = concerts.result.concerts
    console.log(concerts)

   var globe = {type: "Sphere"},
       graticule = d3.geo.graticule()(),
       countries = topojson.feature(world, world.objects.countries),
       states = topojson.feature(world, world.objects.states),
       country_borders = topojson.mesh(world, world.objects.countries, function(a, b) { return a !== b }),
       state_borders = topojson.mesh(world, world.objects.states, function(a, b) { return a.id !== b.id }),
       temp_context

   temp_context = path.context()
   path.context(null)
   svg.selectAll('.concert')
       .data(concerts, function(d) { return d.properties.id })
   .enter().append("path")
       .attr('class', 'concert')
       .attr('d', path)
       .on('mouseover', concertMouseover)
       .on('mouseout', function(d) {
           textbox.classed('hidden', true)
       })
   path.context(temp_context)

   d3.select('body').append('div').append('button')
       .attr('type', 'button')
       .text('This season')
       .on('click', function() {
           getConcertData('This season')
       })
   var zoom = d3.geo.zoom()
     .projection(projection)
     .duration(function(S) { return 2000 * Math.sqrt(S); }) // assume ease="quad-in-out"
     .scaleExtent([height / 2 - 1, Infinity])
     .on("zoom", function() {
       projection.clipAngle(Math.asin(Math.min(1, .5 * Math.sqrt(width * width + height * height) / projection.scale())) * degrees);
       c.clearRect(0, 0, width * ratio, height * ratio);
       c.strokeStyle = "#999", c.lineWidth = .25 * ratio, c.beginPath(), path(graticule), c.stroke();
       c.fillStyle = "#69d2e7", c.beginPath(), path(countries), c.fill();
       c.fillStyle = "#00f", c.beginPath(), path(states), c.fill();
       c.strokeStyle = "#fff", c.lineWidth = .5 * ratio, c.beginPath(), path(country_borders), c.stroke();
       c.strokeStyle = "#fff", c.lineWidth = .5 * ratio, c.beginPath(), path(state_borders), c.stroke();
       c.strokeStyle = "#000", c.lineWidth = .5 * ratio, c.beginPath(), path(globe), c.stroke();
       temp_context = path.context()
       path.context(null)
       svg.selectAll("path").attr("d",path);
       path.context(temp_context)
     })
     //.on("zoomend", transition);

   canvas
       .call(zoom)
       .call(zoom.event);
   sphere
       .call(zoom)

   function transition() {
     zoomBounds(projection, states.features[30]);
     canvas.transition()
         .ease("quad-in-out")
         .duration(2000) // see https://github.com/mbostock/d3/pull/2045
         .call(zoom.projection(projection).event);
   }

   function zoomBounds(projection, o) {
     var centroid = d3.geo.centroid(o),
         clip = projection.clipExtent();

     projection
         .rotate([-centroid[0], -centroid[1]])
         .clipExtent(null)
         .scale(1)
         .translate([0, 0]);

     var b = path.bounds(o),
         k = Math.min(1000, .45 / Math.max(Math.max(Math.abs(b[1][0]), Math.abs(b[0][0])) / width, Math.max(Math.abs(b[1][1]), Math.abs(b[0][1])) / height));

     projection
         .clipExtent(clip)
         .scale(k)
         .translate([width / 2, height / 2]);
   }
   })

 function concertMouseover(d) {
     var loc = projection(d3.select(this).datum().geometry.coordinates)
     textbox.style('top', loc[1] + "px")
     textbox.style('left', loc[0] + 15 + "px")
     textbox.text(d.properties.title)
     textbox.classed('hidden', false)
 }

 function getConcertData(request) {
     d3.xhr('/concertrpc.php')
     .header('content-type', 'application/json')
     .post(JSON.stringify({
         params: [request],
         id: 1
     }), function(error, info) {
         var concerts = JSON.parse(info.responseText)
         if (concerts.error) {
             console.log(concerts.error)
             return
         }
         var c = svg.selectAll('.concert')
             .data(concerts.result.concerts, function(d) { return d.properties.id })
         c.transition()
             .style('opacity', '1')

         c.enter()
             .append('path')
             .attr('class', 'concert')
             .attr('d', path)
             .on('mouseover', concertMouseover)
             .on('mouseout', function(d) {
                 textbox.classed('hidden', true)
             })
         c.exit().transition()
             .duration(1000)
             .style('opacity', '0')
             .remove()
     })
 }
格雷格·海狸

我不确定是什么引起了问题,但罪魁祸首是我尝试将世界各国的地图与美国各州的地图组合在一起时生成的topojson文件。我发现可以使用另一幅世界地图,现在该地图在手机和台式机上的显示方式相同。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章