zoukankan      html  css  js  c++  java
  • 如何使用CSS Paint API动态创建与分辨率无关的可变背景

    设置项目

    首先,创建一个新的 index.html 文件,并编写如下代码:

    <!DOCTYPE html>
    <html lang="en">
      <head>
        <meta charset="UTF-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <title> css Paint API</title>
        <link rel="stylesheet" href="styles.css" />
      </head>
      <body>
        <textarea class="pattern"></textarea>
        <script>
          if ('paintWorklet' in CSS) {
            CSS.paintWorklet.addModule('pattern.js');
          }
        </script>
      </body>
    </html>

    有几件事要注意:

    • 在第13行,我们加载了一个新的Paint worklet。目前,全球支持率约为63%。因此,我们必须首先检查是否支持 paintWorklet。
    • 我正在使用 textarea 进行演示,因此我们可以看到调整画布的大小将如何重绘图案。
    • 最后,你需要创建一个 pattern.js(用于注册绘画工作区)以及一个 styles.css,我们可以在其中定义几个样式。

    什么是worklet?

    Paint worklet是一个定义了应该画在画布上的内容的类。它们的工作原理与 canvas 元素类似。如果你以前有这方面的知识,代码会看起来很熟悉。然而,它们并不是100%相同的。例如,在worklet中还不支持文本渲染方法。

    在这里,我们还要定义CSS样式。这是我们要使用worklet的地方:

    .pattern {
       250px;
      height: 250px;
      border: 1px solid #000;
    
      background-image: paint(pattern);
    }

    我添加了一个黑色的边框,这样我们可以更好地看到 textarea。要引用一个paint worklet,你需要把 paint(worklet-name) 作为一个值传递给 background-image 属性。但是 pattern 是从哪里来的呢?我们还没有定义它,所以让我们把它作为我们的下一步。

    https://www.tmojm.com 创业加盟网

    定义Worklet

    打开 pattern.js 并添加以下内容:

    class Pattern {
      paint(context, canvas, properties) {
    
      }
    }
    
    registerPaint('pattern', Pattern);

    在这里可以使用 registerPaint 方法注册paintWorklet。你可以在此处定义的CSS中引用第一个参数。第二个参数是定义应在canvas上绘画的类。它具有一个包含三个参数的 paint 方法:

    • context:这将返回一个 PaintRenderingContext2D 对象,该对象实现 CanvasRenderingContext2D API 的子集。
    • canvas:这是我们的canvas,一个 PaintSize 对象,只有两个属性:width和height。
    • properties:这将返回一个 StylePropertyMapReadOnly 对象,我们可以使用该对象通过JavaScript读取CSS属性及其值。

    绘制矩形

    下一步是显示一些东西,所以让我们绘制矩形。将以下内容添加到 paint 方法中:

    paint(context, canvas, properties) {
      for (let x = 0; x < canvas.height / 20; x++) {
        for (let y = 0; y < canvas.width / 20; y++) {
          const bgColor = (x + y) % 2 === 0 ? '#FFF' : '#FFCC00';
    
          context.shadowColor = '#212121';
          context.shadowBlur = 10;
          context.shadowOffsetX = 10;
          context.shadowOffsetY = 1;
    
          context.beginPath();
          context.fillStyle = bgColor;
          context.rect(x * 20, y * 20, 20, 20);
          context.fill();
        }
      }
    }

    我们在这里所做的就是创建一个嵌套循环,以循环遍历画布的宽度和高度。由于矩形的大小为20,因此我们要将矩形的高度和宽度除以20。

    在第4行,我们可以使用模数运算符在两种颜色之间切换。我还为深度添加了一些阴影。最后,我们在画布上绘制矩形。如果在浏览器中打开它,则应具有以下内容:

    使背景动态化

    遗憾的是,除了调整 textarea 的大小和一窥Paint API是如何重绘一切的,这大部分还是静态的。所以,让我们通过添加我们可以改变的自定义CSS属性来让事情变得更加动态。

    打开你的 styles.css 并在其中添加以下几行:

    .pattern {
          250px;
         height: 250px;
         border: 1px solid #000;
    
         background-image: paint(pattern);
    +    --pattern-color: #FFCC00;
    +    --pattern-size: 23;
    +    --pattern-spacing: 0;
    +    --pattern-shadow-blur: 10;
    +    --pattern-shadow-x: 10;
    +    --pattern-shadow-y: 1;
     }

    你可以通过在CSS属性前加上 — 来定义自定义CSS属性。这些属性可以被 var() 函数使用。但在我们的案例中,我们将在我们的paint worklet中使用它。

    在CSS中检查支持

    为确保支持Paint API,我们还可以检查CSS中的支持。为此,我们有两个选择:

    • 使用 @supports 规则守护规则。
    • 使用后备背景图片。
    /* 第一种选择 */
    @supports (background: paint(pattern)) {
      /**
       * 如果该部分得到评估,则意味着Paint API 支持
       **/
    }
    
    /**
     * 第二种选择
     * 如果支持Paint API,后一条规则将覆盖第一条规则。
     * 如果不支持,CSS将使其无效,并将应用url()的规则。
     **/
    .pattern {
      background-image: url(pattern.png);
      background-image: paint(pattern);
    }

    访问绘画worklet中的参数

    要读取 pattern.js 中的这些参数,您需要向定义paint worklet的类中添加一个新方法:

    class Pattern {
      // `inputProperties`方法返回的任何东西,paint worklet都可以访问。
      static get inputProperties() { 
        return [
          '--pattern-color',
          '--pattern-size',
          '--pattern-spacing',
          '--pattern-shadow-blur',
          '--pattern-shadow-x',
          '--pattern-shadow-y'
        ]; 
      }
    }

    要在 paint 方法内部访问这些属性,可以使用 properties.get:

    paint(context, canvas, properties) {
      const props = {
        color: properties.get('--pattern-color').toString().trim(),
        size: parseInt(properties.get('--pattern-size').toString()),
        spacing: parseInt(properties.get('--pattern-spacing').toString()),
        shadow: {
          blur: parseInt(properties.get('--pattern-shadow-blur').toString()),
          x: parseInt(properties.get('--pattern-shadow-x').toString()),
          y: parseInt(properties.get('--pattern-shadow-y').toString())
        }
      };
    }

    对于颜色,我们需要将其转换为字符串。其他所有内容都需要转换为数字。这是因为 properties.get 返回 CSSUnparsedValue。

    为了使内容更具可读性,我创建了两个新函数来为我们处理解析:

    paint(context, canvas, properties) {
      const getPropertyAsString = property => properties.get(property).toString().trim();
      const getPropertyAsNumber = property => parseInt(properties.get(property).toString());
    
      const props = {
        color: getPropertyAsString('--pattern-color'),
        size: getPropertyAsNumber('--pattern-size'),
        spacing: getPropertyAsNumber('--pattern-spacing'),
        shadow: {
          blur: getPropertyAsNumber('--pattern-shadow-blur'),
          x: getPropertyAsNumber('--pattern-shadow-x'),
          y: getPropertyAsNumber('--pattern-shadow-y')
        }
      };
    }

    现在我们要做的就是用相应的 prop 值替换for循环中的所有内容:

    for (let x = 0; x < canvas.height / props.size; x++) {
      for (let y = 0; y < canvas.width / props.size; y++) {
        const bgColor = (x + y) % 2 === 0 ? '#FFF' : props.color;
    
        context.shadowColor = '#212121';
        context.shadowBlur = props.shadow.blur;
        context.shadowOffsetX = props.shadow.x;
        context.shadowOffsetY = props.shadow.y;
    
        context.beginPath();
        context.fillStyle = bgColor;
        context.rect(x * (props.size + props.spacing),
                     y * (props.size + props.spacing), props.size, props.size);
        context.fill();
      }
    }

    现在回到你的浏览器,试着改变一下。

  • 相关阅读:
    ||和&&
    用jQuery编的一个分页小代码
    Intent携带额外的数据的方法
    Handler消息传递机制
    安卓中的消息提示
    使用AlertDialog创建对话框的大致步骤
    布局管理器
    Android中支持的常用距离单位
    开发自定义View
    Gridview中奇偶数行颜色设置
  • 原文地址:https://www.cnblogs.com/qianxiaox/p/15065989.html
Copyright © 2011-2022 走看看