Component effect:
Source code:
Create a new file named MiddleMoveLine.vue
and introduce the declaration where it is used.
<template> <!-- Re-optimized the overall implementation logic...one disk is divided into two parts, A/B--- You need to first understand the positioning layout [child absolute parent phase] --- child absolute positioning / parent relative positioning (the most commonly used combination) before you can understand the layout in this component In addition, z-index can only be set for positioned elements---not setting it is similar to stacking behavior. Those written first are suppressed below. usage: just nest <MiddleMoveLine :safe-distance="[50,50]" :percent-a="30"> <template v-slot:paneA> <div style="background-color: #5ee012;width: 100%;height: 100%;font-size: 50px">I am the first panA</div> </template> <template v-slot:paneB> <MiddleMoveLine direction="y" :safe-distance="[50,50]" :percent-a="60"> <template v-slot:paneA> <div style="background-color: #c512e0;width: 100%;height: 100%;font-size: 50px">I am the second panA</div> </template> <template v-slot:paneB> <div style="background-color: #c70b2c;width: 100%;height: 100%;font-size: 50px">I am the second panB</div> </template> </MiddleMoveLine> </template> </MiddleMoveLine> --> <div class="line-pane-view" :class="{cursor}" ref="line-pane" @mouseup="mouseUp" @mousemove="mouseMove"> <div :class="[direction==='x'?'pane-ax':'pane-ay']" :style="paneABstyle[0]"> <slot name="paneA"></slot> </div> <div class="middle-line active" ref="mouse-ctrl" :style="middleLineStyle" :class="[direction==='x'?'middle-line-x':'middle-line-y']" @mousedown="mouseD"> </div> <div :class="[direction==='x'?'pane-bx':'pane-by']" :style="paneABstyle[1]"> <slot :style="{'z-index':zIndex}" name="paneB"></slot> </div> </div> </template> <script> export default {<!-- --> name: "MiddleMoveLine", props: {<!-- -->//Data passed by the parent component direction: {<!-- -->// Describes the direction and appearance of the dividing center line default: 'x' // x--the center line is divided into two parts A and B in the x direction on the x axis, that is, in the left and right directions. }, safeDistance: {<!-- --> default: function () {<!-- --> return [30, 40]//A’s safety distance is 30px, B’s safety distance is 40px } }, zIndex: {<!-- -->// The level of the second element. Because the second element often suppresses the first one, you may need to add this to change the level. default: 1 }, percentA: {<!-- --> default: 55//A accounts for 55%, B accounts for 45% = 1 - 50% }, }, data() {<!-- --> return {<!-- --> active: false, percentX: 20,// 20% midline x percentY: 10,// Used when the center line is y mouseX: 0,//The position of the mouse in line-pane-view coordinates mouseY: 0, parentWidth: 0,//The width and height of the parent element line-pane-view parentHeight: 0 }; }, mounted() {<!-- --> this.percentX = this.percentA this.percentY = 100 - this.percentA }, computed: {<!-- --> paneABstyle() {<!-- -->// Change the length and width of A and B through styles // x--The center line is divided in the left and right directions. At this time, A and B are related to each other. When moving the center line, the width of A and B should be changed. const x = this.percentX; const y = this.percentY; if (this.direction === 'x') {<!-- -->// Return the styles of A and B at the same time return [{<!-- -->['width']: x + '%'}, {<!-- -->['width']: 100 - x + '%'}] } else {<!-- --> return [{<!-- -->['height']: y + '%'}, {<!-- -->['height']: 100 - y + '%'},] } }, middleLineStyle() {<!-- -->//The middle line also needs to be changed synchronously const left = this.percentX const top = this.percentY if (this.direction === 'x') {<!-- --> return {<!-- -->['left']: left + "%"} } else {<!-- --> return {<!-- -->['top']: top + "%"} } }, cursor() {<!-- -->// Set the mouse dragging style according to whether it is activated or not return this.active ? (this.direction === 'x' ? 'row-resize' : 'col-resize') : '' }, }, methods: {<!-- --> mouseMove(e) {<!-- --> // The mouse is not pressed or not triggered if (e.buttons === 0 || e.which === 0) {<!-- --> this.active = false } if (!this.active) return; // console.log("Mouse movement:", e,"e.currentTarget:",e.currentTarget); const parentRect = e.currentTarget.getBoundingClientRect(); let x = e.clientX - parentRect.left; let y = e.clientY - parentRect.top; const w = parentRect.width; const h = parentRect.height; const safeDistance = this.safeDistance // Judgment that Bu is within a safe distance, exception handling: x = x < safeDistance[0] ? safeDistance[0] : x x = x > (w - safeDistance[1]) ? (w - safeDistance[1]) : x y = y < safeDistance[0] ? safeDistance[0] : y y = y > (h - safeDistance[1]) ? (h - safeDistance[1]) : y this.mouseX = x this.mouseY = y this.parentWidth = w; this.parentHeight = h; console.log("Mouse movement: this.mouseX,Y", this.mouseX, this.mouseY, "this.parentWidth,H:", this.parentWidth, this.parentHeight); console.log("Mouse movement:left,top:", (this.mouseX / this.parentWidth) * 100 + "%", (this.mouseY / this.parentHeight) * 100 + "%"); this.percentX = (x / w) * 100; this.percentY = (y / h) * 100; // You can send events to the parent component so that the parent component can handle the proportion of other components to adapt this.$emit('change-view-size', {<!-- -->x, y, w, h}) }, mouseUp() {<!-- --> console.log("Mouse released---event of the entire panel"); if(this.active) this.active = false }, //Mouse events on the center line mouseD() {<!-- --> console.log("Mouse pressed"); if (!this.active) this.active = true }, }, watch: {<!-- --> // There is currently no need to dynamically change the initial proportion... // percentA(newVal, oldVal) {// The initial load in vue2 will not run (the data is not considered to have changed), and it can only run if the data is changed during operation // In vue3, it can run during initialization (see the vue3 official website for specific configuration) // // console.log("percentA has changed...", newVal, oldVal) // // this.percentX = newVal // // this.percentY = 100 - newVal // }, } } ; </script> <style scoped lang="scss"> .line-pane-view {<!-- --> width: 100%; height: 100%; position: relative; /*The son must be the same as the father---since the children are absolute, the father must be positioned to be trapped*/ user-select: none; } .middle-line {<!-- --> /* Set the positioning method of the element to absolute positioning, positioning relative to the nearest positioning context */ position: absolute; /* Set the box model to border-box, the width and height of the element include content, padding and border */ //-moz-box-sizing: border-box; /* For Firefox browser */ //-webkit-box-sizing: border-box; /* Applicable to WebKit core browsers (such as Chrome, Safari) */ box-sizing: border-box; /* Standard writing method, suitable for most modern browsers */ background-color: #0D0D0D; /* Set the opacity of the element to 0.1, with a value ranging from 0 (fully transparent) to 1 (fully opaque) */ opacity: .1; /* Set the stacking order of elements to control the display priority of elements in the stacking order */ z-index: 2; /* Set the background clipping method to padding-box, and the background is only drawn in the padding area */ -moz-background-clip: padding; /* Applicable to Firefox browser */ -webkit-background-clip: padding; /* Applicable to WebKit core browsers (such as Chrome, Safari) */ background-clip: padding-box; /* Standard writing method, suitable for most modern browsers */ } /*x--Midline left and right division */ .middle-line-x {<!-- --> width: 11px; height: 100%; margin-left: -5px; border-left: 5px solid rgba(255, 255, 255, 0); border-right: 5px solid rgba(255, 255, 255, 0); cursor: col-resize; } .middle-line-y {<!-- --> height: 11px; margin: -5px 0; border-top: 5px solid rgba(255, 255, 255, 0); border-bottom: 5px solid rgba(255, 255, 255, 0); cursor: row-resize; width: 100%; } // A represents top and left | B represents bottom and right .pane-ay {<!-- --> position: absolute; top: 0; /*top --- when the center line is y*/ width: 100%; } .pane-by {<!-- --> position: absolute; bottom: 0; /*bottom --- when the center line is y*/ width: 100%; padding-top: 3px; } .pane-ax {<!-- --> position: absolute; left: 0; /*Left --- when the center line is x*/ height: 100%; padding-right: 3px; } .pane-bx {<!-- --> position: absolute; right: 0; /*right --- when the center line is x*/ height: 100%; padding-left: 3px; } .active:hover {<!-- --> background-color: mediumvioletred; } .middle-move-line.active {<!-- --> background-color: #575555; } </style>