javascript html2canvas和使用OpenLayers7复制Map的问题

ryoqjall  于 2023-06-04  发布在  Java
关注(0)|答案(1)|浏览(263)

我正在尝试使用open layers 7创建一个网页,它允许用户加载Map,然后缩放、旋转或更改用作bg的tilelayer。
有一天,他们可以点击一个按钮,应该复制他们的Map到一个html画布。我正在尝试使用html 2canvas进行此过程。
因此,脚本的工作预期的2底图,但对其他人我没有得到任何输出时,试图复制Map到画布。
我相信这是一个问题与污染的画布,由于在那里的图像被托管也许?任何帮助understandig是怎么回事,我如何可以修复它,所以我可以复制任何Map背景将不胜感激。
HTML-

<button onclick="duplicateMap()">Copy Map</button>

<div

 id="mapBox">
        <div id="map" class="map"></div>
        <div id="rotationContainer">
            0 <input id="rotationSlider" type="range" min="0" max="360" value="0"> 360
            <br>
        </div>
        <input id="zoomSlider" type="range" orient="vertical" min="10" max="18" value="13" />
    </div>
    <div id="mapCopy"></div>
    
    <div id="baseMapSelect">
      <h4 style="margin:0px; text-decoration: underline;">Select your map style</h4>
    </div>

CSS-

button{margin: 10px 0}
#mapBox{
    position: absolute;
    width: 40%;
}

#map {
  width: 300px;
  height: 300px;
    border: 2px solid black;
}
#mapCopy{
    position:absolute;
    top: 50px;
    left: 450px;
    width: 40%;
    float: right;
}

#baseMapSelect {
    position: relative;
  top: 330px;
}

input[type=range][orient="vertical"] {
  writing-mode: bt-lr;
  /* IE */
  -webkit-appearance: slider-vertical;
  /* Chromium */
  width: 8px;
  min-height: 175px;
  padding: 0 5px;
}

#zoomSlider {
  position: absolute;
    top: 0px;
  left: 315px;
  height: 280px;
  margin: 10px;
}

#rotationContainer{
    position: relative;
    left: 5px;
}

JS-

window.onload = init;

// set some variables
var selectedBaseMap = "OSMStandard";
var currentLonLat = [-63.5859487, 44.648618]; //Halifax Lon/Lat
var defaultZoom = 12;
var defaultRotation = 0;
var rotationSlider = document.getElementById("rotationSlider");
var zoomSlider = document.getElementById("zoomSlider");

mapCenter = ol.proj.fromLonLat(currentLonLat); //Converts Lon/Lat to center

function init() {
  // setup the map
  const map = new ol.Map({
    view: new ol.View({
      center: mapCenter,
      zoom: defaultZoom,
      rotation: defaultRotation,
    }),
    target: "map",
  });

  // ROTATION //
  rotationSlider.oninput = function () {
    map.getView().setRotation(degreesToRads(this.value));
  };
  // ZOOM //
  zoomSlider.oninput = function () {
    map.getView().setZoom(this.value);
  };

  map.getView().on("change:rotation", function (event) {
    deg = radsToDegrees(event.target.getRotation());
    console.log(deg);
    if (deg > 360) {
      deg = deg - 360;
    }
    rotationSlider.value = deg;
  });

  /* Base Map Layer */
  const openStreetMapStandard = new ol.layer.Tile({
    source: new ol.source.OSM(),
    visible: true,
    title: "OSMStandard",
  });
  const openStreetMapHumanitarian = new ol.layer.Tile({
    source: new ol.source.OSM({
      url: "https://{a-c}.tile.openstreetmap.fr/hot/{z}/{x}/{y}.png",
    }),
    visible: false,
    title: "OSMHumanitarian",
  });
  const stamenToner = new ol.layer.Tile({
    source: new ol.source.XYZ({
      url: "https://stamen-tiles.a.ssl.fastly.net/toner/{z}/{x}/{y}.png",
      attributions:
        'Map tiles by <a href="http://stamen.com">Stamen Design</a>, \
                        under <a href="http://creativecommons.org/licenses/by/3.0">CC BY 3.0</a>. \
                        Data by <a href="http://openstreetmap.org">OpenStreetMap</a>, under <a href="http://www.openstreetmap.org/copyright">ODbL</a>.',
    }),
    visible: false,
    title: "StamenToner",
  });
  const stamenTerrain = new ol.layer.Tile({
    source: new ol.source.XYZ({
      url: "https://stamen-tiles.a.ssl.fastly.net/terrain/{z}/{x}/{y}.jpg",
      attributions:
        'Map tiles by <a href="http://stamen.com">Stamen Design</a>, \
                        under <a href="http://creativecommons.org/licenses/by/3.0">CC BY 3.0</a>. \
                        Data by <a href="http://openstreetmap.org">OpenStreetMap</a>, under <a href="http://www.openstreetmap.org/copyright">ODbL</a>.',
    }),
    visible: false,
    title: "StamenTerrain",
  });
  const stamenWaterColor = new ol.layer.Tile({
    source: new ol.source.XYZ({
      url: "https://stamen-tiles.a.ssl.fastly.net/watercolor/{z}/{x}/{y}.jpg",
      attributions:
        'Map tiles by <a href="http://stamen.com">Stamen Design</a>, \
                        under <a href="http://creativecommons.org/licenses/by/3.0">CC BY 3.0</a>. \
                        Data by <a href="http://openstreetmap.org">OpenStreetMap</a>, under <a href="http://creativecommons.org/licenses/by-sa/3.0">CC BY SA</a>.',
    }),
    visible: false,
    title: "StamenWatercolor",
  });

  /* End Base Map Layer */

  // Layer Group
  const baseLayerGroup = new ol.layer.Group({
    layers: [
      openStreetMapStandard,
      openStreetMapHumanitarian,
      stamenToner,
      stamenTerrain,
      stamenWaterColor,
    ],
  });

  map.addLayer(baseLayerGroup);

  // load the base maps into radio buttons for user selection
  var baseMapSelect = document.getElementById("baseMapSelect");
  baseLayerGroup.getLayers().forEach(function (element, index, array) {
    var baseLayerTitle = element.get("title");
    var html = "";
    if (baseLayerTitle == selectedBaseMap) {
      html +=
        '<input type="radio" id="baseSelect' +
        (index + 1) +
        '" class="baseLayerRadio" name="baseLayerSelect" value="' +
        baseLayerTitle +
        '" onchange="changeBaseMap(this)" checked>';
    } else {
      html +=
        '<input type="radio" id="baseSelect' +
        (index + 1) +
        '" class="baseLayerRadio" name="baseLayerSelect" value="' +
        baseLayerTitle +
        '" onchange="changeBaseMap(this)">';
    }
    html +=
      '<label for="baseSelect' +
      (index + 1) +
      '">' +
      baseLayerTitle +
      "</label>";
    var div = document.createElement("div");
    div.innerHTML = html;
    baseMapSelect.appendChild(div.firstChild);
  });

  const baseLayerElements = document.querySelectorAll(
    "#baseMapSelect > input[type=radio]"
  );
  for (let baseLayerElement of baseLayerElements) {
    //add a listener for each radio
    baseLayerElement.addEventListener("change", function () {
      let baseLayerElementValue = this.value;
      baseLayerGroup.getLayers().forEach(function (element, index, array) {
        let baseLayerTitle = element.get("title");

        // if baseLayerTitle = baseLayerElementValue then setVisible = true, else setVisible = false
        element.setVisible(baseLayerTitle === baseLayerElementValue);
      });
    });
  }
}

//update the currently selected basemap
function changeBaseMap(x) {
  selectedBaseMap = x.value;
}

function duplicateMap() {
  //create an image of map.
  html2canvas(document.getElementById("map")).then(function (canvas) {
    console.log(canvas);
    document.getElementById('mapCopy').appendChild(canvas);
  });
}

/* rotation function */
function degreesToRads(deg) {
  return (deg * Math.PI) / 180;
}
function radsToDegrees(rads) {
  return (rads * 180) / Math.PI;
}

这是一个JSFiddle,我已经得到了。
先谢谢你了!

moiiocjp

moiiocjp1#

在一些帮助下,我找到了解决方案。
解决方案是将crossOrigin: 'anonymous'添加到XYZ基线层,因为这不是它们的默认设置。
最后的代码现在工作。
Here is a working Fiddle, for those interested.

相关问题