globe-contour.html 6.0 KB
<!doctype html>
<html>
    <head>
        <meta charset="utf-8">
        <title>Globe - ECHARTS-GL</title>
        <meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no">
        <meta name="apple-mobile-web-app-capable" content="yes"> <!-- Fullscreen Landscape on iOS -->
        <link rel="stylesheet" href="./common.css">
    </head>
    <body>
        <div id="main"></div>
        <script src="https://unpkg.com/d3-contour@1"></script>
        <script src="https://unpkg.com/d3-geo@1"></script>
        <script src="https://unpkg.com/d3-timer@1"></script>
        <script src="../node_modules/echarts/dist/echarts.js"></script>
        <script src="https://cdn.jsdelivr.net/npm/echarts@4.9.0/map/js/world.js"></script>
        <script src="../dist/echarts-gl.js"></script>
        <script src="lib/jquery.min.js"></script>
        <script src="lib/stackBlur.js"></script>
        <script src="lib/dat.gui.js"></script>
        <script src="js/commonUI.js"></script>
        <script>

var config = {
    color: '#c0101a',
    levels: 1,
    intensity: 8,
    threshold: 0.01
}

var canvas = document.createElement('canvas');
canvas.width = 4096;
canvas.height = 2048;
context = canvas.getContext("2d");

context.lineWidth = 0.5;
context.strokeStyle = config.color;
context.fillStyle = config.color;
context.shadowColor = config.color;

var gui = new dat.GUI();

image("asset/bathymetry_bw_composite_4k.jpg").then(function(image) {
  var m = image.height,
      n = image.width,
      values = new Array(n * m),
      contours = d3.contours().size([n, m]).smooth(true),
      projection = d3.geoIdentity().scale(canvas.width / n),
      path = d3.geoPath(projection, context);

  StackBlur.R(image, 5);

  for (var j = 0, k = 0; j < m; ++j) {
    for (var i = 0; i < n; ++i, ++k) {
      values[k] = image.data[(k << 2)] / 255;
    }
  }

  var option = {
    image: canvas
  }

  var results = [];
  function update(threshold, levels) {
    context.clearRect(0, 0, canvas.width, canvas.height);
    var thresholds = [];
    for (var i = 0; i < levels; i++) {
        thresholds.push((threshold + 1 / levels * i) % 1);
    }
    results = contours.thresholds(thresholds)(values);
    redraw();
  }

  function redraw() {
    results.forEach(function (d, idx) {
        context.beginPath();
        path(d);
        context.globalAlpha = 1;
        context.stroke();
        if (idx > config.levels / 5 * 3) {
            context.globalAlpha = 0.01;
            context.fill();
        }
    });
    option.onupdate();
  }
  d3.timer(function(t) {
    var threshold = (t % 10000) / 10000;
    update(threshold, 1);
  });

  initCharts(option);

  update(config.threshold, config.levels);

//   gui.add(config, 'levels', 0, 100).step(1).onFinishChange(function () {
//     update(config.threshold, config.levels);
//   });

//   gui.add(config, 'threshold', 0, 1.00).onFinishChange(function () {
//     update(config.threshold, config.levels);
//   });

    gui.addColor(config, 'color').onChange(function () {
        context.strokeStyle = context.fillStyle = context.shadowColor = config.color;
        redraw();
    });
});

function image(url) {
  return new Promise(function(resolve) {
    var image = new Image;
    image.src = url;
    image.onload = function() {
      var canvas = document.createElement("canvas");
      canvas.width = image.width / 4;
      canvas.height = image.height / 4;
      var context = canvas.getContext("2d");
      context.drawImage(image, 0, 0, canvas.width, canvas.height);
      resolve(context.getImageData(0, 0, canvas.width, canvas.height));
    };
  });
}

var chart;
function initCharts(option) {
    chart = echarts.init(document.getElementById('main'));

    var contourChart = echarts.init(document.createElement('canvas'), null, {
        width: 4096,
        height: 2048
    });

    var img = new echarts.graphic.Image({
        style: {
            image: option.image,
            x: -1,
            y: -1,
            width: option.image.width + 2,
            height: option.image.height + 2
        }
    });
    contourChart.getZr().add(img);

    option.onupdate = function () {
        img.dirty();
    }

    // https://www.behance.net/gallery/50293671/T-GLOBEhttps://bl.ocks.org/mbostock/818053c76d79d4841790c332656bf9da

    chart.setOption({
        globe: {

            // environment: 'asset/starfield.jpg',

            heightTexture: 'asset/bathymetry_bw_composite_4k.jpg',

            displacementScale: 0.05,
            displacementQuality: 'high',

            baseColor: '#111',

            shading: 'realistic',
            realisticMaterial: {
                roughness: 0.2,
                metalness: 0
            },

            postEffect: {
                enable: false,
                depthOfField: {
                    enable: true
                },
                bloom: {
                    intensity: 0.05
                }
            },
            temporalSuperSampling: {
                enable: true
            },
            light: {
                ambient: {
                    intensity: 0
                },
                main: {
                    intensity: 0.1,
                    shadow: false
                },
                ambientCubemap: {
                    texture: 'asset/lake.hdr',
                    exposure: 1,
                    diffuseIntensity: 0.5,
                    specularIntensity: 2
                }
            },
            viewControl: {
                autoRotate: false
            },

            layers: [{
                type: 'blend',
                blendTo: 'emission',
                texture: contourChart,
                intensity: config.intensity
            }]
        }
    });

    window.addEventListener('resize', function () {
        chart.resize();
    });

    gui.add(config, 'intensity', 0, 10).onChange(function () {
        chart.setOption({
            globe: {
                layers: [{
                    intensity: config.intensity
                }]
            }
        })
    });
}
        </script>
    </body>
</html>