P5.js:如何防止文本在使用 flexbox 时被压碎

问题描述

我正在尝试使用 p5.js 草图创建响应式网页。

在网页中,我使用 flexBox 切换了侧边栏。 但是一旦侧边栏出现在窗口的左侧,它就会粉碎我在 p5.js 中的画布(结果是画布中的所有图像/文本也会变形)。 为了让我的问题易于理解,我在此处上传了一张图片和一张 demo 非常感谢,非常感谢您的帮助。

demo_image

/*When button clicked,show / hide the sidebar */
function toggle(){
  $('main').on('click','.toggle-sidebar',function(){
    var sidebar = $('.sidebar');
       sidebar.toggleClass('is-visible');
       sidebar.toggle(300);
    })
};
toggle();


/*p5.js*/
const typo = (sketch) => {
  let x1 = 0;
  let x2;
  let speed = 3;
  /*Responsive canvas => make the canvas width equals to it's parent container*/
  let cvs_parent_width = document.getElementById("canvas").offsetWidth;
  let cvs_width = cvs_parent_width;
  /*Responsive font => font size is set based on canvas width */
  let ratio_responsive = 200 / 1500;
  
  sketch.setup = () => {
   let cvs = sketch.createCanvas(cvs_width,sketch.windowHeight);
    sketch.textFont("Palatino");
    cvs.style("display","block");
  };

  sketch.draw = () => {
    sketch.background(220);
    x1 += speed;
    x2 += speed;
    if (x2 > 0) {
      x1 = x2 - cvs_width;
    }
    if (x1 > 0) {
      x2 = x1 - cvs_width;
    }

    let typo_size = cvs_width * ratio_responsive;
    sketch.textSize(typo_size);
    sketch.text("TYPO CrushED",x1,30,cvs_width,sketch.windowHeight);
    sketch.text("TYPO CrushED",x2,sketch.windowHeight);
  }
}

let typo_sketch = new p5(typo,"canvas");
html,body  {
  width: 100%;
  height: 100%;
  margin: 0;
}

main{
  overflow:hidden;
}

/* FlexBox for showing n hide sidebar*/
/* flex parent */
.flexgroup {
  display: flex;
  justify-content: flex-end;
}

/* flex item1 */
.sidebar {
  flex-grow: 0;
  flex-shrink: 0;
  flex-basis: auto;
  height: 100%;
  width:50vw;
}

/* flex item2 */
.image {
  flex-grow: 1;
  flex-shrink: 0;
  flex-basis: 100%;
  max-width:100%;
  transition: flex-basis .3s;
}

.none{
  display:none;
}

.sidebar.is-visible  ~ .image {
  flex-basis: 0;
  transition: flex-basis .3s;
}

/* parameters of canvas */
canvas{
  margin:auto;
  display:block;
  max-width: 100%; 
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<!DOCTYPE html>
<html lang="en">
  <head>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.3.1/p5.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.3.1/addons/p5.sound.min.js"></script>
    
    <Meta charset="utf-8" />

  </head>
  <body>
  <main>
  <!-- TOGGLE BUTTON-->
  <button class="toggle-sidebar">Toggle</button>

  <!-- FLEXBox-->
  <div class='flexgroup'>
  <!-- FLEXBox Item1-->
    <div class="sidebar none">
     <p>
        SIDEBAR
      </p>
    </div>
   
  <!-- FLEXBox Item2-->
    <div class='image'>
      <div id="canvas">
  <!-- P5.JS-->    
      </div>
    </div>
  </div>
</main>
  </body>
</html>

解决方法

当画布因布局变化而调整大小时,绘图上下文大小不会更新以反映这一点。您需要检测新尺寸并相应地更新画布大小。当使用全窗口画布或相对于窗口大小调整大小的画布时,这可以通过 p5.js windowResized 函数轻松完成。然而,因为你是根据 flexbox 布局为特定元素(动画不少)调整画布大小,所以事情有点复杂。如果您使用的是 modern,mainstream web browser,那么您可以使用 ResizeObserver。以下是演示如何使用 ResizeObserver 解决您的问题的代码段:

/*When button clicked,show / hide the sidebar */
function toggle(){
  $('main').on('click','.toggle-sidebar',function(){
    var sidebar = $('.sidebar');
       sidebar.toggleClass('is-visible');
       sidebar.toggle(300);
    })
};
toggle();


/*p5.js*/
const typo = (sketch) => {
  let x1 = 0;
  let x2;
  let speed = 3;
  /*Responsive canvas => make the canvas width equals to it's parent container*/
  let cvs_parent_width = document.getElementById("canvas").offsetWidth;
  let cvs_width = cvs_parent_width;
  /*Responsive font => font size is set based on canvas width */
  let ratio_responsive = 200 / 1500;
  let cvs;
  
  sketch.setup = () => {
    cvs = sketch.createCanvas(cvs_width,sketch.windowHeight);
    sketch.textFont("Palatino");
    cvs.style("display","block");
    new ResizeObserver(canvasParentResized).observe(cvs.parent());
  };
  
  let supressResize = false;
  function canvasParentResized() {
    if (!supressResize) {
      let parent = cvs.parent();
      if (parent && parent.offsetWidth) {
        // console.log('resized');
        supressResize = true;
        cvs_width = cvs_parent_width = parent.offsetWidth;
        sketch.resizeCanvas(cvs_parent_width,sketch.windowHeight);
      } else {
        console.log(parent.offsetWidth);
      }
    } else {
      // Resizing the canvas tiggers the ResizeObserver recursively
      // console.log('supressed');
      supressResize = false;
    }
  }

  sketch.draw = () => {
    sketch.background(220);
    x1 += speed;
    x2 += speed;
    if (x2 > 0) {
      x1 = x2 - cvs_width;
    }
    if (x1 > 0) {
      x2 = x1 - cvs_width;
    }

    let typo_size = cvs_width * ratio_responsive;
    sketch.textSize(typo_size);
    sketch.text("TYPO CRUSHED",x1,30,cvs_width,sketch.windowHeight);
    sketch.text("TYPO CRUSHED",x2,sketch.windowHeight);
  }
}

let typo_sketch = new p5(typo,"canvas");
html,body  {
  width: 100%;
  height: 100%;
  margin: 0;
}

main{
  overflow:hidden;
}

/* Flexbox for showing n hide sidebar*/
/* flex parent */
.flexgroup {
  display: flex;
  justify-content: flex-end;
}

/* flex item1 */
.sidebar {
  flex-grow: 0;
  flex-shrink: 0;
  flex-basis: auto;
  height: 100%;
  width:50vw;
}

/* flex item2 */
.image {
  flex-grow: 1;
  flex-shrink: 0;
  flex-basis: 100%;
  max-width:100%;
  transition: flex-basis .3s;
}

.none{
  display:none;
}

.sidebar.is-visible  ~ .image {
  flex-basis: 0;
  transition: flex-basis .3s;
}

/* parameters of canvas */
canvas{
  margin:auto;
  display:block;
  max-width: 100%; 
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<!DOCTYPE html>
<html lang="en">
  <head>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.3.1/p5.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.3.1/addons/p5.sound.min.js"></script>
    
    <meta charset="utf-8" />

  </head>
  <body>
  <main>
  <!-- TOGGLE BUTTON-->
  <button class="toggle-sidebar">Toggle</button>

  <!-- FLEXBOX-->
  <div class='flexgroup'>
  <!-- FLEXBOX Item1-->
    <div class="sidebar none">
     <p>
        SIDEBAR
      </p>
    </div>
   
  <!-- FLEXBOX Item2-->
    <div class='image'>
      <div id="canvas">
  <!-- P5.JS-->    
      </div>
    </div>
  </div>
</main>
  </body>
</html>