|
@@ -27,20 +27,36 @@
|
|
|
/>
|
|
|
</div>
|
|
|
<div
|
|
|
- id="selectableArea"
|
|
|
+ class="background-img"
|
|
|
:style="{
|
|
|
width: data.image_width + 'px',
|
|
|
height: data.image_height + 'px',
|
|
|
- background: data.image_list[0]
|
|
|
- ? 'url(' + data.image_list[0].file_url + ') center / contain no-repeat'
|
|
|
- : '#DCDFE6',
|
|
|
- position: 'relative',
|
|
|
border: '1px dotted #DCDFE6',
|
|
|
- textAlign: 'center',
|
|
|
- lineHeight: data.image_height + 'px',
|
|
|
+ background: data.image_list[0] && file_url ? '' : '#DCDFE6',
|
|
|
}"
|
|
|
>
|
|
|
- {{ data.image_list[0] ? '' : '背景图' }}
|
|
|
+ <div
|
|
|
+ v-if="data.image_list[0] && file_url"
|
|
|
+ class="img-set"
|
|
|
+ :style="{ top: `${data.imgData.top - 9}px`, left: `${data.imgData.left}px` }"
|
|
|
+ >
|
|
|
+ <div class="dot top-left" @mousedown="dragStart($event, 'nwse-resize', 'top-left')"></div>
|
|
|
+ <div class="horizontal-line" @mousedown="dragStart($event, 'ns-resize', 'top')"></div>
|
|
|
+ <div class="dot top-right" @mousedown="dragStart($event, 'nesw-resize', 'top-right')"></div>
|
|
|
+ <div class="vertical-line" @mousedown="dragStart($event, 'ew-resize', 'left')"></div>
|
|
|
+ <img
|
|
|
+ :src="file_url"
|
|
|
+ draggable="false"
|
|
|
+ alt="背景图"
|
|
|
+ :style="{ width: `${data.imgData.width}px`, height: `${data.imgData.height}px` }"
|
|
|
+ @mousedown="dragStart($event, 'move', 'move')"
|
|
|
+ />
|
|
|
+ <div class="vertical-line" @mousedown="dragStart($event, 'ew-resize', 'right')"></div>
|
|
|
+ <div class="dot bottom-left" @mousedown="dragStart($event, 'nesw-resize', 'bottom-left')"></div>
|
|
|
+ <div class="horizontal-line" @mousedown="dragStart($event, 'ns-resize', 'bottom')"></div>
|
|
|
+ <div class="dot bottom-right" @mousedown="dragStart($event, 'nwse-resize', 'bottom-right')"></div>
|
|
|
+ </div>
|
|
|
+ <p v-else :style="{ lineHeight: data.image_height + 'px', textAlign: 'center' }">背景图</p>
|
|
|
</div>
|
|
|
</template>
|
|
|
</ModuleBase>
|
|
@@ -63,6 +79,7 @@ export default {
|
|
|
labelText: '背景图',
|
|
|
acceptFileType: '.jpg,.png,.jpeg',
|
|
|
iconClass: 'picture',
|
|
|
+ file_url: '',
|
|
|
};
|
|
|
},
|
|
|
watch: {
|
|
@@ -75,18 +92,55 @@ export default {
|
|
|
immediate: true,
|
|
|
},
|
|
|
},
|
|
|
+ mounted() {
|
|
|
+ document.querySelector('.background-img').addEventListener('mousemove', this.mouseMove);
|
|
|
+ document.body.addEventListener('mouseup', this.mouseUp);
|
|
|
+ },
|
|
|
+ beforeDestroy() {
|
|
|
+ document.querySelector('.background-img')?.removeEventListener('mousemove', this.mouseMove);
|
|
|
+ document.body.removeEventListener('mouseup', this.mouseUp);
|
|
|
+ },
|
|
|
methods: {
|
|
|
updateFileList({ file_list, file_id_list, file_info_list }) {
|
|
|
this.data.image_list = file_list;
|
|
|
this.data.image_id_list = file_id_list;
|
|
|
this.data.image_info_list = file_info_list;
|
|
|
this.data.file_id_list = file_id_list;
|
|
|
+ if (file_list.length > 0) {
|
|
|
+ const img = new Image();
|
|
|
+ img.src = file_list[0].file_url;
|
|
|
+ this.file_url = file_list[0].file_url;
|
|
|
+ img.onload = () => {
|
|
|
+ const { width, height } = img;
|
|
|
+
|
|
|
+ if (width > this.data.image_width || height > this.data.image_height) {
|
|
|
+ const wScale = width / this.data.image_width;
|
|
|
+ const hScale = height / this.data.image_height;
|
|
|
+ const scale = wScale > hScale ? this.data.image_width / 2 / width : this.data.image_height / 2 / height;
|
|
|
+
|
|
|
+ this.data.imgData = {
|
|
|
+ width: width * scale,
|
|
|
+ height: height * scale,
|
|
|
+ top: 0,
|
|
|
+ left: 0,
|
|
|
+ };
|
|
|
+ } else {
|
|
|
+ this.data.imgData = {
|
|
|
+ width,
|
|
|
+ height,
|
|
|
+ top: 0,
|
|
|
+ left: 0,
|
|
|
+ };
|
|
|
+ }
|
|
|
+ };
|
|
|
+ }
|
|
|
},
|
|
|
|
|
|
handleData() {
|
|
|
this.data.image_list.forEach((item) => {
|
|
|
GetFileURLMap({ file_id_list: [item.file_id] }).then(({ url_map }) => {
|
|
|
- this.$set(item, 'file_url', url_map[item.file_id]);
|
|
|
+ this.file_url = url_map[item.file_id];
|
|
|
+ // this.$set(item, 'file_url', url_map[item.file_id]);
|
|
|
});
|
|
|
});
|
|
|
this.handleMindMap();
|
|
@@ -102,6 +156,127 @@ export default {
|
|
|
});
|
|
|
this.data.mind_map.node_list = node_list;
|
|
|
},
|
|
|
+ /**
|
|
|
+ * 拖拽开始
|
|
|
+ * @param {MouseEvent} event
|
|
|
+ * @param {string} cursor
|
|
|
+ * @param {string} type
|
|
|
+ */
|
|
|
+ dragStart(event, cursor, type) {
|
|
|
+ const { clientX, clientY } = event;
|
|
|
+ this.data.drag = {
|
|
|
+ dragging: true,
|
|
|
+ startX: clientX,
|
|
|
+ startY: clientY,
|
|
|
+ type,
|
|
|
+ };
|
|
|
+
|
|
|
+ document.querySelector('.background-img').style.cursor = cursor;
|
|
|
+ },
|
|
|
+ /**
|
|
|
+ * 鼠标移动
|
|
|
+ * @param {MouseEvent} event
|
|
|
+ */
|
|
|
+ mouseMove(event) {
|
|
|
+ if (!this.data.drag.dragging) return;
|
|
|
+ const { clientX, clientY } = event;
|
|
|
+ const { startX, startY, type } = this.data.drag;
|
|
|
+
|
|
|
+ const widthDiff = clientX - startX;
|
|
|
+ const heightDiff = clientY - startY;
|
|
|
+
|
|
|
+ if (type === 'top-left') {
|
|
|
+ this.data.imgData.width = Math.min(this.data.image_width, Math.max(0, this.data.imgData.width - widthDiff));
|
|
|
+ this.data.imgData.height = Math.min(this.data.image_height, Math.max(0, this.data.imgData.height - heightDiff));
|
|
|
+ this.data.imgData.top = Math.min(
|
|
|
+ this.data.image_height - this.data.imgData.height,
|
|
|
+ Math.max(0, this.data.imgData.top + heightDiff),
|
|
|
+ );
|
|
|
+ this.data.imgData.left = Math.min(
|
|
|
+ this.data.image_width - this.data.imgData.width,
|
|
|
+ Math.max(0, this.data.imgData.left + widthDiff),
|
|
|
+ );
|
|
|
+ } else if (type === 'top-right') {
|
|
|
+ this.data.imgData.width = Math.min(this.data.image_width, Math.max(this.data.imgData.width + widthDiff));
|
|
|
+ this.data.imgData.height = Math.min(this.data.image_height, Math.max(0, this.data.imgData.height - heightDiff));
|
|
|
+ this.data.imgData.top = Math.min(
|
|
|
+ this.data.image_height - this.data.imgData.height,
|
|
|
+ Math.max(0, this.data.imgData.top + heightDiff),
|
|
|
+ );
|
|
|
+ this.data.imgData.left = Math.min(
|
|
|
+ this.data.image_width - this.data.imgData.width,
|
|
|
+ Math.max(0, this.data.imgData.left),
|
|
|
+ );
|
|
|
+ } else if (type === 'bottom-left') {
|
|
|
+ this.data.imgData.width = Math.min(this.data.image_width, Math.max(0, this.data.imgData.width - widthDiff));
|
|
|
+ this.data.imgData.height = Math.min(this.data.image_height, Math.max(this.data.imgData.height + heightDiff));
|
|
|
+ this.data.imgData.top = Math.min(
|
|
|
+ this.data.image_height - this.data.imgData.height,
|
|
|
+ Math.max(0, this.data.imgData.top),
|
|
|
+ );
|
|
|
+ this.data.imgData.left = Math.min(
|
|
|
+ this.data.image_width - this.data.imgData.width,
|
|
|
+ Math.max(0, this.data.imgData.left + widthDiff),
|
|
|
+ );
|
|
|
+ } else if (type === 'bottom-right') {
|
|
|
+ this.data.imgData.width = Math.min(this.data.image_width, Math.max(this.data.imgData.width + widthDiff));
|
|
|
+ this.data.imgData.height = Math.min(this.data.image_height, Math.max(this.data.imgData.height + heightDiff));
|
|
|
+ this.data.imgData.top = Math.min(
|
|
|
+ this.data.image_height - this.data.imgData.height,
|
|
|
+ Math.max(0, this.data.imgData.top),
|
|
|
+ );
|
|
|
+ this.data.imgData.left = Math.min(
|
|
|
+ this.data.image_width - this.data.imgData.width,
|
|
|
+ Math.max(0, this.data.imgData.left),
|
|
|
+ );
|
|
|
+ }
|
|
|
+
|
|
|
+ if (type === 'top') {
|
|
|
+ this.data.imgData.height = Math.min(this.data.image_height, Math.max(0, this.data.imgData.height - heightDiff));
|
|
|
+ this.data.imgData.top = Math.min(
|
|
|
+ this.data.image_height - this.data.imgData.height,
|
|
|
+ Math.max(0, this.data.imgData.top + heightDiff),
|
|
|
+ );
|
|
|
+ } else if (type === 'bottom') {
|
|
|
+ this.data.imgData.height = Math.min(this.data.image_height, Math.max(this.data.imgData.height + heightDiff));
|
|
|
+ this.data.imgData.top = Math.min(
|
|
|
+ this.data.image_height - this.data.imgData.height,
|
|
|
+ Math.max(0, this.data.imgData.top),
|
|
|
+ );
|
|
|
+ } else if (type === 'left') {
|
|
|
+ this.data.imgData.width = Math.min(this.data.image_width, Math.max(this.data.imgData.width - widthDiff));
|
|
|
+ this.data.imgData.left = Math.min(
|
|
|
+ this.data.image_width - this.data.imgData.width,
|
|
|
+ Math.max(0, this.data.imgData.left + widthDiff),
|
|
|
+ );
|
|
|
+ } else if (type === 'right') {
|
|
|
+ this.data.imgData.width = Math.min(this.data.image_width, Math.max(this.data.imgData.width + widthDiff));
|
|
|
+ this.data.imgData.left = Math.min(
|
|
|
+ this.data.image_width - this.data.imgData.width,
|
|
|
+ Math.max(0, this.data.imgData.left),
|
|
|
+ );
|
|
|
+ }
|
|
|
+
|
|
|
+ if (type === 'move') {
|
|
|
+ this.data.imgData.top = Math.min(
|
|
|
+ this.data.image_height - this.data.imgData.height,
|
|
|
+ Math.max(0, this.data.imgData.top + heightDiff),
|
|
|
+ );
|
|
|
+ this.data.imgData.left = Math.min(
|
|
|
+ this.data.image_width - this.data.imgData.width,
|
|
|
+ Math.max(0, this.data.imgData.left + widthDiff),
|
|
|
+ );
|
|
|
+ }
|
|
|
+ this.data.drag.startX = clientX;
|
|
|
+ this.data.drag.startY = clientY;
|
|
|
+ },
|
|
|
+ /**
|
|
|
+ * 鼠标抬起
|
|
|
+ */
|
|
|
+ mouseUp() {
|
|
|
+ this.data.drag.dragging = false;
|
|
|
+ document.querySelector('.background-img').style.cursor = 'auto';
|
|
|
+ },
|
|
|
},
|
|
|
};
|
|
|
</script>
|
|
@@ -141,4 +316,79 @@ export default {
|
|
|
align-items: center;
|
|
|
padding: 20px 0;
|
|
|
}
|
|
|
+
|
|
|
+.background-img {
|
|
|
+ height: 310px;
|
|
|
+ border: 1px dashed rgba(0, 0, 0, 8%);
|
|
|
+
|
|
|
+ .img-set {
|
|
|
+ position: relative;
|
|
|
+ display: inline-grid;
|
|
|
+ grid-template:
|
|
|
+ ' . . . ' 2px
|
|
|
+ ' . img . ' auto
|
|
|
+ ' . . . ' 2px
|
|
|
+ / 2px auto 2px;
|
|
|
+
|
|
|
+ img {
|
|
|
+ object-fit: cover;
|
|
|
+ }
|
|
|
+
|
|
|
+ .horizontal-line,
|
|
|
+ .vertical-line {
|
|
|
+ background-color: $main-color;
|
|
|
+ }
|
|
|
+
|
|
|
+ .horizontal-line {
|
|
|
+ width: 100%;
|
|
|
+ height: 2px;
|
|
|
+ cursor: ns-resize;
|
|
|
+ }
|
|
|
+
|
|
|
+ .vertical-line {
|
|
|
+ width: 2px;
|
|
|
+ height: 100%;
|
|
|
+ cursor: ew-resize;
|
|
|
+ }
|
|
|
+
|
|
|
+ .dot {
|
|
|
+ z-index: 1;
|
|
|
+ width: 6px;
|
|
|
+ height: 6px;
|
|
|
+ background-color: $main-color;
|
|
|
+
|
|
|
+ &.top-left {
|
|
|
+ top: -2px;
|
|
|
+ left: -2px;
|
|
|
+ }
|
|
|
+
|
|
|
+ &.top-right {
|
|
|
+ top: -2px;
|
|
|
+ right: 2px;
|
|
|
+ }
|
|
|
+
|
|
|
+ &.bottom-left {
|
|
|
+ bottom: 2px;
|
|
|
+ left: -2px;
|
|
|
+ }
|
|
|
+
|
|
|
+ &.bottom-right {
|
|
|
+ right: 2px;
|
|
|
+ bottom: 2px;
|
|
|
+ }
|
|
|
+
|
|
|
+ &.top-left,
|
|
|
+ &.bottom-right {
|
|
|
+ position: relative;
|
|
|
+ cursor: nwse-resize;
|
|
|
+ }
|
|
|
+
|
|
|
+ &.top-right,
|
|
|
+ &.bottom-left {
|
|
|
+ position: relative;
|
|
|
+ cursor: nesw-resize;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
</style>
|