HTML Canvas 无法在移动设备上使用太大的画布绘制线条

发布于 2025-01-09 13:01:51 字数 4131 浏览 0 评论 0原文

编辑(2022 年 4 月 4 日): 我想我发现了问题。这与 iPhone 想要给画布分配多少内存有关。以下是我找到的一些资源: https://pqina.nl/blog/total -canvas-内存使用超出最大限制/ https://pqina.nl/blog/canvas-area-exceeds -the-maximum-limit/

我正在制作一个网站,您可以使用 p5js 在手机上的 HTML 画布上绘图。但是,当我使用函数 createCanvas() 创建画布并将宽度设置为大于 932 时,存在一个问题,它不会绘制线条。宽度为 932 或更小时,效果非常好。当 Chrome 中处于开发模式并选择 iPhone 12 作为选定设备时,它也会绘制界限。只有当画布大于 932 时,它才会在我的手机上破裂。当宽度大于932时,代码中似乎一切正常。在IOS上使用chrome时,我通过chrome://inspect检查了调试器,并且变量(例如p5js库的touches变量)被传递,并且触摸事件起作用,它唯一不做的就是画线。

关于我正在构建的网站,您需要了解一些事情:

  • 您可以用一根手指绘图,并且可以用两根手指滚动画布。这就是为什么我希望画布很大。以便用户可以滚动浏览它。
  • 您在主元素中滚动,而不是直接在画布元素中滚动。
  • 画布顶部有一个 UI 元素,您可以在其中选择颜色。

我使用 preventDefault(); 禁用了大部分触摸事件,以便我可以实现自己的触摸事件;用一根手指绘图,用两根手指滚动。

const main = document.getElementById("main");

let canvas;

// scrollX and scrollY are the amount to scroll throught the main element
let scrollY;
let scrollX;

// ptouch is the previous touch coordinates
let ptouchX;
let ptouchY;

let onCanvas = false;

// Check if canvas is touched. If it
document.addEventListener('touchstart', (event) => {
    if (event.target.isEqualNode(canvas.canvas)) {
        // Check if canvas is touched
        onCanvas = true;
        event.preventDefault();
    }
    else {
        onCanvas = false;
    }
}, { passive: false });

// Prevent all touchmove events
document.addEventListener('touchmove', (event) => {
    if (onCanvas || event.scale !== 1) {
        event.preventDefault();
    }
}, { passive: false });


document.addEventListener('touchend', (event) => {
    event.preventDefault();
    ptouchY = 0;
    ptouchX = 0;
});


function setup() {
    // canvas = createCanvas(932, 2000);
    canvas = createCanvas(2000, 2000);
    canvas.parent(main);
    strokeWeight(3);
    stroke(0);
}

function draw() {

    // Get the first touch coordinates and return;
    if (touches.length > 0 && (!ptouchX || !ptouchY)) {
        ptouchX = touches[0].x;
        ptouchY = touches[0].y;
        return;
    }

    // Drawing lines when there is one finger and there is a previous touch coordinates.
    if (touches.length === 1 && ptouchX && ptouchY && onCanvas) {
        line(touches[0].x, touches[0].y, ptouchX, ptouchY);
    }

    // Scroll throught the main element
    if (touches.length === 2) {
        scrollX = ptouchX - touches[0].x;
        scrollY = ptouchY - touches[0].y;

        main.scrollBy(scrollX, scrollY);
        return;
    }

    // While there are touches, the current touches become the previous touches.
    if (touches.length > 0) {
        ptouchX = touches[0].x;
        ptouchY = touches[0].y;
        return;
    }

}
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <script src="https://cdn.jsdelivr.net/npm/[email protected]/lib/p5.js"></script>
  <title>Drawing app</title>
  <style>
    html,
    body {
      margin: 0;
      padding: 0;
    }
    
    body {
      width: 100vw;
      height: 100vh;
    }
    
    main {
      width: 100vw;
      height: 100vh;
      overflow: scroll;
    }
  </style>
</head>

<body>

  <main id="main"></main>
  <script src="main.js"></script>
  
</body>

</html>

我认为这可能是造型错误。 Safari 或 Chrome 会更改画布或其他元素的大小,但在 ios 上的 chrome 调试器中,画布宽度返回 2000。代码运行良好,因此浏览器也不会禁用某些功能。

我试图思考为什么会发生这种行为,但我想不出任何东西。

我还有一台 Windows 笔记本电脑。

希望你能帮忙。谢谢。

Edit (4-4-2022):
I think I found the problem. It has something to do with how much memory the iPhone wants to give for the canvas. Here are some resources that I found:
https://pqina.nl/blog/total-canvas-memory-use-exceeds-the-maximum-limit/
https://pqina.nl/blog/canvas-area-exceeds-the-maximum-limit/

I am making a website where you can draw on an HTML canvas on your phone with p5js. But there is this one issue when I create the canvas with the function createCanvas() and set the width bigger than 932, it doesn't draw the lines. With a width of 932 or smaller, it works perfectly. It also draws the lines when in dev mode in chrome with iPhone 12 as selected device. Only when the canvas is bigger than 932 does it break on my phone. Everything seems to work in the code while the width is bigger than 932. With chrome on IOS, I checked the debugger via chrome://inspect, and the variables (such as the touches variable of the p5js library ) are passed through and the touch events work, the only thing that it doesn't do is draw the lines.

Some things you need to know about the website that I am building:

  • You are able to draw with one finger and you can scroll through the canvas with two fingers. That is why I want the canvas to be big. So that the user can scroll through it.
  • You scroll in the main element not directly in the canvas element.
  • There is a UI element on top of the canvas where you can select colors.

I disabled most of the touch events with preventDefault(); so that I can implement my own touch events; drawing with one finger and scrolling with two.

const main = document.getElementById("main");

let canvas;

// scrollX and scrollY are the amount to scroll throught the main element
let scrollY;
let scrollX;

// ptouch is the previous touch coordinates
let ptouchX;
let ptouchY;

let onCanvas = false;

// Check if canvas is touched. If it
document.addEventListener('touchstart', (event) => {
    if (event.target.isEqualNode(canvas.canvas)) {
        // Check if canvas is touched
        onCanvas = true;
        event.preventDefault();
    }
    else {
        onCanvas = false;
    }
}, { passive: false });

// Prevent all touchmove events
document.addEventListener('touchmove', (event) => {
    if (onCanvas || event.scale !== 1) {
        event.preventDefault();
    }
}, { passive: false });


document.addEventListener('touchend', (event) => {
    event.preventDefault();
    ptouchY = 0;
    ptouchX = 0;
});


function setup() {
    // canvas = createCanvas(932, 2000);
    canvas = createCanvas(2000, 2000);
    canvas.parent(main);
    strokeWeight(3);
    stroke(0);
}

function draw() {

    // Get the first touch coordinates and return;
    if (touches.length > 0 && (!ptouchX || !ptouchY)) {
        ptouchX = touches[0].x;
        ptouchY = touches[0].y;
        return;
    }

    // Drawing lines when there is one finger and there is a previous touch coordinates.
    if (touches.length === 1 && ptouchX && ptouchY && onCanvas) {
        line(touches[0].x, touches[0].y, ptouchX, ptouchY);
    }

    // Scroll throught the main element
    if (touches.length === 2) {
        scrollX = ptouchX - touches[0].x;
        scrollY = ptouchY - touches[0].y;

        main.scrollBy(scrollX, scrollY);
        return;
    }

    // While there are touches, the current touches become the previous touches.
    if (touches.length > 0) {
        ptouchX = touches[0].x;
        ptouchY = touches[0].y;
        return;
    }

}
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <script src="https://cdn.jsdelivr.net/npm/[email protected]/lib/p5.js"></script>
  <title>Drawing app</title>
  <style>
    html,
    body {
      margin: 0;
      padding: 0;
    }
    
    body {
      width: 100vw;
      height: 100vh;
    }
    
    main {
      width: 100vw;
      height: 100vh;
      overflow: scroll;
    }
  </style>
</head>

<body>

  <main id="main"></main>
  <script src="main.js"></script>
  
</body>

</html>

I thought that it might be a styling err. That Safari or Chrome changes the size of the canvas or some other element but in the chrome debugger on ios, the canvas width returns 2000. The code works fine so the browsers don't disable some functionalities either.

I am trying to think why this behavior would occur but I can't think of anything.

And also I have a windows laptop.

Hope you can help. Thanks.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文