【问题标题】:Approaches for setting an animated canvas as background clipped text of a heading tag?将动画画布设置为标题标签的背景剪辑文本的方法?
【发布时间】:2021-09-25 15:53:02
【问题描述】:

我想将动画画布作为<h1 /> 的背景剪辑。要求是:

  • 使用实际的<h1 /> 标记而不是在画布中呈现标题。
  • 使用要通过ctx.drawImage() 渲染的图像。

h1 { 
  color: transparant;
  background-image: <some-canvas>;
  background-clip: text;
}

到目前为止,我已经尝试了几种方法并取得了不同程度的成功:

  • 使用-webkit-canvas-moz-element 创建一个常规画布并将其设置为&lt;h1 /&gt;-tag 的背景。这种方法满足了我的所有要求,但不幸的是 -webkit-canvas 在 Chromium 中与 document.getCSSCanvasContext("2d") 一起被弃用。 Safari 是唯一可用的浏览器。
  • 使用 CSS Paint API (Houdini)。使用 requestAnimationFrame() 更新 css var 我可以继续勾选动画并执行我想要实现的动画。但是,在 Chromium 中,必须使用解决方法来传递图像(而不是创建图像类型的属性,图像必须使用 background-image 传递,这使我无法使用 background-image 告诉 CSS Paint使用我的 worklet 作为背景。规范没有完全实现。
  • 创建内联 svg 作为背景图像: url("data:image/svg+xml;utf8,&lt;svg&gt;&lt;foreignObject&gt;&lt;canvas id='..'/&gt;&lt;/foreignObject&gt;&lt;/svg&gt;"); 并尝试使用 requestAnimationFrame 更新该画布。根本不起作用。

我还有其他方法可以尝试吗?

【问题讨论】:

    标签: javascript html css canvas houdini


    【解决方案1】:

    如果它不是background-image,您可以canvas元素放在h1元素中,匹配canvaswidthheight 设置为h1 元素的z-index,使其低于h1 元素中的文本,使其看起来在文本后面,就像背景一样。

    var canvas = document.getElementById('canvas');
    var ctx = canvas.getContext('2d');
    
    /*
      Set the dimensions of the canvas to 
      match the parent h1 element
    ----------------------------------------------------------*/
    setCanvasSize();
    
    // (and for demonstrative purposes, scale on window resize)
    window.addEventListener('resize', setCanvasSize, false);
    
    function setCanvasSize () {
      var _w = canvas.parentNode.clientWidth;
      var _h = canvas.parentNode.clientHeight;
      canvas.width = _w;
      canvas.height = _h;
      canvas.style.width = "'" + _w + "px'";
      canvas.style.height = "'" + _h + "px'";
    }
    /*--------------------------------------------------------*/
    
    /*--------------------------------------------------------
      All this code below is just a ball animation borrowed from MDN
      to illustrate what I'm suggesting.
      
      Source: MDN 
      https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API/Tutorial/Advanced_animations 
    */
    var raf;
    var running = false;
    
    var ball = {
      x: 100,
      y: 100,
      vx: 5,
      vy: 1,
      radius: 50,
      color: 'blue',
      draw: function() {
        ctx.beginPath();
        ctx.arc(this.x, this.y, this.radius, 0, Math.PI * 2, true);
        ctx.closePath();
        ctx.fillStyle = this.color;
        ctx.fill();
      }
    };
    
    function clear() {
      ctx.fillStyle = 'rgba(255, 255, 255, 0.3)';
      ctx.fillRect(0,0,canvas.width,canvas.height);
    }
    
    function draw() {
      clear();
      ball.draw();
      ball.x += ball.vx;
      ball.y += ball.vy;
    
      if (ball.y + ball.vy > canvas.height || ball.y + ball.vy < 0) {
        ball.vy = -ball.vy;
      }
      if (ball.x + ball.vx > canvas.width || ball.x + ball.vx < 0) {
        ball.vx = -ball.vx;
      }
    
      raf = window.requestAnimationFrame(draw);
    }
       
    if (!running) {
      raf = window.requestAnimationFrame(draw);
      running = true;
    }
    
    ball.draw();
    /*--------------------------------------------------------*/
    h1 {
      /* Important for positioning the span element */
      position: relative;
      
      /* Cosmetic/demonstrative */
      border: 2px solid red;
      height: 100%;
      text-align: center;
      color: red;
      font-size: 32px;
      font-family: Roboto,sans-serif;
      margin: 0 auto;
    }
    
    h1 span { 
      /* Vertically and horizontally center the text */
      position: absolute;
      top: 50%;
      left: 50%;
      transform: translate(-50%,-50%);
      
      /*
        Text will appear above canvas as long as its 
        z-index > canvas' z-index
      */
      z-index: 2;
    
    }
    
    h1 canvas {
      /* this will make the canvas appear behind the text */
      position: relative;
      z-index: 1; 
    }
    <h1>
      <span>Lorem Ipsum etc.</span>
      <canvas id="canvas"></canvas>
    </h1>

    只是一个想法,也许您可​​以尝试一下并扩展该想法以满足您的需求。我不是 100% 确定你在做什么,如果没有帮助,请见谅。

    【讨论】:

    • 绝对放置画布会有更好的结果,这样它就不会影响 h1 的大小。此外,最好使用 ResizeObserver(在父级上)来设置画布的大小。
    猜你喜欢
    • 1970-01-01
    • 2015-11-21
    • 1970-01-01
    • 1970-01-01
    • 2014-08-12
    • 2017-02-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多