无法从画布上制作一块 [英] Unable to make a chunk from canvas

查看:79
本文介绍了无法从画布上制作一块的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我希望与地图进行这种交互,以便当用户选择地图上的某个区域时,就会从该区域创建图像.在此小提琴中,我做了一个最小化和可复制的示例.最重要的部分是此裁剪功能:

I want to have such an interaction with a map, that when a user selects some area on the map, an image is created from this area. I made a minimized and compiltely reproducible example in this fiddle. The most important part is this crop function:

function crop(img, sx, sy, dw, dh) {
   var canvas = document.createElement('canvas');
   var ctx = canvas.getContext('2d');
   canvas.width = dw;
   canvas.height = dh;
   ctx.drawImage(img, sx, sy, dw, dh, 0, 0, dw, dh);
   return canvas.toDataURL("image/png");
}

此功能在所选区域之外创建一个块.这就是选择的样子:

This function creates a chunk out of selected area. This is how selection looks like:

但这就是我得到的结果:

But this is what I get as a result:

所以,我的块完全不正确.但是更有趣的是,在某些任意计算机上和某些任意浏览器中,块是正确的.因此,我确实需要使该代码跨平台和跨浏览器.

So, my chunk is totally incorrect. But what is more interesting is that on some arbitrary computers and in some arbitrary browsers chunks are correct. So, I really need to make this code cross-platform and cross-browser.

推荐答案

但是问题是,从JavaScript代码看来,不可能知道这个系统/浏览器参数-我的意思是初始页面缩放级别.

But the problem is, it seems like from JavaScript code it is impossible to know this system/browser parameter - I mean initial page zoom level.

实际上有 window.devicePixelRatio
只需使用它代替ratio_Wratio_H,它就会开始工作:

Actually there is window.devicePixelRatio
Just use it in place of ratio_W and ratio_H, and it starts working:

var initialZoom = devicePixelRatio;

var map = new ol.Map({
  layers: [new ol.layer.Tile({
    source: new ol.source.OSM()
  })],
  target: 'map',
  view: new ol.View({
    center: [-348792.96, 7170957.18],
    zoom: 10
  })
});

var draw = new ol.interaction.Draw({
   features: new ol.Collection(),
   type: "LineString",
   style: function (feature) {
       var style = [
         new ol.style.Style({
           fill: new ol.style.Fill({
             color: 'rgba(142,142,142,0.5)'
           }),
           stroke: new ol.style.Stroke({
             color: 'rgba(142,142,142,1)',
             lineDash: [4,4],
             width: 2
           })
         })
       ];
       return style;
   },
   geometryFunction: function (coordinates, geom) {
       if (!geom) {
           geom = new ol.geom.Polygon(null);
       }
       var start = coordinates[0];
       var end = coordinates[1];
       var mapExtent = map.getView().calculateExtent(map.getSize());

       var chunk = [start, [start[0], end[1]], end, [end[0], start[1]],start];
       var coords = [[[mapExtent[0],mapExtent[1]],[mapExtent[0],mapExtent[3]],[mapExtent[2],mapExtent[3]],[mapExtent[2],mapExtent[1]],[mapExtent[0],mapExtent[1]]], chunk];
       map.exportExtent = coordinates; // all you need
       geom.setCoordinates(coords);
       return geom;
   },
   maxPoints: 2
});

var canvas = map.getViewport().firstChild;

draw.on("drawend", function (e) {
    var image = new Image(), 
        link = document.getElementById("export-png");
   
    var topLeft = map.getPixelFromCoordinate(map.exportExtent[0]);
    var bottomRight = map.getPixelFromCoordinate(map.exportExtent[1]);
    
    var sx = topLeft[0];
    var sy = topLeft[1];
    var dw = bottomRight[0] - topLeft[0];
    var dh = bottomRight[1] - topLeft[1];
    
    image.id = "pic";
    image.crossOrigin = "anonymous";
    image.onload = function () { 
        sx = sx * initialZoom;
        sy = sy * initialZoom;
        dw = dw * initialZoom;
        dh = dh * initialZoom;
        link.href = crop(image, sx, sy, dw, dh);
        link.click();
    };
    
    image.src = canvas.toDataURL("image/png");
});

map.addInteraction(draw);

function crop(img, sx, sy, dw, dh) {
   var canvas = document.createElement('canvas');
   var ctx = canvas.getContext('2d');
   canvas.width = dw;
   canvas.height = dh;
   ctx.drawImage(img, sx, sy, dw, dh, 0, 0, dw, dh);
   return canvas.toDataURL("image/png");
}

<link href="https://openlayers.org/en/v4.6.4/css/ol.css" rel="stylesheet"/>
<script src="https://openlayers.org/en/v4.6.4/build/ol-debug.js"></script>
<div id="map" class="map"></div> 
<a id="export-png" class="btn" download="map.png">&nbsp;</a>

摘录来自@dube的答案,我只修改了image.onload 并将initialZoom存储在第一行.

Snippet comes from @dube's answer, and I modified image.onload only and stored initialZoom in the first line.

这篇关于无法从画布上制作一块的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆