qiuyueyuan 2019-08-22 13:02 采纳率: 0%
浏览 441

FabricJS 在mac机器上对Canvas调整大小屏幕会闪烁

我的HTML代码:
<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="utf-8" />
        <title>Ionic App</title>
        <!--script type="text/javascript" language='javascript' src="fabric.js"></script-->
        <script type="text/javascript" language='javascript' src="index.js"></script>
        <style type="text/css">
            html, body {
                width: 100%;
                height: 100%;
                margin-top: 0px;
                margin-bottom: 0px;
                margin-left: 0px;
                margin-right: 0px;
            }
            #left {
                float: left;
                width: 20%;
                height: 100%;
                border: 0px solid red;
                padding: 0px;
                margin: 0px;
            }
            #center {
                float: left;
                width: 80%;
                height: 100%;
                border: 0px solid green;
            }
            #canvasWrapper {
                overflow: scroll;
                background: #FFFFFF;
            }
            #canvas{
                border: 0px solid black;
            }
        </style>
    </head>
    <body id='body'>
        <div id='left'>
            <button onclick="init()">Init Canvas</button>
            <input type="file" onchange="chooseImage(event)"/><br/>
            <button onclick="zoomIn()">Zoom In</button>
            <button onclick="zoomOut()">Zoom Out</button><br/>
        </div>
        <div id='center'>
            <div id='canvasWrapper' tabIndex='0'>
                <canvas id="canvas" ></canvas>
            </div>
        </div>
    </body>
</html>

index.js代码:
/*! index.js 使用FabricJS对钡条逻辑封装的*/
              // 0  1    2  3    4     5  6    7     8    9    10
var zoomArray = [0.33, 0.4, 0.5, 0.66, 0.8, 1, 1.25, 1.5, 2, 2.5, 3];    //缩放的比例,都是对称的
var zoomIndex = 5;              //当前的zoomIndex

var canvasWrapper = null;       //Canvas的包裹物,当外部的window大小变化时候需要对它的宽度和高度设置
var canvas = null;              //Canvas
var fCanvas = null;             //中间的Fabric.Canvas

var backgroundBase64 = null;
var backgroundImage = null;     //背景fabric.Image
var backgroundImageWidth = 0    //Canvas的宽度,由图片的宽度决定
var backgroundImageHeight = 0;  //Canvas的高度,由图片的高度决定

//Canvas的属性
var canvasAttrs = {
    imageSmoothingEnabled: false,
    enableRetinaScaling: false,
    stopContextMenu: true,          //Menu禁用
    fireLeftClick: true,            //左按键启用
    fireMiddleClick: true,          //滚动键启用
    fireRightClick: false,          //右按键禁用
    //selectionColor: '#CC00FF',    //selection的颜色
    selectionLineWidth: 2,          //selection的线宽
    selection: true,                //selection启动
    selectionBorderColor: '#FFFF00',//selection边框颜色
    selectionFullyContained: true,  //只有当selection全部包含Canvas.Object的时候才会被选中
    selectionKey: 'ctrlKey'         //使用ctrlKey进行多选
};
//图片属性,中间Canvas的背景图和坐下那个图
var imageAttrs = {
    left: 0,
    top: 0,
    selectable: false,          //设置不能被选中,这样就可以作为背景图了
    hoverCursor: "default",     //设置它的鼠标形状
    crossOrigin: 'Anonymous'
};

/*!
 * OK选择文件
 */
function chooseImage(event) {
    var file = event.target.files[0];
    var reader = new FileReader();
    reader.onload = function(event) {
        var imgBase64 = event.target.result;
        backgroundBase64 = imgBase64;

        //构造数据
        var data = {};
        var dataMap = {};
        data['partitions'] = [];
        data['items'] = [];
        data['filters'] = {};
        dataMap['data'] = data;
        dataMap["base64"] = backgroundBase64;

        loadData(dataMap);
    }
    reader.readAsDataURL(file)
}

/*!
 * OK这是上来执行的函数
 */
function init() {
    __initFilterBackend();
    __initCanvasWrapper();
    __initCanvas();
}

function loadData(dataMap) {
    if (dataMap == null) return;

    //图片的Base64编码。这个值肯定是有的
    backgroundBase64 = dataMap['base64'];
    //加载背景图
    fabric.util.loadImage(backgroundBase64, function(img) {
        //背景图
        backgroundImage = new fabric.Image(img, imageAttrs);
        backgroundImageWidth = backgroundImage.width;
        backgroundImageHeight = backgroundImage.height;
        fCanvas.setWidth(backgroundImageWidth);
        fCanvas.setHeight(backgroundImageHeight);
        fCanvas.add(backgroundImage);
    });
}

/*!
 * OK放大按钮触发
 */
function zoomIn() {
    var oldZoom = zoomArray[zoomIndex];

    ++zoomIndex;
    if (zoomIndex > (zoomArray.length - 1)) {
        zoomIndex = (zoomArray.length - 1);
        //直接return掉,因为zoomIndex > (zoomArray.length - 1)说明之前的zoomIndex已经是数组最后一个了
        return;
    }

    __zoom(oldZoom);
}

/*!
 * OK缩小按钮触发
 */
function zoomOut() {
    var oldZoom = zoomArray[zoomIndex];

    --zoomIndex;
    if (zoomIndex < 0) {
        zoomIndex = 0;
        //直接return掉,因为zoomIndex < 0说明之前的zoomIndex已经是0了
        return;
    }
    __zoom(oldZoom);
}

/*!
 * OK初始化Filter后端。使用Canvas2dFilterBackend,因为如果用new fabric.WebglFilterBackend()会报错
 */
function __initFilterBackend() {
    fabric.filterBackend = new fabric.Canvas2dFilterBackend();
}

/*!
 * OK初始化CanvasWrapper
 */
function __initCanvasWrapper() {
    //如果已经初始话好了就直接return
    if (canvasWrapper != null) return;

    var centerDiv = window.document.getElementById('center');
    var width = centerDiv.offsetWidth;
    var height = centerDiv.offsetHeight;

    canvasWrapper = window.document.getElementById('canvasWrapper');
    //这里通过style的width和height里设置加上px,并且这里我不设置style的maxWidth和maxHeight
    //因为如果设置了maxWidth和maxHeight后当我们对里面的Canvas进行缩小的时候,如果里面的Canvas变的太小,这样
    canvasWrapper.style.width = width + 'px';
    canvasWrapper.style.height = height + 'px';
}

/*!
 * OK初始化Canvas
 */
function __initCanvas() {
    //如果已经初始化好了就直接return
    if (fCanvas != null) return;
    canvas = window.document.getElementById('canvas');

    //这里不设置宽度和高度,通过导入图片的宽高来设置
    fCanvas = new fabric.Canvas(canvas, canvasAttrs);
    //单纯设置canvas.backgroundColor内容无效,必须和下面的canvas.add一起才会起效果
    fCanvas.backgroundColor = 'black';
}

/*!
 * OK缩放的核心函数
 */
function __zoom(oldZoom) {
    //记录一开始的left和top值
    //var scrollLeft = canvasWrapper.scrollLeft;
    //var scrollTop = canvasWrapper.scrollTop;

    //以下是放大缩小操作,重新设置放大缩小的比例
    var zoom = zoomArray[zoomIndex];
    //在指定的点进行缩放
    fCanvas.setZoom(zoom);
    //!Important,加入对Canvas大小的设置,这样可以让CanvasWrapper也能进行调整
    fCanvas.setWidth(backgroundImageWidth*zoom);
    fCanvas.setHeight(backgroundImageHeight*zoom);

    //放大完后要重新设置transform
    //var vpt = fCanvas.viewportTransform;
    //console.log('-----' + vpt[4] + ' and ' + vpt[5]);
    //vpt[4] = 0;
    //vpt[5] = 0;
    //fCanvas.requestRenderAll();

    /* oldleft      newLeft
     * --------- = ---------
     * oldZoom      newZoom
     */
    //canvasWrapper.scrollLeft = (scrollLeft*zoom)/oldZoom;
    //canvasWrapper.scrollTop = (scrollTop*zoom)/oldZoom;
}
  • 写回答

1条回答 默认 最新

  • 自在猫先生 2023-07-03 11:07
    关注

    源于chatGPT仅供参考

    这个问题可能是由于在调整大小屏幕时,Canvas重新渲染造成的。为了解决这个问题,你可以尝试以下几点:
    
    1. 在调整大小屏幕之前先隐藏Canvas,然后调整完大小后再显示出来,这样可以减少闪烁的效果。
    
    2. 使用`requestAnimationFrame`方法来延迟Canvas的重绘,这样可以确保在屏幕刷新的时候进行渲染,减少闪烁的可能性。
    
    下面是修改后的JavaScript代码示例:
    
    ```javascript
    // ...
    
    /*!
     * OK缩放的核心函数
     */
    function __zoom(oldZoom) {
        //记录一开始的left和top值
        //var scrollLeft = canvasWrapper.scrollLeft;
        //var scrollTop = canvasWrapper.scrollTop;
    
        //以下是放大缩小操作,重新设置放大缩小的比例
        var zoom = zoomArray[zoomIndex];
    
        // 隐藏Canvas
        fCanvas.wrapperEl.style.display = 'none';
    
        // 使用requestAnimationFrame延迟重绘
        window.requestAnimationFrame(function() {
            //在指定的点进行缩放
            fCanvas.setZoom(zoom);
            //!Important,加入对Canvas大小的设置,这样可以让CanvasWrapper也能进行调整
            fCanvas.setWidth(backgroundImageWidth*zoom);
            fCanvas.setHeight(backgroundImageHeight*zoom);
    
            //放大完后要重新设置transform
            //var vpt = fCanvas.viewportTransform;
            //console.log('-----' + vpt[4] + ' and ' + vpt[5]);
            //vpt[4] = 0;
            //vpt[5] = 0;
            //fCanvas.requestRenderAll();
    
            // 显示Canvas
            fCanvas.wrapperEl.style.display = 'block';
        });
    
        /* oldleft      newLeft
         * --------- = ---------
         * oldZoom      newZoom
         */
        //canvasWrapper.scrollLeft = (scrollLeft*zoom)/oldZoom;
        //canvasWrapper.scrollTop = (scrollTop*zoom)/oldZoom;
    }
    
    // ...
    

    通过上述修改,你可以尝试解决在调整大小屏幕时Canvas闪烁的问题。希望能对你有所帮助!

    ```

    评论

报告相同问题?

悬赏问题

  • ¥15 js调用html页面需要隐藏某个按钮
  • ¥15 ads仿真结果在圆图上是怎么读数的
  • ¥20 Cotex M3的调试和程序执行方式是什么样的?
  • ¥20 java项目连接sqlserver时报ssl相关错误
  • ¥15 一道python难题3
  • ¥15 牛顿斯科特系数表表示
  • ¥15 arduino 步进电机
  • ¥20 程序进入HardFault_Handler
  • ¥15 oracle集群安装出bug
  • ¥15 关于#python#的问题:自动化测试