Small knowledge, big challenge! This article is participating in the creation activity of “Essential Tips for Programmers”.

This article also participated in the “Digitalstar Project” to win a creative gift package and creative incentive money

preface

I continue to build the big data visualization platform. Last time, I talked about the design scheme of the overall project. If you are interested, you can go to have a look.

  1. Building big Data Visualization Platform (Part I — Visualization Platform Scheme)

This article I want to tell you how to build an editor kernel, which I think is one of the key points and also one of the difficulties in this project, so I liver the code for several days, and finally build it, hair is almost gone, so today I will make a summary.

First to give you a look at the general effect, although the interface is a little ugly, but the early stage is a step by step up, I hope you can support more support.

Give you a list of needs to achieve what functions! And then I’ll show you how to step on the hole.

  1. Module components that can be dragged and customized to stretch
  2. Drag-and-drop module components support display guides and alignment lines
  3. Scale lines for the horizontal and vertical axes
  4. An auxiliary line on a scale line of a ruler
  5. Freely scalable canvas

1. Draggable module components

Visual platforms must allow users to drag and drop modules to locate and set their size and other configuration information. I’ve been thinking about this step for a long time, and I’ve read a lot of similar articles.

1.1 Falling into the abyss for the first time

I started with vue-Draggable, which is the same plugin I used before. Here is the basic usage:

/ / installation
npm i vuedraggable -S 

<template>
  <vuedraggable class="wrapper" v-model="list">
    <transition-group>
      <div v-for="item in list" :key="item" class="item">
        <p>{{item}}</p>
      </div>
    </transition-group>
  </vuedraggable>
</template>

<script>
import vuedraggable from 'vuedraggable';

export default {
  name: 'HelloWorld',
  components: {vuedraggable},
  props: {
  },
  data() {
    return {
      list: [1.2.34.4.54.5]
    }
  },
  updated() {
    console.log(this.list)
  },
  methods: {
  }
}
</script>
<style scoped>
.wrapper {
  display: flex;
  justify-content: center;
  width: 100%;
}
.item{
  width: 300px;
  height: 50px;
  background-color: #42b983;
  color: #ffffff;
}
</style>

Copy the code

Vue-draggable can basically meet the drag-and-drop function, but we found that in order to expand the functions of custom stretch size, guide line and alignment line, vue-Draggable can not meet our needs. Therefore, it is recommended not to use vue-Draggable, which generally uses simple scenarios such as drag-and-drop sorting and drag-and-drop cloning.

1.2 The second time nearly perfect

Here’s how to use vue-Draggable resizable, which supports drag and drop and custom stretch size:

/ / installation
npm install -S vue-draggable-resizable

<template>
<div class="bi-canvas-panel" :style="boxStyle">
    <vue-draggable-resizable 
    v-for="(item, index) in modules" 
    :key="index" 
    :x="item.x"
    :y="item.y" 
    :z="item.z" 
    :w="item.width" 
    :h="item.height"
    @deactivated="onDeactivated"
    @activated="onActivated"
    @dragging="onDrag" 
    @resizing="onResize" 
    :parent="true">
        <p>
        Hello! I'm a flexible cobi-mponent. You can drag me around and you can resize me.<br>
            X: {{ item.x }} / Y: {{ item.y }} - Width: {{ item.width }} / Height: {{ item.height
            }}</p>
    </vue-draggable-resizable>
</div>
</template>

<script>
import VueDraggableResizable from 'vue-draggable-resizable'
import 'vue-draggable-resizable/dist/VueDraggableResizable.css'

export default {
  name: "HelloWorld",
  data: function() {
    return {
        // Component Module information
        modules: [
          {
            // Basic attributes (width, height, horizontal position, vertical position, level)
            width: 500,
            height: 300,
            x: 0,
            y: 0,
            z: 0
          },
          {
            // Basic attributes
            width: 500,
            height: 300,
            x: 0,
            y: 0,
            z: 0
          }
        ],
        activeIndex: null
    };
  },
  methods: {
    // Modify the module size change callback function
    onResize: function (x, y, width, height) {
      const item = this.modules[this.activeIndex]
      item.x = x
      item.y = y
      item.width = width
      item.height = height
    },
    // Drag the module position change callback function
    onDrag: function (x, y) {
      const item = this.modules[this.activeIndex]
      item.x = x
      item.y = y
    },
    // Touch or click select
    onActivated (index) {
      this.activeIndex = index
    },
    // Good touch or click
    onDeactivated () {
      this.activeIndex = null}}}; </script> <style scoped>.wrapper {
  display: flex;
  justify-content: center;
  width: 100%;
}
.item{
  width: 300px;
  height: 50px;
  background-color: #42b983;
  color: #ffffff;
}
</style>
Copy the code

Let me show you the finished effect :(the picture is a little fuzzy, maybe it is the problem of the recording tool, if you have a good recording tool, you can recommend it to me, writing blog is really difficult)

After completing the drag and drop function and custom stretch function (don’t ask me why I don’t write it myself, it’s not that I can’t write it myself, it may take more time to write it myself, why not use that time to brush the nuggets article 😁😁), then I’m ready to implement the reference line and alignment line.

2 Realize the function of dragging the reference line and alignment line of the module

2.1 Implement the reference line function of drag and drop module

The plugin already provides the values of x and y coordinates, so we can use them directly. Create an outer layer of the same size as the parent. Create two built-in guides (x and Y) using relative positioning in the upper left corner of the outer layer.

<template>
<div class="bi-canvas-panel" :style="boxStyle">
    <vue-draggable-resizable 
    v-for="(item, index) in modules" 
    :key="index" 
    :x="item.x"
    :y="item.y" 
    :z="item.z" 
    :w="item.width" 
    :h="item.height"
    @deactivated="onDeactivated"
    @activated="onActivated"
    @dragging="onDrag" 
    @resizing="onResize" 
    :parent="true">
    <div class="bi-nav-line" v-show="activeIndex == index && auxiliaryFn.isReferenceLine">
        <div class="bi-nav-line-top" :style="{height: (item.y + 1000) + 'px'}"></div>
        <div class="bi-nav-line-left" :style="{width: (item.x + 1000) + 'px'}"></div>
        <div class="bi-nav-line-account">{{ item.x}}, {{ item.y}}</div>
    </div>
        <p>
        Hello! I'm a flexible cobi-mponent. You can drag me around and you can resize me.<br>
            X: {{ item.x }} / Y: {{ item.y }} - Width: {{ item.width }} / Height: {{ item.height
            }}</p>
    </vue-draggable-resizable>
</div>
</template>
Copy the code

Let me show you the finished effect :(the picture is a little fuzzy, maybe it is the problem of the recording tool, if you have a good recording tool, you can recommend it to me, writing blog is really difficult)

2.1 Realize the function of dragging and dragging the alignment line of the module

It is also very simple to realize the alignment line. There are corresponding examples on the official website of vue-Draggable – Resizable, which we can use directly. Look at the following code:

<template>
<div class="bi-canvas-panel" :style="boxStyle">
    <vue-draggable-resizable 
    v-for="(item, index) in modules" 
    :key="index" 
    :x="item.x"
    :y="item.y" 
    :z="item.z" 
    :w="item.width" 
    :h="item.height"
    @deactivated="onDeactivated"
    @activated="onActivated"
    @dragging="onDrag" 
    @resizing="onResize" 
    :parent="true">
    <div class="bi-nav-line" v-show="activeIndex == index && auxiliaryFn.isReferenceLine">
        <div class="bi-nav-line-top" :style="{height: (item.y + 1000) + 'px'}"></div>
        <div class="bi-nav-line-left" :style="{width: (item.x + 1000) + 'px'}"></div>
        <div class="bi-nav-line-account">{{ item.x}}, {{ item.y}}</div>
    </div>
        <p>
        Hello! I'm a flexible cobi-mponent. You can drag me around and you can resize me.<br>
            X: {{ item.x }} / Y: {{ item.y }} - Width: {{ item.width }} / Height: {{ item.height}}</p> </vue-draggable-resizable> <! --> <spanclass="ref-line v-line"
      v-for="(item, index) in vLine"
      v-show="item.display && auxiliaryFn.isAlignmentLine"
      :key="'v-line' + index + item.position"
      :style="{ left: item.position, top: '-25%', height: '150%'}"
></span>
<span class="ref-line h-line"
      v-for="(item, index) in hLine"
      :key="'h-line' + index + item.position"
      v-show="item.display && auxiliaryFn.isAlignmentLine"
      :style="{ top: item.position, left: '-25%', width: '150%'}"
></span>
</div>
</template>
<script>
import VueDraggableResizable from 'vue-draggable-resizable'
import 'vue-draggable-resizable/dist/VueDraggableResizable.css'

export default {
  name: "HelloWorld",
  data: function() {
    return {
        vLine: [],
        hLine: []
    };
  },
  methods: {
    ` ` `
    // Auxiliary line callback event
    getRefLineParams (params) {
      const { vLine, hLine } = params
      this.vLine = vLine
      this.hLine = hLine
    }
  }
};
</script>
Copy the code

You think that’s all it takes?

When I ran it, I found that the alignment line did not take effect, which left me confused. After checking the official website and my code, I found that there was no problem, but how could it go wrong? At first I thought there was a version problem. I then installed other versions of the Vue-Draggable-Resizable plugin, which I tried several times but didn’t have. I wondered if there was something wrong on the official website. Found a lot of versions are said to have, was forced to view the source code, period found there is no source code this function, I crashed, how? The website says yes. I had no choice but to learn from Baidu, and I finally found the problem. Originally, vuE-Draggable – Resizable plug-in has two versions. One is vue-Draggable-resizable and the other is vue-draggable-resizable gorkys. Vue-draggable – Resizable – Gorkys has this function, but I did not upload before. The Chinese description document is also written according to the function of vue-Draggable – Resizable – Gorkys plug-in. Look at this problem for a long time, really collapse. Let me show you the effect.

Here’s a story

Vue-draggable resizable was developed by a foreign programmer named Mauricius, and then one of the programmers named Gorkys used this plug-in, Finding that the plugin didn’t satisfy both conflict detection between components (no overlap between components allowed) and alignment between components (similar to adsorption), Gorkys pulled the code locally from the Vue-Draggable – Resizable branch of mauricius’s plugin. Then I added both features and improved the documentation, and finally uploaded my own code to Github. It’s really do-it-yourself.

The addresses of these two plug-ins:

Vue – Draggable – Resizable Original component address: VUE – Draggable -resizable VUE – Draggable – Resizable Gorkys new component address: VUue – Draggable -resizable

advice

Here I suggest you to use vue-Draggable resizable Gorkys plug-in, after all, the function is relatively complete, or you can just like him, directly pull the code to change, so it is ok, ha ha ha. There is also a website address to share with you, quick start

This is where we left off in the first installment of building the editor kernel. It’s not easy to code and document at the same time. Let me know in the comments below if you think it’s bad or if you have any good suggestions, and don’t forget to use your precious fingers and click “like”. Thank you.