跳到主要内容

自定义点视图

示例

结果
Loading...
实时编辑器
function render(props) {
  const container = useRef(null);

  const dataUrl = useBaseUrl('/json/bin.json');

  const initChat = (map, option) => {
    const chart = new EChartsLayer(option, {
      stopEvent: false,
      hideOnMoving: false,
      hideOnZooming: false,
      forcedPrecomposeRerender: true,
    });

    chart.appendTo(map);
  };

  var COLORS = ['#070093', '#1c3fbf', '#1482e5', '#70b4eb', '#b4e0f3', '#ffffff'];
  var lngExtent = [39.5, 40.6];
  var latExtent = [115.9, 116.8];
  var cellCount = [50, 50];
  var cellSizeCoord = [(lngExtent[1] - lngExtent[0]) / cellCount[0], (latExtent[1] - latExtent[0]) / cellCount[1]];

  var gapSize = 0;

  const renderItem = (params, api) => {
    var context = params.context;
    var lngIndex = api.value(0);
    var latIndex = api.value(1);
    var coordLeftTop = [
      +(latExtent[0] + lngIndex * cellSizeCoord[0]).toFixed(6),
      +(lngExtent[0] + latIndex * cellSizeCoord[1]).toFixed(6),
    ];
    var pointLeftTop = getCoord(params, api, lngIndex, latIndex);
    var pointRightBottom = getCoord(params, api, lngIndex + 1, latIndex + 1);

    return {
      type: 'rect',
      shape: {
        x: pointLeftTop[0],
        y: pointLeftTop[1],
        width: pointRightBottom[0] - pointLeftTop[0],
        height: pointRightBottom[1] - pointLeftTop[1],
      },
      style: api.style({
        stroke: 'rgba(0,0,0,0.1)',
      }),
      styleEmphasis: api.styleEmphasis(),
    };
  };

  const getCoord = (params, api, lngIndex, latIndex) => {
    var coords = params.context.coords || (params.context.coords = []);
    var key = lngIndex + '-' + latIndex;

    // bmap returns point in integer, which makes cell width unstable.
    // So we have to use right bottom point.
    return (
      coords[key] ||
      (coords[key] = api.coord([
        +(latExtent[0] + lngIndex * cellSizeCoord[0]).toFixed(6),
        +(lngExtent[0] + latIndex * cellSizeCoord[1]).toFixed(6),
      ]))
    );
  };

  const init = async () => {
    const map = new ol.Map({
      target: container.current,
      view: new ol.View({
        projection: 'EPSG:4326',
        rotation: 0,
        center: [116.28245, 39.92121],
        zoom: 9, // resolution
      }),
      layers: [
        new TileLayer({
          source: new XYZ({
            url: 'https://{a-c}.basemaps.cartocdn.com/dark_all/{z}/{x}/{y}.png',
          }),
        }),
      ],
    });

    const data = await fetch(dataUrl).then((res) => res.json());

    const option = {
      tooltip: {
        formatter: function (params, ticket, callback) {
          return params.value;
        },
        trigger: 'item',
      },
      visualMap: {
        type: 'piecewise',
        inverse: true,
        top: 10,
        right: 10,
        pieces: [
          {
            value: 0,
            color: COLORS[0],
          },
          {
            value: 1,
            color: COLORS[1],
          },
          {
            value: 2,
            color: COLORS[2],
          },
          {
            value: 3,
            color: COLORS[3],
          },
          {
            value: 4,
            color: COLORS[4],
          },
          {
            value: 5,
            color: COLORS[5],
          },
        ],
        borderColor: '#ccc',
        borderWidth: 2,
        backgroundColor: '#eee',
        dimension: 2,
        inRange: {
          color: COLORS,
          opacity: 0.7,
        },
      },
      series: [
        {
          type: 'custom',
          renderItem: renderItem,
          animation: false,
          itemStyle: {
            emphasis: {
              color: 'yellow',
            },
          },
          encode: {
            tooltip: 2,
          },
          data: data,
        },
      ],
    };

    initChat(map, option);

    function resize(target) {}

    return {
      resize,
    };
  };

  useEffect(() => {
    const { resize } = init();

    return () => {};
  }, []);

  return (
    <div className="live-wrap">
      <div ref={container} className="map-content" />
    </div>
  );
}