# # use

> The use here takes the introduction separately as an example,Global introductionUse similar.

## # `WebLoading`

> Whether it is `DOM`, `FULL` or `MINI` , it will eventually go to `WebLoading`.

    import { LoadingType } from "web-loading/src/types.d";
    import initLoading from 'web-loading/src/loading'
    let webLoading:LoadingType = initLoading({})
    console.log(webLoading)

> `LoadingType`：`loading`、`resize`、`close`、`update`、`getOptions`、`getLoadingId`。

### # loading

> Start the animation`loading`。

- Parameters:

  - `dom:HTMLElement`
  - `options?:OptionsType`

- Return: void

> When the `loading` function is called, it will first check whether the `loadingId` exists (whether it is still being drawn). Only when there is no drawing status can it be started.

> The `loading` parameter 2 can override the `options` of the initialization `initLoading` .

### # resize

> Recalculate and draw the `loading` size.

- Parameter: None
- Return: void

> `Resize`will retrieve the size and redraw from the bound`HtmlElement`. This function will not re-instance`WebLoading`and`loading`business scenarios. For example,`window. addEventListener (`resize`, loading. resize)` may be used.

### # close

> close`loading。`

- Parameter: None
- Return: void

> `close` will first clear all `stores` and other records of`WebLoading`, and stop the`requestAnimationFrame`call, and finally clear the relevant elements according to`delayInto`. During the closing process,`WebLoading`will use`hookCall`to trigger the`hook`to close hook function (`BEFORE _COLSE`: before closing,`COLSED`: after closing, that is, after clearing the elements) to facilitate the drawing of model.

### # update

> Draw `model` dynamically. Public Configuration cannot be modified dynamically.

- Parameter:
  - `options?:OptionsType`
- Return:void

> The update function does not re-instance `WebLoading`, and re-draws`model`through the parameter`options`. The business scenario is similar to `loading`, but `loading` initializes`WebLoading`every time. Only when it is closed can the corresponding business be implemented. Therefore,`update`is recommended in the dynamic rendering`model`business scenario.

### # getOptions

> Get the current options configuration.

- Parameter: None

- Return:

  - `options:OptionsType`

### # getLoadingId

> obtain `loadingId`。

- Parameter: None

- Return:

  - `loadingId:string | null`

> The `loadingId` will be assigned a value after initialization, and will be assigned a value of`null`after`close`is closed. Therefore, if`loadingId`is`null`, there is currently no drawing status, otherwise the opposite is true.

## # options

    import { MODEL_TYPES } from "web-loading/src/utils";
    import initLoading from 'web-loading/src/loading'
    let webLoading = initLoading({
        model:MODEL_TYPES.GEAR
    })

### # Public

attribute | type | default | remarks
--- | --- | --- | ---
`html?:` | `string` | `''` | **Html ** loading method (priority is higher than custom)
`custom?:` | `typeof BaseModel or null` | `null` | Custom model (has the highest priority)
`type?:` | `LOADING_TYPES` | `LOADING_TYPES.DOM` | Start mode
`miniClass?:` | `string or null or undefined` | `mini` | Start byMINIisclass
`model?:` | `MODEL_TYPES` | `MODEL_TYPES.RING` | Model module
`text?:` | `string` | `加载中...` | Font content
`textGap?:` | `number` | `8` | Font spacing
`fontSize?:` | `number` | `12` | Font size
`fontFamily?:` | `string` | `Microsoft YaHei` | Font type
`delay?:` | `number` | `65` | Animation delay
`delayInto?:` | `number` | `520` | Turn enter/off animation delay
`optimization?:` | `boolean` | `false` | Optimization processing (not supported temporarily)
`zIndex?:` | `string` | `2001` | Loading level
`themeColor?:` | `string` | `rgba(64,158,255,1)` | Theme color
`bgColor?:` | `string` | `rgba(0, 0, 0, 0.8)` | Background color
`shadowColor?:` | `string` | `rgba(64,158,255,0.6)` | Shadow color
`shadowOffsetX?:` | `number` | `2` | Shadow X
`shadowOffsetY?:` | `number` | `2` | Shadow Y
`shadowBlur?:` | `number` | `5` | Shadow range
`pointerEvents?:` | `boolean` | `false` | Event penetration(DOMmodel)
`toast?:` | `boolean` | `true` | Whether to display a prompt

- LOADING_TYPES

attribute | enum | remarks
--- | --- | ---
DOM | `dom` | Element
FULL | `full` | Full screen
MINI | `mini` | Mobile terminal

- MODEL_TYPES

Supported models

### # model

Model configuration details

## # custom model

### # TypeScript Item Example

- custom

    import type { OptionsType, LimitType, ElementType } from "web-loading/src/types.d";
    import BaseModel from "web-loading/src/draw/model/BaseModel";
    // 1?.If options in the model need custom parameters, define options type
    interface CustomOptionsType extends OptionsType {
      size?: number;
    }
    // 2?.Customize the default parameters of the model (if you do not need to customize the options parameter, you can use OptionsType)
    // 2.1?. Define default values
    let modelDefOptions: CustomOptionsType = {
      size: 10,
    };
    // 2.2?.Size of limit value
    let limits: Array<LimitType> = [
      {
        key: "size",
        message: "key < 100",
        limit: (key) => {
          return key < 100;
        },
      },
    ];
    // 3.Custom model class
    class CustomLoading extends BaseModel<CustomOptionsType> {
      constructor(w: number, h: number, canvas: HTMLCanvasElement, options: Required<CustomOptionsType>, element: ElementType) {
       super(w, h, canvas, options, element, modelDefOptions, limits, function modelDefCall(model) {
          //BaseModel initialization success callback (you can do some special initialization operations yourself)
          //The model is CustomLoading itself. Here, the initialization default brush fill is red
          model.ctx.fillStyle = "red";
        });
        // 根据周期调用
        this.run(this.draw);
      }
      draw() {
        // Empty the canvas
        this.clearRect();
        let op = this.options;
        // Draw (get the configured custom options parameter here)
        this.ctx.fillRect(-op.size / 2, -op.size / 2, op.size, op.size);
      }
    }

> Here is a simple custom drawing of a rectangle

> - `BaseModel` is a user-defined inheritance class. If it is introduced globally, the `BaseModel` attribute is mounted in the `window`.
> - Note: `modelDefOptions`,`limits`, `modelDefCall` are not required parameters
> - Here, if the customized model does not need the `options` parameter, you can omit the 1、2 steps.

- loading

    import { LoadingType } from "web-loading/src/types.d";
    import initLoading from "web-loading/src/loading";
    let dom = document.querySelector("xxx");
    // configuration parameter
    let options: CustomOptionsType = {
      custom: CustomLoading as typeof BaseModel,
      size: 20,
    };
    let webLoading: LoadingType = initLoading(options);
    webLoading.loading(dom);

### # Native html project example

    <!DOCTYPE html>
    <html lang="en">
      <head>
        <meta charset="UTF-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <title>web-loading</title>
      </head>
      <script src="https://cdn.jsdelivr.net/npm/web-loading"></script>
      <body>
        <div id="app">
          <div class="item">
            <div>
              id:
              <span class="value">001</span>
            </div>
            <div>
              user:
              <span class="value">use1</span>
            </div>
          </div>
        </div>
        <script>
          window.onload = () => {
            // encapsulation
            let modelDefOptions = {
              size: 10
            }
            let limits = [
              {
                key: 'size',
                message: 'key < 100',
                limit: (key) => {
                  return key < 100
                }
              }
            ]
            class CustomLoading extends BaseModel {
              constructor(w, h, canvas, options, store) {
                super(w, h, canvas, options, store, modelDefOptions, function modelDefCall(model) {
                  model.ctx.fillStyle = 'red'
                })
                this.run(this.draw)
              }
              draw() {
                this.clearRect()
                let op = this.options
                this.ctx.fillRect(-op.size / 2, -op.size / 2, op.size, op.size)
              }
            }
            // loading
            let docApp = document.querySelector('#app')
            const webLoading = initLoading({
              custom: CustomLoading,
              size: 20
            })
            window.addEventListener('resize', webLoading.resize)
            webLoading.loading(docApp)
            setTimeout(() => {
              webLoading.close()
            }, 1500)
          }
        </script>
      </body>
      <style>
        #app {
          margin: 12px;
          padding: 12px;
          height: 200px;
          border: 1px solid gray;
          overflow: auto;
          border-radius: 5px;
        }
        #app .item {
          display: flex;
          flex-direction: column;
          border: 1px solid gray;
          border-radius: 5px;
          padding: 10px;
          line-height: 30px;
          margin-bottom: 6px;
          height: 60px;
        }
        #app .item .value {
          display: inline-block;
          min-width: 31px;
          min-height: 16px;
          font-weight: bold;
          color: rgb(64, 158, 255);
        }
      </style>
    </html>

### # 1、`BaseModel`parameter

> `WebLoading` will automatically inject relevant parameters when calling`custom`.

parameter | type | remarks
--- | --- | ---
`w` | `number` | Canvas Width
`h` | `number` | Canvas height
`canvas` | `HTMLCanvasElement` | Canvas element, `BaseModel` default and get the context of `2d`, but you can also get other contexts according to the canvas element
`options` | `Required<CustomOptionsType>` | `Options` is to adjust model parameters, which are divided into public parameters and model parameters, which will be merged eventually, and `Required` indicates you The parameter of is not empty (has initial value)
`element` | `ElementType` | Container element
`modelDefOptions?:` | `T` | Custom default parameters for model(optional)
`limits?:` | `Array<LimitType>` | Custom model's' options 'value restriction function (optional)
`modelDefCall?:` | `(model: BaseModel<T>) => void` | `BaseModel` initialization completion callback (optional)

### # `ElementType`

> Inherited`HTMLElement`。

attribute | type | remarks
--- | --- | ---
`loadingId` | `string or null` | Record `loading` element `id`
`$store` | `ElementStoreType` | `loding` cache content
`HTMLElement attribute...` | ... | ...

### # `ElementType.$store:ElementStoreType`

> When drawing model, you need to use some states of `WebLoading`.

attribute | type | remarks
--- | --- | ---
`options` | `OptionsType` | Save the final merged `options` parameter
`animationId` | `number or undefined` | Record `animation` status
`loadingId` | `string or null` | Record `loading` element `id`
`hookCall` | `HooksCallType` | Hook function of `loading`
`model` | `BaseModel or null` | model in use

### # `ElementType.$store.hookCall:HooksCallType`

> `WebLoading`The hook function triggered when closing.

> `HOOKSCALL_KEY`Enumeration.

attribute | enum | type | remarks
--- | --- | --- | ---
`BEFORE_COLSE` | `beforeColse` | `Function` | Before closing
`COLSED` | `colsed` | `Function` | After closing (after deleting elements)

Take `custom` as an example

    // Other codes are omitted
    class CustomLoading extends BaseModel<CustomOptionsType> {
        constructor(w: number, h: number, canvas: HTMLCanvasElement, options: Required<CustomOptionsType>, element: ElementType) {
            super(w, h, canvas, options, element);
            this.initOptions(defOptions);
            this.run(this.draw);
            this.store.hookCall.beforeColse(() => {
                console.log("Before closing");
            });
            this.store.hookCall.colsed(() => {
                console.log("After closing");
            });
        }
        draw() {
            let op = this.options;
            this.ctx.fillRect(0, 0, op.size, op.size);
        }
    }

### # `LimitType`

> Limit the range of `options` parameter values.

attribute | type | remarks
--- | --- | ---
`key` | `string` | The `options` attribute that needs to be restricted
`message` | `string` | Prompt for exceeding the limit
`limit` | `(key: any) => boolean` | Restricted operation

### # 2、`BaseModel` function

> `BaseModel`The built-in function is mainly for user extension model rendering

function | return | remarks
--- | --- | ---
`initContextCall` | `void` | initContextCall
`run` | `void` | run
`clearRect` | `void` | clearRect
`drowRadiusRect` | `void` | drowRadiusRect
`drawText` | `void` | drawText
`clearAnimationFrame` | `void` | clearAnimationFrame

### # `BaseModel:initContextCall`

> `BaseModel` Initialize the custom canvas property (triggered during inheritance).

参数 | 类型 | 备注
--- | --- | ---
`modelDefOptions?:` | `T` | Customize the default `options` value of model.
`limits?:` | `Array<LimitType>` | Customize the limit range of the `options` value of model.
`modelDefCall?:` | `BaseModel<T>` | `BaseModel` initialization completion callback.

### # `BaseModel:run`

> The `requestAnimationFrame` is delayed according to the `options.delay`.

parameter | type | remarks
--- | --- | ---
`fun` | `Function` | If it is loading before calling, the last state will be cleared.

    this.run(()=>{
        // Triggered according to options.delay
    })

### # `BaseModel:clearRect`

> Empty the canvas.

parameter | type | remarks
--- | --- | ---
`x?:` | `number` | Empty starting point X
`y?:` | `number` | Empty starting point Y
`w_r?:` | `number` | Empty end X (width), in case of circular emptying `w_ R` is radius
`h?:` | `number` | Empty end Y (height)

- Empty all

    this.clearRect()

> Considering that the drawing area may exceed the default width and height, emptying all will empty twice the width and height.

- Custom Emptying

    this.clearRect(0,0,100,100)

> Emptying starts at the coordinates of `x=0, y=0` and ends at `x=100, y=100`.

- Empty circular area

    this.clearRect(0,0,10)

> Empty the area with `x=0, y=0` and radius of `10`.

### # `BaseModel:drowRadiusRect`

> Draw a rectangle with rounded corners.

parameter | type | remarks
--- | --- | ---
`x` | `number` | Start X
`y` | `number` | Start Y
`w` | `number` | End X (width)
`h` | `number` | End Y (height)

    this.drowRadiusRect(0, 0, 100, 100, 10)
    // Need to draw by yourself
    this.ctx.fill()

> Draw a rectangle with `x=0, y=0` width and height of `100` and rounded corners of `10`.

### # `BaseModel:drawText`

> Draw default text.

parameter | type | remarks
--- | --- | ---
`params?:` | `DrawTextParamsType` | Draw text parameters

### # `BaseModel:drawText.DrawTextParamsType`

parameter | type | default | remarks
--- | --- | --- | ---
`esGap` | `number` | `0` | Extra text gap (textGap+fontSize)
`x` | `number` | `0` | X-axis
`text` | `string` | `加载中...` | text
`textColor` | `string` | `rgba(64,158,255,1)` | text color

    this.drawText()

### # `BaseModel:clearAnimationFrame`

> Empty (stop)`requestAnimationFrame`。

parameter | type | remarks
--- | --- | ---
`id` | `number` | `animationId`

    this.clearAnimationFrame(element.$store.animationId)

> The ID passed in is `id` returned by `requestAnimationFrame` , and `WebLoading` has been saved in the store.

### # 3、`BaseModel` technique

### # Dynamic options

> Whether it is initialization or in the `run` function, modifying `options` is real-time and dynamic, which can control the delay time triggered by`requestAnimationFrame`to be irregular.

    this.run(()=>{
        // Dynamic modification of delay will affect the trigger of run function
        this.options.delay = 10
    })

## # Html configuration method

> Add html configuration to `options`, which has priority over model and `custom`.

### # initialization

    import initLoading from 'web-loading/src/loading'
    let webLoading = initLoading({
        html:`<div class="spinner">
        <svg viewBox="25 25 50 50" class="circular">
            <circle stroke-miterlimit="10" stroke-width="3" fill="none" r="20" cy="50" cx="50" class="path"></circle>
        </svg>
    </div>`
    })

> Html priority is higher than custom.

### # Css animation

    .spinner {
      --red: #d62d20;
      --blue: #0057e7;
      --green: #008744;
      --yellow: #ffa700;
      position: relative;
      width: 60px;
    }

    .spinner:before {
      content: "";
      display: block;
      padding-top: 100%;
    }

    .circular {
      animation: rotate73451 2s linear infinite;
      height: 100%;
      transform-origin: center center;
      width: 100%;
      position: absolute;
      top: 0;
      bottom: 0;
      left: 0;
      right: 0;
      margin: auto;
    }

    .path {
      stroke-dasharray: 1, 200;
      stroke-dashoffset: 0;
      animation: dash0175 1.5s ease-in-out infinite, color7123 6s ease-in-out infinite;
      stroke-linecap: round;
    }

    @keyframes rotate73451 {
      100% {
        transform: rotate(360deg);
      }
    }

    @keyframes dash0175 {
      0% {
        stroke-dasharray: 1, 200;
        stroke-dashoffset: 0;
      }

      50% {
        stroke-dasharray: 89, 200;
        stroke-dashoffset: -35px;
      }

      100% {
        stroke-dasharray: 89, 200;
        stroke-dashoffset: -124px;
      }
    }

    @keyframes color7123 {
      100%, 0% {
        stroke: var(--red);
      }

      40% {
        stroke: var(--blue);
      }

      66% {
        stroke: var(--green);
      }

      80%, 90% {
        stroke: var(--yellow);
      }
    }

> The class naming should try to isolate external elements.