FabricJS:大的网格对象模糊

时间:2018-07-28 02:51:07

标签: fabricjs

我想用fabricjs绘制一个大网格,但是太模糊了。我使用fabricJS canvas.toSVG()导出到svg文件,然后在浏览器中打开svg文件,它的视图很好。所以我认为这很可能是边缘漏洞。

测试代码为:

var data = [];
    var temp = [0,0,-0.012,-0.012,-0.012,-0.012,-0.012,-0.012,0,0,-0.012,-0.012,0,0.049,0.073,0.049,0.049,0.037,-0.012,-0.012,-0.024,-0.049,-0.024,-0.049,-0.061,-0.012,-0.061,-0.086,0.061,0.146,0.354,0.403,-0.647,-1.88,-1.672,-0.757,-0.33,-0.098,0.024,0.012,0.073,0.122,0.098,0.146,0.183,0.171,0.207,0.232];
    for (var i = 0; i < 200; i++) {
        data = data.concat(temp);
    }
    
    // case 1 : blurry
    var canvas1 = new fabric.Canvas("ecg1");
    var width   = 8000;
    var height  = 400;
    canvas1.setWidth(width);
    canvas1.setHeight(height);
    var bg1  = getBackgroundPath(width, height);
    var ecg1 = getEcgPath(data);
    canvas1.add(bg1);
    canvas1.add(ecg1);
    canvas1.renderAll(); // blurry
    
    // case 2 : ok
    var canvas2 = new fabric.Canvas("ecg2");
    var data2 = data.slice(0, 3000);
    width   = 1000;
    height  = 400;
    canvas2.setWidth(width);
    canvas2.setHeight(height);
    var bg2  = getBackgroundPath(width, height);
    var ecg2 = getEcgPath(data2);
    canvas2.add(bg2);
    canvas2.add(ecg2);
    canvas2.renderAll();
    
    // case 3 : blurry
    var canvas3 = new fabric.Canvas("ecg3");
    canvas3.setWidth(width);
    canvas3.setHeight(height);
    canvas3.add(new fabric.Group([bg2, ecg2]));
    canvas3.renderAll();
    
    function getBackgroundPath(width, height) {
        var grid = [];
        for (var y = 0; y <= height; y += 10) {
            grid.push("M");
            grid.push("0");
            grid.push(y);
            grid.push("H");
            grid.push(width);
        }
        for (var x = 0; x <= width; x += 10) {
            grid.push("M");
            grid.push(x);
            grid.push("0");
            grid.push("V");
            grid.push(height);
        }
        return new fabric.Path(grid.join(" "), {
            top  : 0,
            left : 0,
            stroke: 'pink',
            strokeWidth: 1
        });
    }
    function getEcgPath(data) {
        var xm = 2;
        var ym = 100;
        var max  = Math.max.apply(Math, data);
        var path = [];
        for (var i = 0; i < data.length; i++) {
            path.push("L");
            path.push(i * xm);
            path.push((max - data[i]) * ym);
        }
        path[0] = "M";
        return new fabric.Path(path.join(" "), {
            top  : 0,
            left : 0,
            fill : '',
            stroke: 'black',
            strokeWidth: 1
        });
    }
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
</head>
<body>
  <canvas id="ecg1"></canvas>
  <canvas id="ecg2"></canvas>
  <canvas id="ecg3"></canvas>
  
  <script type="text/javascript" src="http://cdnjs.cloudflare.com/ajax/libs/fabric.js/2.3.3/fabric.min.js" ></script>
</body>
</html>

结果是 enter image description here enter image description here

2 个答案:

答案 0 :(得分:0)

请在此处进一步阅读: http://fabricjs.com/fabric-object-caching

这个问题实际上很容易解决,可以禁用ECG行的缓存。 如果您的应用程序只需要绘制一条大路径或其中的一条,则无需进行缓存。

缓存如何工作? 缓存在单独的画布上绘制对象,然后在移动它的每一帧时重复使用该画布。 与必须对许多对象的每一帧执行多次填充和描边操作相比,这种方法具有更高的性能,尤其是当对象很复杂时。

为避免性能下降,默认情况下,用于缓存的画布限制为2兆像素(您可以通过更改fabric.perfLimitSizeTotal将其向上推),无论兆像素大小如何,默认情况下最大大小限制为4096(如果您不需要支持ie11,可以通过更改fabric.maxCacheSideLimit使其更大。

在您的情况下,路径可以由CPU顺利处理。

对于网格,我们需要更多代码。

var data = [];
    var temp = [0,0,-0.012,-0.012,-0.012,-0.012,-0.012,-0.012,0,0,-0.012,-0.012,0,0.049,0.073,0.049,0.049,0.037,-0.012,-0.012,-0.024,-0.049,-0.024,-0.049,-0.061,-0.012,-0.061,-0.086,0.061,0.146,0.354,0.403,-0.647,-1.88,-1.672,-0.757,-0.33,-0.098,0.024,0.012,0.073,0.122,0.098,0.146,0.183,0.171,0.207,0.232];
    for (var i = 0; i < 200; i++) {
        data = data.concat(temp);
    }
    
    // case 1 : blurry
    var canvas1 = new fabric.Canvas("ecg1");
    var width   = 8000;
    var height  = 400;
    canvas1.setWidth(width);
    canvas1.setHeight(height);
    var bg1  = getBackgroundPath(width, height);
    var ecg1 = getEcgPath(data);
    canvas1.add(bg1);
    canvas1.add(ecg1);
    canvas1.renderAll(); // blurry
    
    
    function getBackgroundPath(width, height) {
        var grid = [];
        for (var y = 0; y <= height; y += 10) {
            grid.push("M");
            grid.push("0");
            grid.push(y);
            grid.push("H");
            grid.push(width);
        }
        for (var x = 0; x <= width; x += 10) {
            grid.push("M");
            grid.push(x);
            grid.push("0");
            grid.push("V");
            grid.push(height);
        }
        return new fabric.Path(grid.join(" "), {
            top  : 0,
            left : 0,
            stroke: 'pink',
            strokeWidth: 1
        });
    }
    function getEcgPath(data) {
        var xm = 2;
        var ym = 100;
        var max  = Math.max.apply(Math, data);
        var path = [];
        for (var i = 0; i < data.length; i++) {
            path.push("L");
            path.push(i * xm);
            path.push((max - data[i]) * ym);
        }
        path[0] = "M";
        return new fabric.Path(path.join(" "), {
            top  : 0,
            left : 0,
            fill : '',
            stroke: 'black',
            strokeWidth: 1,
            objectCaching: false,
        });
    }
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
</head>
<body>
  <canvas id="ecg1"></canvas>
  <script type="text/javascript" src="http://cdnjs.cloudflare.com/ajax/libs/fabric.js/2.3.3/fabric.min.js" ></script>
</body>
</html>

答案 1 :(得分:0)

@AndreaBogazzi

谢谢您的回答。使用fabric.Object.prototype.objectCaching = false之后,效果很好。

在我的应用程序中,绘制网格代码如下。

var data = [];
    var temp = [0,0,-0.012,-0.012,-0.012,-0.012,-0.012,-0.012,0,0,-0.012,-0.012,0,0.049,0.073,0.049,0.049,0.037,-0.012,-0.012,-0.024,-0.049,-0.024,-0.049,-0.061,-0.012,-0.061,-0.086,0.061,0.146,0.354,0.403,-0.647,-1.88,-1.672,-0.757,-0.33,-0.098,0.024,0.012,0.073,0.122,0.098,0.146,0.183,0.171,0.207,0.232];
    for (var i = 0; i < 200; i++) {
        data = data.concat(temp);
    }
    
    // case 1 : blurry
    var canvas1 = new fabric.Canvas("ecg1");
    var width   = 8000;
    var height  = 400;
    canvas1.setWidth(width);
    canvas1.setHeight(height);
    var bg11 = getBackgroundDot(width, height);
    var bg12 = getBackgroundPath(width, height);
    var ecg1 = getEcgPath(data);
    canvas1.add(bg11);
    canvas1.add(bg12);
    canvas1.add(ecg1);
    canvas1.renderAll(); // blurry
    
    function getBackgroundDot() {
        var dotLineWidth = 2;
        var dot = [];
        dot.push("M 0 0");
        for (var y = 0; y <= height; y += 10) {
            if (y % 50 == 0) {
                continue;
            }
            dot.push("M");
            dot.push("0");
            dot.push(y);
            dot.push("H");
            dot.push(width);
        }
        var sda = [0, 10];
        for (var i = 1; i < 5; i++) {
            sda.push(dotLineWidth);
            sda.push(8);
        }
        return new fabric.Path(dot.join(" "), {
            top  : 0,
            left : 0,
            stroke: 'pink',
            strokeWidth: dotLineWidth,
            strokeDashArray: sda
        });
    }
    
    function getBackgroundPath(width, height) {
        var grid = [];
        for (var y = 0; y <= height; y += 50) {
            grid.push("M");
            grid.push("0");
            grid.push(y);
            grid.push("H");
            grid.push(width);
        }
        for (var x = 0; x <= width; x += 50) {
            grid.push("M");
            grid.push(x);
            grid.push("0");
            grid.push("V");
            grid.push(height);
        }
        return new fabric.Path(grid.join(" "), {
            top  : 0,
            left : 0,
            stroke: 'pink',
            strokeWidth: 1
        });
    }
    
    function getEcgPath(data) {
        var xm = 2;
        var ym = 100;
        var max  = Math.max.apply(Math, data);
        var path = [];
        for (var i = 0; i < data.length; i++) {
            path.push("L");
            path.push(i * xm);
            path.push((max - data[i]) * ym);
        }
        path[0] = "M";
        return new fabric.Path(path.join(" "), {
            top  : 0,
            left : 0,
            fill : '',
            stroke: 'black',
            strokeWidth: 1
        });
    }
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
</head>
<body>
    
<canvas id="ecg1"></canvas>
    
<script type="text/javascript" src="http://cdnjs.cloudflare.com/ajax/libs/fabric.js/2.3.3/fabric.min.js" ></script>
</body>
</html>