【问题标题】:Lit-Element Not Resizing on Window Resize窗口调整大小时点亮元素不调整大小
【发布时间】:2021-10-28 04:24:22
【问题描述】:

我有一个画布元素,它应该随着窗口调整大小而调整大小,但由于某种原因它没有改变。元素应保持为正方形,占据视图高度的 80%。

相关的 css 看起来像这样,而 square 类适用于另一个没有在 css 和 javascript 中更新的元素。

static get styles() {
    return [
      tachyons,
      css`
        .square {
          width: min(50vw, 75vh);
          height: min(50vw, 75vh);
        }`
      ]
}

尽管浏览器识别了类,但画布不会更新。我正在使用 Safari 进行测试(不要问为什么)。

const karelView = ({ displayAltCanvas, index, indexes, className }) => {
  return html`<div class=${className || '' + ' mt5'}>
    <canvas
      id="canvasAlt"
      class="square ${displayAltCanvas ? 'bg-light-yellow' : 'absolute o-0'}"
    ></canvas>
    <canvas id="canvas" class="square${displayAltCanvas ? ' dn' : ''}"></canvas>
    <div class="db w-100">
      <input
        class="w-100"
        type="range"
        min="0"
        value=${index ? index() : 0}
        max=${indexes || 0}
        step="1"
        @input=${e => index?.(parseInt(e.target.value))}
      />
    </div>
  </div>`;
};

这就是我认为错误的来源。回调被正确触发,但由于某种原因,即使窗口已经调整大小并且 css 应该已经更新了 clientWidth,分辨率仍然匹配。

  async handleResize(canvas) {
    canvas ??= this.canvas;
    if (canvas === null) {
      console.warn('null canvas');
      return;
    }
    const width = canvas.clientWidth;
    const height = canvas.clientHeight;
    const resolutionMatch = canvas.width === width && canvas.height === height;
    if (!resolutionMatch) {
      canvas.width = width;
      canvas.height = height;
    }
    const world = this.state || (await this.worlds).currentWorld;
    // this.index !== undefined && this.index(this.index());
    draw(this.canvas, world);
  }

  connectedCallback() {
    super.connectedCallback();
    this._resizers = (() => {
      this.handleResize(this.canvas);
      this.handleResize(this.canvasAlt);
    }).bind(this);
    window.addEventListener('resize', this._resizers);
  }

  render() {
    return html` ${karelView({
      displayAltCanvas: this.displayAltCanvas,
      index: this.index,
      indexes: this.indexes,
    })}`;
  }

【问题讨论】:

    标签: javascript web-component shadow-dom lit-element lit-html


    【解决方案1】:

    &lt;canvas&gt;.clientWidth 在本机代码中正确调整大小。

    因此,如果 Lit 完美无瑕,那一定是您的代码中存在错误。

    注意事项:

    • 当您在 DOM 中移动元素时,connectedCallback 将触发多次

    • 不需要oldskool bind()(除非你传递一个函数reference

    • 无需声明async handleResize(这不是你的错误的原因)

    <my-element></my-element>
    
    <script>
      customElements.define('my-element', class extends HTMLElement {
        constructor() {
          super()
            .attachShadow({mode:'open'})
            .innerHTML = `<b/><style>canvas{width:50vw}</style><canvas></canvas>`;
        }
        query(selector){
          return this.shadowRoot.querySelector(selector);
        }
        connectedCallback() {
          window.addEventListener("resize", evt => this.handleResize(evt) );
          this.handleResize();
        }
        handleResize(evt) {
          let canvas = this.query("canvas");
          this.query("b").innerHTML = canvas.clientWidth + "px";
        }
      })
    </script>

    或者:

    <my-element></my-element>
    
    <script>
      customElements.define('my-element', class extends HTMLElement {
        constructor() {
          super()
            .attachShadow({mode:'open'})
            .innerHTML = `<b/><style>canvas{width:50vw}</style><canvas></canvas>`;
          window.addEventListener("resize", evt => {
            this.shadowRoot.querySelector("b").innerHTML = 
                 this.shadowRoot.querySelector("canvas").clientWidth + "px";
          });
          window.dispatchEvent(new Event("resize"));
        }
      })
    </script>

    【讨论】: