Location>code7788 >text

Front-end Visual Designer with Konva (18) - Material Nesting - Load Stage

Popularity:377 ℃/2024-07-23 10:22:57

This chapter focuses on implementing nesting of materials (loading phase) This means that the objects that can be dragged into the canvas are not just picture materials, but also nested pictures and graphics.

Please give me a free Star!

If you find any bugs, please feel free to raise an Issue!

github source code

gitee source code

sample address (computing)

Based on the original drop processing, add a json type material processing entrance:

// src/Render/handlers/

drop: (e: GlobalEventHandlersEventMap['drop']) => {
  // summarize
  [
    type === 'svg'
    ? `loadSvg`
    : type === 'gif'
    ? 'loadGif'
    : type === 'json'
    ? 'loadJson' // additional,deal with json Type material
    : 'loadImg'
  ](src).then((target: | ) => {
    // picture material
    if (target instanceof ) {
      // summarize
    } else {
      // json source material (in literature and art)
      (nanoid())
      ('asset')
      group = target
      (group)
    }
  })
  // summarize
}

drop The original logic is basically unchanged, the key logic is in loadJson:

// src/Render/tools/

  // load node json
  async loadJson(src: string) {
    try {
      // retrieve jsonelement
      const json = (await (await fetch(src)).text())

      // sub-material
      const assets =

      // refresh (computer window)id
      (assets)

      // Generate Blanks stage+layer
      const stageEmpty = new ({
        container: ('div')
      })
      const layerEmpty = new ()
      (layerEmpty)

      // void json radical (chemistry)
      const jsonRoot = (())
      [0].children = [json]

      // reload stage
      const stageReload = ((jsonRoot), ('div'))

      // goal group(assume (office) json Transformed nodes)
      const groupTarget = [0].children[0] as

      // free up memory
      ()
      ()
      ()

      // 深度遍历加载sub-material
      const nodes: {
        target:  | | |
        parent?:  | | |
      }[] = [{ target: groupTarget }]

      while ( > 0) {
        const item = ()
        if (item) {
          const node =
          if (node instanceof ) {
            if () {
              const n = await ()
              (false)
              ?.add(n)
              ()
            } else if () {
              const n = await ()
              (false)
              ?.add(n)
              ()
            } else if () {
              const n = await ()
              (false)
              ?.add(n)
              ()
            }
          }
          if (
            node instanceof ||
            node instanceof ||
            node instanceof
          ) {
            (
              ...().map((o) => ({
                target: o,
                parent: node
              }))
            )
          }
        }
      }

      // corresponds English -ity, -ism, -ization:点击void区域可选择
      const clickMask = new ({
        id: 'click-mask',
        width: (),
        height: ()
      })
      (clickMask)
      (1)

      return groupTarget
    } catch (e) {
      (e)
      return new ()
    }
  }

loadJson, key logic description:

1. jsonIdCover refreshes the ids inside the loaded json.

2. Borrow an empty stage to get the json structure of an empty stage (since the material json only contains the material's own structure, it needs to be supplemented with the upper level json structure)

3. Load the spliced json and get a new stage.

4. Extract the target material group from the stage of 3.

5. Load the group's internal image material.

6, insert a transparent Rect, so that it clicks on the space between the sub-asset them, but also can select the entire asset

Finally, a treatment is carried out:

// src/Render/tools/

  // deep-seated group (used form a nominal expression) id Harmonization for the top floor group (used form a nominal expression) id
  groupIdCover(group: ) {
    const groupId = ()
    const subGroups = ('.sub-asset') as []
    while ( > 0) {
      const subGroup = () as | undefined
      if (subGroup) {
        const points =
        if ((points)) {
          for (const point of points) {
             =
             = groupId
            for (const pair of ) {
               =
               = groupId
               =
               = groupId
            }
          }
        }

        (...(('.sub-asset') as []))
      }
    }
  }

The logic here is to send the new id of the top-level asset to all the points and pairs below it through breadth-first traversal, and keep the original groupId (the rawGroupId above) for future use. after the groupId is updated, the linking line algorithm ignores the pair relationship of different sub-assets under the same asset (the linking line has already been cured into a Line instance when saved as a material json). After the groupId update, when the linking line algorithm is executed, it will ignore the pair relationship of different sub-assets under the same asset, i.e., it will not duplicate the real-time linking line between different sub-assets in the same asset (the linking line has already been cured into a line instance directly when it is saved as a json, and it will follow the action of the root asset in the future, especially the transform transformation).

Next, since the internal points belonging to each sub-asset are still valid for this implementation, first, adjust the pointsVisible so that when hovering the root asset, all internal points will be visible:

// src/Render/tools/

  pointsVisible(visible: boolean, group?: ) {
    const start = group ??

    // Finding the deep points
    for (const asset of [
      ...(['asset', 'sub-asset'].includes(()) ? [start] : []),
      ...('.asset'),
      ...('.sub-asset')
    ]) {
      const points = ('points') ?? []
      ({
        points: ((o: any) => ({ ...o, visible }))
      })
    }

    // repaint
    ()
  }

Then, the key is to adjust LinkDraw:

// src/Render/draws/

override draw() {
    // summarize
  
    // All layers of material
    const groups = [
      ...(('.asset') as []),
      ...(('.sub-asset') as [])
    ]
    
    // summarize
    
    const pairs = ((ps, point) => {
      return ( ? ((o) => !) : [])
    }, [] as LinkDrawPair[])
    
    // summarize
    
    // connection line
    for (const pair of pairs) {
      // multilayer material,Need to troubleshoot internal pair treat (sb a certain way)
      // pair Nor can it be used for disabled
      if ( !== && !) {
        // summarize
      }
    }
}

1、groups The query has to be increased to include the sub-asset

2、Filter out disabled pair records

3、Filter out the pair record of the same asset

The rest of the logic, basically, remains the same.

At this point, the logic of "material nesting" has basically been realized.

The overall code has not changed much compared to the last feature release, and has little impact on the previous code.

More Stars please!

source code (computing)

gitee source code

sample address (computing)