You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在PaperJS中禁用画布重绘以保留刮刮卡擦除效果?

固定初始画布尺寸解决刮除效果丢失问题

没问题!固定初始画布尺寸确实能解决窗口缩放或手机旋转时刮除效果丢失的问题——核心就是让画布保持一开始的固定像素尺寸,不再随窗口变化重绘,只通过CSS让它在页面上自适应显示。下面是具体的实现步骤和修改后的代码:

核心修改思路

  • 取消PaperJS对窗口resize的监听,避免触发重绘清空图层
  • 固定画布的实际绘图尺寸(和你的刮刮卡图片尺寸一致)
  • 用CSS让画布自适应页面空间,但不改变内部绘图区域的大小

修改后的完整代码

<html> 
<head> 
    <meta charset="UTF-8"> 
    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" /> 
    <title>圣诞刮刮卡</title> 
    <script type="text/javascript" src="wp-content/themes/generatepress_child/paper-full.min.js"></script> 
    <script type="text/paperscript" canvas="canvas"> 
        // Based on 'JPEG Raster' by Jonathan Puckey: 
        // http://www.flickr.com/photos/puckey/3179779686/in/photostream/ 

        // 创建 raster 项,使用隐藏的图片
        var raster = new Raster('mona'); 
        raster.visible = true; 
        raster.position = view.center; 

        var lastPos = view.center; 

        function moveHandler(event) { 
            if (lastPos.getDistance(event.point) < 1) return; 
            lastPos = event.point; 

            var size = this.bounds.size.clone(); 
            var isLandscape = size.width > size.height; 
            size /= isLandscape ? [2, 1] : [1, 2]; 

            if (size.ceil().width > 10) { 
                var path = new Path.Rectangle({ 
                    point: this.bounds.topLeft.floor(), 
                    size: size.ceil(), 
                    onMouseMove: moveHandler 
                }); 
                path.fillColor = raster.getAverageColor(path); 

                var path = new Path.Rectangle({ 
                    point: isLandscape ? this.bounds.topCenter.ceil() : this.bounds.leftCenter.ceil(), 
                    size: size.floor(), 
                    onMouseMove: moveHandler 
                }); 
                path.fillColor = raster.getAverageColor(path); 
            } 
            this.remove(); 
        } 

        // 初始化时创建初始遮罩路径,不再监听resize事件
        function onLoad() {
            // 让 raster 适配固定的画布尺寸
            raster.fitBounds(view.bounds, true); 
            // 创建初始遮罩
            new Path.Rectangle({ 
                rectangle: view.bounds, 
                fillColor: raster.getAverageColor(view.bounds), 
                onMouseMove: moveHandler 
            }); 
        }

        // 页面加载完成后执行初始化
        window.onload = onLoad;
    </script> 
    <style type="text/css" id="wp-custom-css"> 
        #canvas{ 
            background: center center url(/web.jpg); 
            width:100%; 
            height:100vh; 
            position: absolute; 
            top:0; 
            bottom: 0; 
            left: 0; 
            right: 0; 
            margin: 0 auto;
            object-fit: contain; /* 关键:让画布自适应显示但保持比例 */
        } 
        #cc{ 
            max-width:2560px; 
            position: absolute; 
            top:0; 
            bottom: 0; 
            left: 0; 
            right: 0; 
            margin: 0 auto; 
        } 
    </style> 
</head> 
<body> 
    <!-- 移除 resize 属性,固定画布尺寸为图片的1024x1024 -->
    <canvas id="canvas" width="1024" height="1024"></canvas> 
    <img width="1024" height="1024" id="mona" style="display: none;" src="/web.jpg"> 
</body> 
</html>

关键修改点说明

  1. 画布标签修改:给<canvas>添加了固定的width="1024"和height="1024",同时移除了resize属性——这告诉PaperJS不要监听窗口尺寸变化。
  2. 移除onResize函数:原来的onResize会在窗口变化时清空所有图层并重绘,现在我们不需要这个逻辑了,换成onLoad在页面加载时初始化一次遮罩。
  3. CSS添加object-fit: contain:让画布在页面上自适应缩放时,保持内部内容的比例,不会拉伸变形,用户看到的刮刮卡始终是正确的比例。

这样修改后,不管窗口怎么缩放或者手机旋转,画布的内部绘图区域尺寸都是固定的1024x1024,已经刮除的部分不会被清空,效果就能完美保留啦!

内容的提问来源于stack exchange,提问作者Alo Lätt

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 08:59:38